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.添加 ...
随机推荐
- maven "Generating project in Batch mode"问题的解决
在maven的五分钟入门里面,有这样一个命令: mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -Darc ...
- oracle Lower Upper length substr
字符函数: Lower(char):将字符串装换为小写的格式 Upper(char):将字符串装换为大写的格式 length(char):返回字符串的长度 substr(char,m,n):从m开始截 ...
- ALL运算符
ALL在英文中的意思是“所有”,ALL运算符要求比较的值需要匹配子查询中的所有值.ALL运算符同样不能单独使用,必须和比较运算符共同使用. 下面的SQL语句用来检索在所有会员入会之前出版的图书: SE ...
- Python的替换函数——strip(),replace()和re.sub()(转)
原文地址:http://blog.csdn.net/zcmlimi/article/details/47709049 在Python中常用的三个"替换"函数是strip(),rep ...
- 2016ACM-ICPC网络赛北京赛区 1001 (trie树牌大模拟)
[题目传送门] 1383 : The Book List 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 The history of Peking University ...
- 【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game
给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开 ...
- 倒置数组 Exercise07_12
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:倒置数组 * */ public class Exercise07_12 ...
- Problem E: 十六进制转十进制
#include<stdio.h> int main(void) { ]; int sum,i; while(gets(str)!=NULL) { sum=; ;str[i]!='\0'; ...
- Java中的服务器与客户端的简单连接
Java中重点之一就是服务器与客户端的连接,因为是在同一台PC上,所以就设置服务器的地址为“localhost”,注意,我当时试着设置其他名称,但都不行,这个原因还请老司机告一下.另外还要注意,服务端 ...
- 使用织梦开源的分词算法库编写的YII获取分词扩展
在编辑文章中,很多时候都需要自动根据文章内容获取关键字的功能,因此,本文主要是说明如何在yii中使用织梦开源的分词算法编写一个独立的扩展,可以在不同的模块中使用,步骤如下: 1 到这里下载其他朋友整理 ...