欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-30 23:21:58
之前已经用自定义view做出如下这样一个效果了 这两天需要重新拿来使用,发现效果虽然做出来了,不过思路不太对,就重新参考写了一个,用法也更为简单了 首要的自然是需要...

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

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

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

首要的自然是需要继承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 实现带字母索引的侧边栏功能,希望对大家有所帮助