实现包含快速检索的ListView
-
1.案例演示:
案例演示.gif -
2.实现逻辑:
- 1.界面分为ListView和自定义QuickIndexBar;
2.右边自定义QuickIndexBar,并获取到被点击的字母,点击字母变色;
x和y坐标演示图.png
绘制文本X坐标:设置为以底部为中心点后,x坐标为控件宽度的一半;
绘制文本Y坐标:格子高度的一半+文本高度的一半+索引*格子高度;
计算触摸点对应的字母:根据触摸点的y坐标除以格子高度,得到的值就是字母对应的索引值;
点击字母变色:每一次点击颜色会改变,因此每一次点击都要重绘文本,并设置paint.setColor();
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //参数效果为:抗锯齿
mPaint.setTextSize(18);
mPaint.setColor(Color.WHITE);
//以底部中心为起点:
mPaint.setTextAlign(Paint.Align.CENTER);
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float width=mWidth/2;
for (int i=0;i<indexArr.length;i++){
//格子高度的一半+文本高度的一半+索引*格子高度
float height=cellHeight/2+getTextHeight(indexArr[i])/2+i*cellHeight;
canvas.drawText(indexArr[i],width,height,mPaint);
}
}
//平均每个格子的高度:
cellHeight=getMeasuredHeight()*1f/indexArr.length;
//获取文本高度:
private int getTextHeight(String text){
//第二个参数:start:text起始数量
//第三个参数:end:text的最终数量
Rect rect=new Rect();
mPaint.getTextBounds(text,0,text.length(),rect);
return rect.height();
}
- 3.左边为ListView或者RecyclerView,根据当前的被触摸的字母去找与自己列表相同的首字母的那个item,然后放到顶部setSelection(int i);
mQuickIndexBar.setQuickIndexBarListener(new QuickIndexBar.QuickIndexBarListener() {
@Override
public void getLetter(String letter) {
Log.d(TAG, "getLetter: "+letter);
for (int i=0;i<friends.size();i++){
String firstLetter=friends.get(i).getPinyin().charAt(0)+"";
Log.d(TAG, "getLetter: "+firstLetter);
if (letter.equals(firstLetter)){
mListView.setSelection(i);
break;
}
}
}
});
- 4.需要用到获取的汉字的拼音
public class PinYinUtils {
public static String getPinYin(String chinese){
String pinyin ="";
if (TextUtils.isEmpty(chinese)) return null;
HanyuPinyinOutputFormat hanyuPinyinOutputFormat=new HanyuPinyinOutputFormat();
//设置转换为大写
hanyuPinyinOutputFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
//设置音调为无音调
hanyuPinyinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
//由于只能单个转换,因此将字符串转换为字符数组
char[] charArray = chinese.toCharArray();
for (int i=0;i<charArray.length;i++){
//过滤空格
if (Character.isWhitespace(charArray[i])) continue;
//需要判断是否是汉字:
//一个汉字占2个字节,一个字节范围是-127~127,只要该字符大于127就认为可能是汉字;
if (charArray[i]>127){
//可能是汉字
try {
String[] pinyinStringArray = PinyinHelper.toHanyuPinyinStringArray(charArray[i], hanyuPinyinOutputFormat);
if (pinyinStringArray!=null){
pinyin+=pinyinStringArray[i];
}else {
//说明未获取到
}
} catch (Exception e) {
e.printStackTrace();
}
}else{
//一定不是汉字,可能是符号之类的,因此将此字符拼接
pinyin+=charArray[i];
}
}
return pinyin;
}
}
- 5.ListView根据拼音首字母合并:比较上一个item的letter和本次item的letter如果一样则隐藏本次的item的letter
String currentLetter=friend.getPinyin().charAt(0)+"";
if (position>0){
String lastLetter=getItem(position-1).getPinyin().charAt(0)+"";
if (lastLetter.equals(friend.getPinyin().charAt(0)+"")){
//上一个item的letter和本次item的letter一样,则隐藏本次的item的letter:
viewHolder.letter.setVisibility(View.GONE);
}else {
//由于复用,要将所需要的显示出
viewHolder.letter.setVisibility(View.VISIBLE);
}
}else{
viewHolder.letter.setVisibility(View.VISIBLE);
}
viewHolder.letter.setText(currentLetter);
viewHolder.name.setText(friend.getName());
- 3.附上GitHub完整源码:
https://github.com/393633905/QuickIndex
网友评论