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.添加 ...
随机推荐
- Codeforces Round #433 (Div. 2, based on Olympiad of Metropolises) D. Jury Meeting(双指针模拟)
D. Jury Meeting time limit per test 1 second memory limit per test 512 megabytes input standard inpu ...
- luogu P1378 油滴扩展
题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴. ...
- 【DFS】【图论】NOIP2014寻找道路
[NOIP2014]寻找道路 题目描述 Description 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1.路径上的所有点的出边所 ...
- 【计算几何】【凸包】【极角排序】【二分】Gym - 101128J - Saint John Festival
平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内. 对红点求凸包后,转化为询问有多少个黑点在凸包内. 点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后 ...
- [POI2010]Divine Divisor
[POI2010]Divine Divisor 题目大意: 给你\(m(m\le600)\)个数\(a_i(a_i\le10^{18})\).\(n=\prod a_i\).现在要你找到一个最大的\( ...
- 免费网站监控服务阿里云监控,DNSPod监控,监控宝,360云监控使用对比
网站会因为各种原因而导致宕机,具体表现为服务器没有响应,用户打不开网页,域名解析出错,搜索引擎抓取页面失败,返回各种HTTP错误代码.网站宕机可能带来搜索引擎的惩罚,网站服务器不稳定与百度关系文章中就 ...
- all objects of the same class share the same set of class methods
#include <iostream> #include "First.h" void Test(); int main() { std::cerr<<&q ...
- Oracle一条SQL语句时快时慢
今天碰到一个非常奇怪的问题问题,一条SQL语句在PL/SQL developer中很慢,需要9s,问题SQL: SELECT * FROM GG_function_location f WHERE f ...
- Unity3D 避免玩家作弊
如果你的Unity项目快上线了,我强烈建议你看一下Anti-Cheat这个插件.因为IOS和Android分别越狱和Root后玩家可以使用 @八门神器 @烧饼修改器 等一些列作弊的软件来修改游戏内存, ...
- HTTPS 信任证书
使用HttpsURLConnection访问HTTPS链接时一般需要引入证书,否则会产生异常. 但是也可以使用信任所有证书的方式来达到访问的目的. 经上网查询资料发现一个很好用的类来实现信任所有证书的 ...