当前位置: 移动技术网 > 移动技术>移动开发>Android > Android 实现带字母索引的侧边栏功能

Android 实现带字母索引的侧边栏功能

2019年07月24日  | 移动技术网移动技术  | 我要评论

之前已经用自定义view做出如下这样一个效果了

这里写图片描述

这两天需要重新拿来使用,发现效果虽然做出来了,不过思路不太对,就重新参考写了一个,用法也更为简单了

首要的自然是需要继承view绘制出侧边栏,并向外提供一个监听字母索引变化的方法

/**
 * 作者:叶应是叶
 * 时间:2017/8/20 11:38
 * 描述:
 */
public class letterindexview extends view {
 public interface ontouchingletterchangedlistener {
  void onhit(string letter);
  void oncancel();
 }
 private ontouchingletterchangedlistener touchingletterchangedlistener;
 private paint paint;
 private boolean hit;
 private final string[] letters = {"↑", "a", "b", "c", "d", "e", "f", "g", "h",
   "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
   "v", "w", "x", "y", "z", "#"};
 private final int default_width;
 public letterindexview(context context) {
  this(context, null);
 }
 public letterindexview(context context, @nullable attributeset attrs) {
  this(context, attrs, 0);
 }
 public letterindexview(context context, @nullable attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  paint = new paint();
  paint.setantialias(true);
  paint.settextalign(paint.align.center);
  paint.setcolor(color.parsecolor("#565656"));
  default_width = dptopx(context, 24);
 }
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  setmeasureddimension(getwidthsize(widthmeasurespec), getdefaultsize(getsuggestedminimumheight(), heightmeasurespec));
 }
 private int getwidthsize(int widthmeasurespec) {
  int widthmode = measurespec.getmode(widthmeasurespec);
  int widthsize = measurespec.getsize(widthmeasurespec);
  switch (widthmode) {
   case measurespec.at_most: {
    if (widthsize >= default_width) {
     return default_width;
    } else {
     return widthsize;
    }
   }
   case measurespec.exactly: {
    return widthsize;
   }
   case measurespec.unspecified:
   default:
    return default_width;
  }
 }
 @override
 public boolean dispatchtouchevent(motionevent event) {
  switch (event.getaction()) {
   case motionevent.action_down:
    hit = true;
    onhit(event.gety());
    break;
   case motionevent.action_move:
    onhit(event.gety());
    break;
   case motionevent.action_up:
   case motionevent.action_cancel:
    hit = false;
    if (touchingletterchangedlistener != null) {
     touchingletterchangedlistener.oncancel();
    }
    break;
  }
  invalidate();
  return true;
 }
 @override
 protected void ondraw(canvas canvas) {
  if (hit) {
   //字母索引条背景色
   canvas.drawcolor(color.parsecolor("#bababa"));
  }
  float letterheight = ((float) getheight()) / letters.length;
  float width = getwidth();
  float textsize = letterheight * 5 / 7;
  paint.settextsize(textsize);
  for (int i = 0; i < letters.length; i++) {
   canvas.drawtext(letters[i], width / 2, letterheight * i + textsize, paint);
  }
 }
 private void onhit(float offset) {
  if (hit && touchingletterchangedlistener != null) {
   int index = (int) (offset / getheight() * letters.length);
   index = math.max(index, 0);
   index = math.min(index, letters.length - 1);
   touchingletterchangedlistener.onhit(letters[index]);
  }
 }
 public void setontouchingletterchangedlistener(ontouchingletterchangedlistener ontouchingletterchangedlistener) {
  this.touchingletterchangedlistener = ontouchingletterchangedlistener;
 }
 private int dptopx(context context, float dpvalue) {
  float scale = context.getresources().getdisplaymetrics().density;
  return (int) (dpvalue * scale + 0.5f);
 }
}

在侧边栏时,中间会显示当前滑动指向的字母,这其实是一个textview,在主布局文件中添加,通过indexcontrol来控制textview的可见性,并指示listview滑动到指定项

/**
 * 作者:叶应是叶
 * 时间:2017/8/20 11:39
 * 描述:
 */
public class indexcontrol {
 private final listview listview;
 private final textview tv_hint;
 private final map<string, integer> lettermap;
 public indexcontrol(listview contactslistview, letterindexview letterindexview,
      textview tv_hint, map<string, integer> lettermap) {
  this.listview = contactslistview;
  this.tv_hint = tv_hint;
  this.lettermap = lettermap;
  letterindexview.setontouchingletterchangedlistener(new letterchangedlistener());
 }
 private class letterchangedlistener implements letterindexview.ontouchingletterchangedlistener {
  @override
  public void onhit(string letter) {
   tv_hint.setvisibility(view.visible);
   tv_hint.settext(letter);
   int index = -1;
   if ("↑".equals(letter)) {
    index = 0;
   } else if (lettermap.containskey(letter)) {
    index = lettermap.get(letter);
   }
   if (index < 0) {
    return;
   }
   index += listview.getheaderviewscount();
   if (index >= 0 && index < listview.getcount()) {
    listview.setselectionfromtop(index, 0);
   }
  }
  @override
  public void oncancel() {
   tv_hint.setvisibility(view.invisible);
  }
 }
}

这里也提供代码下载:letterindexview

总结

以上所述是小编给大家介绍的android 实现带字母索引的侧边栏功能,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网