Android 实现带字母索引的侧边栏功能
时间:2022-07-27
本文章向大家介绍Android 实现带字母索引的侧边栏功能,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
之前已经用自定义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 实现带字母索引的侧边栏功能,希望对大家有所帮助,如果大家有任何疑问,欢迎给我留言,小编会及时回复大家的!
- go channel 通信通道
- SQl 语句(常见) 新建,删除,修改表,新增字段,修改默认值
- SQL处理表结构的基本方法整理(创建表,关联表,复制表)
- Go web之旅(路由篇)
- Golang插入排序
- Golang写的并行排序算法
- Go中调用dll示例
- python 序列化数据:pickle与json ,dumps与loads
- golang继承,和多态
- python 利用random生成验证码与MD5码加密过程
- Java内部类的继承
- Java继承类中static成员函数的重写
- Search for a range寻找上下界-Leetcode
- Basic Calculator 基本计算器-Leetcode
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 什么是TypeScript的字符串索引签名
- [初探] proxy 的优势与使用场景
- TypeScript里的interface和class以及对应的JavaScript代码
- TypeScript里的interface扩展,多继承以及对应的JavaScript代码
- TypeScript里的混合类型
- 完全图解 HTTPS
- TypeScript里的完整函数定义语法
- TypeScript里的类型为any和泛型的区别
- 乐观锁、悲观锁,这一篇就够了!
- 面向切片编程(AOP)应用的一些实际例子
- 计数计量单位KMGTPEZY【计算机】【天文】
- 不用临时的变量 优雅、高效的交换两个数方法
- SAP offline OData插件的JavaScript代码是如何调用到Android平台的Java代码的
- 一个占据SAP BSP应用占据存储空间的小工具
- 基于Golang的逃逸分析(Language Mechanics On Escape Analysis)