A-Z排序控件的实现
- 前言
最近项目需要做一个地区首字母a-z排序的效果,记录一下自己如何实现的.
先看下效果图:
- 分析
这种效果自己实现还是第一次;之前见过这种效果:
这些字母都是onDraw画上去的;只要知道每个字母的left,top,right,bottom就能知道它的具体位置,所以onMeasure方法中要确定每个单元格的宽高.文字排序可以先把汉字转换成拼音,再去比较首字母的顺序(特殊地区特殊处理,比如重庆);
具体看下是如何确定字母的位置:
于是乎,代码就出来了:
public class QuickIndexBar extends View { private OnLetterUpdateListener onLetterUpdateListener; public interface OnLetterUpdateListener{
void onLetterUpdate(String letter);
} public OnLetterUpdateListener getOnLetterUpdateListener() {
return onLetterUpdateListener;
} public void setOnLetterUpdateListener(
OnLetterUpdateListener onLetterUpdateListener) {
this.onLetterUpdateListener = onLetterUpdateListener;
}
private static final String[] LETTERS = new String[]{
"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 Paint paint; // 单元格宽度
private int cellWidth; // 单元格高度
private float cellHeight; public QuickIndexBar(Context context) {
this(context, null);
} public QuickIndexBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 创建一个抗锯齿的画笔
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 画笔文本加粗
paint.setTypeface(Typeface.DEFAULT_BOLD);
// 颜色
paint.setColor(Color.WHITE);
} @Override
protected void onDraw(Canvas canvas) { // 遍历26个英文字母, 计算坐标, 进行绘制
for (int i = 0; i < LETTERS.length; i++) {
String letter = LETTERS[i]; // 计算x坐标
float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
// 计算y坐标
Rect bounds = new Rect();
// 获取文本的矩形区域
paint.getTextBounds(letter, 0, letter.length(), bounds); float y = cellHeight * 0.5f + bounds.height() * 0.5f + i * cellHeight; // 绘制文本
canvas.drawText(letter, x, y, paint);
}
}
private int lastIndex = -1; @Override
public boolean onTouchEvent(MotionEvent event) { float y;
int currentIndex; switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取被点击到的字母索引
y = event.getY();
// 根据y值, 计算当前按下的字母位置
currentIndex = (int) (y / cellHeight);
if(currentIndex != lastIndex){
if(currentIndex >= 0 && currentIndex < LETTERS.length){
String letter = LETTERS[currentIndex];
if(onLetterUpdateListener != null){
onLetterUpdateListener.onLetterUpdate(letter);
}
System.out.println("letter: " + letter);
// 记录上一次触摸的字母
lastIndex = currentIndex;
}
} break;
case MotionEvent.ACTION_MOVE:
// 获取被点击到的字母索引
y = event.getY();
// 根据y值, 计算当前按下的字母位置
currentIndex = (int) (y / cellHeight);
if(currentIndex != lastIndex){
if(currentIndex >= 0 && currentIndex < LETTERS.length){
String letter = LETTERS[currentIndex];
if(onLetterUpdateListener != null){
onLetterUpdateListener.onLetterUpdate(letter);
}
System.out.println("letter: " + letter);
// 记录上一次触摸的字母
lastIndex = currentIndex;
}
} break;
case MotionEvent.ACTION_UP:
lastIndex = -1;
break;
default:
break;
} return true;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int mHeight = getMeasuredHeight();
cellWidth = getMeasuredWidth();
cellHeight = mHeight * 1.0f / LETTERS.length;
} }
这种竖直的简单快速索引就搞定了,此外还添加了触摸和点击的监听
- 实现
再来看下我们要的效果图那种效果是如何实现的;主要区别就是字母所在位置和触摸位置的差异,偷点懒,直接上代码了:
@Override
protected void onDraw(Canvas canvas) { // 遍历26个英文字母, 计算坐标, 进行绘制
for (int i = 0; i < LETTERS.length; i++) {
String letter = LETTERS[i]; // 计算x坐标
// float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
float y = cellHeight * 0.5f + paint.measureText(letter) * 0.5f;
// 计算y坐标
Rect bounds = new Rect();
// 获取文本的矩形区域
paint.getTextBounds(letter, 0, letter.length(), bounds); // float y = cellHeight * 0.5f + bounds.height() * 0.5f + i * cellHeight;
float x = cellWidth * 0.5f + bounds.width() * 0.5f + i * cellWidth;
// 绘制文本
canvas.drawText(letter, x, y, paint);
}
} private int lastIndex = -1; @Override
public boolean onTouchEvent(MotionEvent event) { float x;
int currentIndex; switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取被点击到的字母索引
x = event.getX();
// 根据x值, 计算当前按下的字母位置
currentIndex = (int) (x / cellWidth);
if (currentIndex != lastIndex) {
if (currentIndex >= 0 && currentIndex < LETTERS.length) {
String letter = LETTERS[currentIndex];
if (onLetterUpdateListener != null) {
onLetterUpdateListener.onLetterUpdate(letter);
}
// 记录上一次触摸的字母
lastIndex = currentIndex;
}
} break;
case MotionEvent.ACTION_MOVE:
// 获取被点击到的字母索引
x = event.getX();
// 根据y值, 计算当前按下的字母位置
currentIndex = (int) (x / cellWidth);
if (currentIndex != lastIndex) {
if (currentIndex >= 0 && currentIndex < LETTERS.length) {
String letter = LETTERS[currentIndex];
if (onLetterUpdateListener != null) {
onLetterUpdateListener.onLetterUpdate(letter);
}
// 记录上一次触摸的字母
lastIndex = currentIndex;
}
} break;
case MotionEvent.ACTION_UP:
lastIndex = -1;
break;
default:
break;
} return true;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int mWidth = getMeasuredWidth();
cellWidth = mWidth * 1.0f / LETTERS.length;
cellHeight = getMeasuredHeight();
}
可以看到主要区别就是单元格的宽度和高度相应改变了;后面会补充一张计算草图.
A-Z排序控件的实现的更多相关文章
- Android开源系列:仿网易Tab分类排序控件实现
前言 产品:网易新闻那个Tab排序好帅. 开发:哦~ 然后这个东东在几天后就出现了..... (PS:差不多一年没回来写博客了~~~~(>_<)~~~~,顺便把名字从 enjoy风铃 修改 ...
- DevExpress控件汉化类 z
更新了一些字段,VER9.3.3 using System; using DevExpress.XtraEditors.Controls; using DevExpress.XtraGrid.Loca ...
- 扩展GridView实现的一个自定义无刷新分页,排序,支持多种数据源的控件TwfGridView
最近项目View层越来越趋向于无刷新化,特别是数据展示方面,还要对Linq有很好的支持.在WebFrom模式的开发中,GridView是一个功能很强大,很常用的控件,但是他也不是完美的,没有自带的无刷 ...
- [DataTable]控件排序事件中用DataView及DataTable排序
控件排序事件中用DataView及DataTable排序 文章分类:.net编程 在做ASP.NET页面开发时,经常要用到dataset(或者DataTable),绑定到DataGrid或GridVi ...
- c++ builder TListView控件按字符串排序(根据网上代码亲测ok)
//--------------------------------------------------------------------------- /* 首先将一个列表框控件安放在Form上, ...
- DevExpress控件学习总结 z
1.Navigation & Layout 1.1 Bar Manager 如果想在窗体或用户控件(user control)上添加工具条(bars)或弹出菜单(popup menus),我们 ...
- dev中gridview控件 z
目录:一.客户端常用1.常用API2.聚焦行变更事件3.客户端选择多行4.客户端选择行5. 获取选择的行数目6.单击行时,选中行7.通过checkbox 选择行8.选择所有行9.启动编辑框,Conta ...
- DEV控件自定义排序实现
一般的控件或者组件都支持按照某一列进行排序.但是,这种排序是根据数据源里的数据默认按照降序或升序排序的,同时这样的排序与字段的类型有关. 假设现在字段的类型是字符串类型 ,但是,存储的数据时数字加一些 ...
- C# 调整控件的Z顺序
当窗口或者容器控件中的控件在布局过程中发生重叠的时候,会出现层次性.Z顺序较大的控件会遮挡Z顺序较小的控件,放在顶层的控件会挡住放在底层的控件. 1.编辑一个这样的窗口(使用Label控件) 2.添加 ...
随机推荐
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- POJ1742 Coin [DP补完计划]
题目传送门 Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 41707 Accepted: 14125 Des ...
- eclipse 设置英文
只需要将eclipse解压目录下的eclipse.ini文件中加入下面一句话就可以了(注意这句话应该单独存在一行): -Duser.language=EN 如下图: 配置完成后,重启eclipse ...
- 有的系统区apk需要对其系统签名,才能正常使用。
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 向方案公司索要platform.x509.pem 和platform.pk8这两个文件. ...
- [xsy2309]数字表格
题意:求$\prod\limits_{i=1}^n\prod\limits_{j=1}^mf_{(i,j)}$,其中$f_0=0,f_1=1,f_n=f_{n-1}+f_{n-2}$ 很妙的题 假设$ ...
- javaWeb中的JDBC学习入门
学习引荐地址:https://www.cnblogs.com/xdp-gacl/p/3946207.html 一.JDBC的相关概念介绍 1.1 数据库驱动 其实就好比我们平时使用到的独立声卡.网卡之 ...
- Node.js的http模块理解
Node.js标准库提供了http模块,其中封装了一个高效的HTTP服务器和一个简易的HTTP客户端. http.Server是一个基于事件的HTTP服务器,它的核心由C++编写,兼顾高性能和简易性 ...
- codevs 1297 硬币
1297 硬币 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 我们知道即使是同一种面值的硬币, ...
- Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵
H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...
- NServiceBus入门:发送一个命令(Introduction to NServiceBus: Sending a command)
原文地址:https://docs.particular.net/tutorials/intro-to-nservicebus/2-sending-a-command/ 侵删. 能够发送和接收mess ...