ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法。

实现步骤:

1.自定义一个名叫SlideBar 的View。

2.在布局文件中加入这个自定义的View。

3. 在Activity中处理监听事件。

接下来讲讲我是怎样实现的:

先来看SlideBar这个类:

package com.folyd.tuan.view;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Typeface;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

/**

* 自定义的View,实现ListView A~Z快速索引效果

*

* @author Folyd

*

*/

public class SlideBar extends View {

private Paint paint = new Paint();

private OnTouchLetterChangeListenner listenner;

// 是否画出背景

private boolean showBg = false;

// 选中的项

private int choose = -1;

// 准备好的A~Z的字母数组

public static 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" };

// 构造方法

public SlideBar(Context context) {

super(context);

}

public SlideBar(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

// 获取宽和高

int width = getWidth();

int height = getHeight() - 30;

// 每个字母的高度

int singleHeight = height / letters.length;

if (showBg) {

// 画出背景

canvas.drawColor(Color.parseColor("#55000000"));

}

// 画字母

for (int i = 0; i < letters.length; i++) {

paint.setColor(Color.BLACK);

// 设置字体格式

paint.setTypeface(Typeface.DEFAULT_BOLD);

paint.setAntiAlias(true);

paint.setTextSize(20f);

// 如果这一项被选中,则换一种颜色画

if (i == choose) {

paint.setColor(Color.parseColor("#F88701"));

paint.setFakeBoldText(true);

}

// 要画的字母的x,y坐标

float posX = width / 2 - paint.measureText(letters[i]) / 2;

float posY = i * singleHeight + singleHeight;

// 画出字母

canvas.drawText(letters[i], posX, posY, paint);

// 重新设置画笔

paint.reset();

}

}

/**

* 处理SlideBar的状态

*/

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

final float y = event.getY();

// 算出点击的字母的索引

final int index = (int) (y / getHeight() * letters.length);

// 保存上次点击的字母的索引到oldChoose

final int oldChoose = choose;

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

showBg = true;

if (oldChoose != index && listenner != null && index > 0

&& index < letters.length) {

choose = index;

listenner.onTouchLetterChange(event, letters[index]);

invalidate();

}

break;

case MotionEvent.ACTION_MOVE:

if (oldChoose != index && listenner != null && index > 0

&& index < letters.length) {

choose = index;

listenner.onTouchLetterChange(event, letters[index]);

invalidate();

}

break;

case MotionEvent.ACTION_UP:

default:

showBg = false;

choose = -1;

if (listenner != null && index > 0 && index < letters.length)

listenner.onTouchLetterChange(event, letters[index]);

invalidate();

break;

}

return true;

}

/**

* 回调方法,注册监听器

*

* @param listenner

*/

public void setOnTouchLetterChangeListenner(

OnTouchLetterChangeListenner listenner) {

this.listenner = listenner;

}

/**

* SlideBar 的监听器接口

*

* @author Folyd

*

*/

public interface OnTouchLetterChangeListenner {

void onTouchLetterChange(MotionEvent event, String s);

}

}

然后在布局文件中加入这个自定义的控件:

android:layout_width="match_parent"

android:layout_height="wrap_content" >

android:id="@android:id/list"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:divider="@drawable/line3" />

android:id="@+id/float_letter"

android:layout_width="80dp"

android:layout_height="80dp"

android:layout_gravity="center"

android:background="#F88701"

android:gravity="center"

android:textSize="40sp"

android:visibility="gone" />

android:id="@+id/slideBar"

android:layout_width="30dp"

android:layout_height="wrap_content"

android:layout_gravity="right|bottom" />

然后在Activity中注册监听事件:

mSlideBar

.setOnTouchLetterChangeListenner(new OnTouchLetterChangeListenner() {

@Override

public void onTouchLetterChange(MotionEvent event, String s) {

float_letter.setText(s);

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

case MotionEvent.ACTION_MOVE:

float_letter.setVisibility(View.VISIBLE);

break;

case MotionEvent.ACTION_UP:

default:

float_letter.postDelayed(new Runnable() {

@Override

public void run() {

float_letter.setVisibility(View.GONE);

}

}, 100);

break;

}

int position = array.indexOf(s);//这个array就是传给自定义Adapter的

mListView.setSelection(position);//调用ListView的setSelection()方法就可实现了

}

});

实现效果如下:

ce03d2222da6efc9b1098b0d81aa1e0a.png

ee39ac07f0675509efe5ab8bf4b376b9.png

不过这样子有一个小小的Bug 。360的某个APP也有这个Bug。

L3Byb3h5L2h0dHAvc3RhdGljLmJsb2cuY3Nkbi5uZXQveGhlZGl0b3IveGhlZGl0b3JfZW1vdC9kZWZhdWx0L3RpdHRlci5naWY=.jpg那个APP99%也是用这种方式实现的。

请看图:

6e1f6f26e9dc1fe5603bdc418db07e9f.png

有人知道是什么Bug吗?

我的Bug是这样的:如果用户手指滑过A之后一直向上滑到,滑到切换城市的黄色标题栏(或滑过Z之后一直向下到滑划出屏幕),因为在整个FrameLayout内用户一直没有弹起手指,所以不能触发MotionEvent.ACTION_UP 这个状态,中间的TextView不能消失。可是我试了MotionEvent的其他一些状态,甚至在switch语句中后面加个default都没用,暂时不知道怎样解决这个小Bug,有知道的朋友还望多多指教。谢谢。

Android ListView A~Z快速索引(改进版)

上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...

8&period;快速索引、listview

实现这样的效果 布局:

Android-自定义联系人快速索引

效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 &l ...

快速索引 &lpar;对View的自定义&rpar;

快速索引 (对View的自定义) 快速索引应用场景: 微信好友列表, 联系人通讯录, 应用管理, 文件管理等. 快速索引7步曲: *1. A-Z索引的绘制. * 2. 处理Touch事件. * 3. ...

Log4net快速索引参考

官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...

Android 快速索引(城市列表和联系人)

最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...

为ListView组件加上快速滑块以及修改快速滑块图像

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐