实现ListView A~Z快速索引
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);
} }
然后在布局文件中加入这个自定义的控件:
<!-- 上面的代码省略掉了--> <FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" > <ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@drawable/line3" /> <TextView
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" /> <com.folyd.tuan.view.SlideBar
android:id="@+id/slideBar"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom" />
</FrameLayout>
然后在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()方法就可实现了
}
});
实现效果如下:
不过这样子有一个小小的Bug 。360的某个APP也有这个Bug。那个APP99%也是用这种方式实现的。
请看图:
有人知道是什么Bug吗?
我的Bug是这样的:如果用户手指滑过A之后一直向上滑到,滑到切换城市的黄色标题栏(或滑过Z之后一直向下到滑划出屏幕),因为在整个FrameLayout内用户一直没有弹起手指,所以不能触发MotionEvent.ACTION_UP 这个状态,中间的TextView不能消失。可是我试了MotionEvent的其他一些状态,甚至在switch语句中后面加个default都没用,暂时不知道怎样解决这个小Bug,有知道的朋友还望多多指教。谢谢。
实现ListView A~Z快速索引的更多相关文章
- Android ListView A~Z快速索引(改进版)
上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...
- 8.快速索引、listview
实现这样的效果 布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...
- Android-自定义联系人快速索引
效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...
- 快速索引 (对View的自定义)
快速索引 (对View的自定义) 快速索引应用场景: 微信好友列表, 联系人通讯录, 应用管理, 文件管理等. 快速索引7步曲: *1. A-Z索引的绘制. * 2. 处理Touch事件. * 3. ...
- Log4net快速索引参考
官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...
- Android 快速索引(城市列表和联系人)
最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...
- 为ListView组件加上快速滑块以及修改快速滑块图像
本文转载自:http://blog.csdn.net/ouyang_peng/article/details/46919723 作者:欧阳鹏 欢迎转载,与人分享是进步的源泉! 转载请保留原文地址:h ...
- 我的Android进阶之旅------>如何为ListView组件加上快速滑块以及修改快速滑块图像
使用布局文件需要将android:fastScrollEnabled="true" ,如下代码所示: <ListView android:id="@+id/list ...
- IPFS - 可快速索引的版本化的点对点文件系统(草稿3)
摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的,而IPFS是一个单一的Bittorrent 群集 ...
随机推荐
- Reader开发(二)增加PDF阅读功能
最近任务很多很忙,所以更新博客的速度很慢. 大概上周就为Reader加了一个PDF阅读的功能,但是一直没时间写上来.昨晚找一下文件发现扩展了功能的Demo居然在文件目录下看不到任何文件,但是却显示有文 ...
- 细节!重点!易错点!--面试java基础篇(二)
今天来给大家分享一下java的重点易错点第二部分,也是各位同学面试需要准备的,欢迎大家交流指正. 1.字符串创建与存储机制:当创建一个字符串时,首先会在常量池中查找是否已经有相同的字符串被定义,其判断 ...
- html,JavaScript调用winfrom方法
---恢复内容开始--- 目的: 在动画上面添加点击事件,通过JavaScript调用winfrom方法 1.创建一个页面 using System; using System.Collections ...
- 多屏广告技术调研 & 广告基础介绍
之前做的多屏广告产品调研,并简单介绍了一些基础广告知识.见ppt:多屏广告技术调研
- JavaScript 进阶(四)解密闭包closure
闭包(closure)是什么东西 我面试前端基本都会问一个问题"请描述一下闭包".相当多的应聘者的反应都是断断续续的词,“子函数”“父函数”“变量”,支支吾吾的说不清楚.我提示说如 ...
- mysql基础:mysql列类型--时间和日期
mysql列类型--整型 http://blog.csdn.net/jk110333/article/details/9342283 mysql列类型--字符串http://blog.csdn.net ...
- FOJ 1607 Greedy division 数学题
题目地址: http://acm.fzu.edu.cn/problem.php?pid=1607 给定一个n,将n平均分成m份,问有几种方法,每种方法中找出最大的数.思路:就是求n的因子数.先将每个数 ...
- 从头学起android<AudioManager 声音编辑器.五十.>
我们用android经常使用的时候,手机的声音增大和缩小操作.在设定场景模式,它往往使用静音和振动运行,这通常是AudioManager来控制的. 今天我们就来看一下AudioManager 的使用. ...
- Codeforces 39E What Has Dirichlet Got to Do with That? 游戏+内存搜索
主题链接:点击打开链接 意甲冠军: 特定 a一箱 b球 不变n (球和箱子都不尽相同,样的物品) 设 way = 把b个球放到a个箱子中的方法数, 若way >= n则游戏结束 有2个人玩游戏. ...
- smartforms长文本处理方式
因为长文本的话不好换行,在smartforms中对于长文本的处理有两种:一种是自定义文本模板,自己定义好的文本格式,然后再使用的时候再文本类型中选择文本模板,最好是勾上如果没有文本存在怎无错误.这种方 ...