A-Z排序控件的实现

  • 前言

  最近项目需要做一个地区首字母a-z排序的效果,记录一下自己如何实现的.

先看下效果图:

  

  • 分析

这种效果自己实现还是第一次;之前见过这种效果:

这些字母都是onDraw画上去的;只要知道每个字母的left,top,right,bottom就能知道它的具体位置,所以onMeasure方法中要确定每个单元格的宽高.文字排序可以先把汉字转换成拼音,再去比较首字母的顺序(特殊地区特殊处理,比如重庆);

具体看下是如何确定字母的位置:

于是乎,代码就出来了:

  1 public class QuickIndexBar extends View {
  2     
  3     private OnLetterUpdateListener onLetterUpdateListener;
  4     
  5     public interface OnLetterUpdateListener{
  6         void onLetterUpdate(String letter);
  7     }
  8     
  9     public OnLetterUpdateListener getOnLetterUpdateListener() {
 10         return onLetterUpdateListener;
 11     }
 12 
 13     public void setOnLetterUpdateListener(
 14             OnLetterUpdateListener onLetterUpdateListener) {
 15         this.onLetterUpdateListener = onLetterUpdateListener;
 16     }
 17     private static final String[] LETTERS = new String[]{
 18         "A", "B", "C", "D", "E", "F",
 19         "G", "H", "I", "J", "K", "L",
 20         "M", "N", "O", "P", "Q", "R",
 21         "S", "T", "U", "V", "W", "X",
 22         "Y", "Z"
 23     };
 24     
 25     private Paint paint;
 26 
 27     // 单元格宽度
 28     private int cellWidth;
 29 
 30     // 单元格高度
 31     private float cellHeight;
 32 
 33 
 34     public QuickIndexBar(Context context) {
 35         this(context, null);
 36     }
 37 
 38     public QuickIndexBar(Context context, AttributeSet attrs) {
 39         this(context, attrs, 0);
 40     }
 41 
 42     public QuickIndexBar(Context context, AttributeSet attrs, int defStyle) {
 43         super(context, attrs, defStyle);
 44         // 创建一个抗锯齿的画笔
 45         paint = new Paint(Paint.ANTI_ALIAS_FLAG);
 46         // 画笔文本加粗
 47         paint.setTypeface(Typeface.DEFAULT_BOLD);
 48         // 颜色
 49         paint.setColor(Color.WHITE);
 50     }
 51     
 52     @Override
 53     protected void onDraw(Canvas canvas) {
 54         
 55         // 遍历26个英文字母, 计算坐标, 进行绘制
 56         for (int i = 0; i < LETTERS.length; i++) {
 57             String letter = LETTERS[i];
 58             
 59             // 计算x坐标
 60             float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
 61             // 计算y坐标
 62             Rect bounds = new Rect();
 63             // 获取文本的矩形区域
 64             paint.getTextBounds(letter, 0, letter.length(), bounds);
 65             
 66             float y = cellHeight * 0.5f + bounds.height() * 0.5f + i * cellHeight;
 67             
 68             // 绘制文本
 69             canvas.drawText(letter, x, y, paint);
 70         }
 71     }
 72     private int lastIndex = -1;
 73     
 74     @Override
 75     public boolean onTouchEvent(MotionEvent event) {
 76         
 77         float y;
 78         int currentIndex;
 79         
 80         switch (event.getAction()) {
 81         case MotionEvent.ACTION_DOWN:
 82             // 获取被点击到的字母索引
 83             y = event.getY();
 84             // 根据y值, 计算当前按下的字母位置
 85             currentIndex = (int) (y / cellHeight);
 86             if(currentIndex != lastIndex){
 87                 if(currentIndex >= 0 && currentIndex < LETTERS.length){
 88                     String letter = LETTERS[currentIndex];
 89                     if(onLetterUpdateListener != null){
 90                         onLetterUpdateListener.onLetterUpdate(letter);
 91                     }
 92                     System.out.println("letter: " + letter);
 93                     // 记录上一次触摸的字母
 94                     lastIndex = currentIndex;
 95                 }
 96             }
 97             
 98             break;
 99         case MotionEvent.ACTION_MOVE:
100             // 获取被点击到的字母索引
101             y = event.getY();
102             // 根据y值, 计算当前按下的字母位置
103             currentIndex = (int) (y / cellHeight);
104             if(currentIndex != lastIndex){
105                 if(currentIndex >= 0 && currentIndex < LETTERS.length){
106                     String letter = LETTERS[currentIndex];
107                     if(onLetterUpdateListener != null){
108                         onLetterUpdateListener.onLetterUpdate(letter);
109                     }
110                     System.out.println("letter: " + letter);
111                     // 记录上一次触摸的字母
112                     lastIndex = currentIndex;
113                 }
114             }
115             
116             break;
117         case MotionEvent.ACTION_UP:
118             lastIndex = -1;
119             break;
120         default:
121             break;
122         }
123         
124         return true;
125     }
126     
127     @Override
128     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
129         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
130         int mHeight = getMeasuredHeight();
131         cellWidth = getMeasuredWidth();
132         cellHeight = mHeight * 1.0f / LETTERS.length;
133     }
134     
135     
136 
137 }

这种竖直的简单快速索引就搞定了,此外还添加了触摸和点击的监听

  • 实现

再来看下我们要的效果图那种效果是如何实现的;主要区别就是字母所在位置和触摸位置的差异,偷点懒,直接上代码了:

 1   @Override
 2     protected void onDraw(Canvas canvas) {
 3 
 4         // 遍历26个英文字母, 计算坐标, 进行绘制
 5         for (int i = 0; i < LETTERS.length; i++) {
 6             String letter = LETTERS[i];
 7 
 8             // 计算x坐标
 9 //            float x = cellWidth * 0.5f - paint.measureText(letter) * 0.5f;
10             float y = cellHeight * 0.5f + paint.measureText(letter) * 0.5f;
11             // 计算y坐标
12             Rect bounds = new Rect();
13             // 获取文本的矩形区域
14             paint.getTextBounds(letter, 0, letter.length(), bounds);
15 
16 //            float y = cellHeight * 0.5f + bounds.height() * 0.5f + i * cellHeight;
17             float x = cellWidth * 0.5f + bounds.width() * 0.5f + i * cellWidth;
18             // 绘制文本
19             canvas.drawText(letter, x, y, paint);
20         }
21     }
22 
23     private int lastIndex = -1;
24 
25     @Override
26     public boolean onTouchEvent(MotionEvent event) {
27 
28         float x;
29         int currentIndex;
30 
31         switch (event.getAction()) {
32             case MotionEvent.ACTION_DOWN:
33                 // 获取被点击到的字母索引
34                 x = event.getX();
35                 // 根据x值, 计算当前按下的字母位置
36                 currentIndex = (int) (x / cellWidth);
37                 if (currentIndex != lastIndex) {
38                     if (currentIndex >= 0 && currentIndex < LETTERS.length) {
39                         String letter = LETTERS[currentIndex];
40                         if (onLetterUpdateListener != null) {
41                             onLetterUpdateListener.onLetterUpdate(letter);
42                         }
43                         // 记录上一次触摸的字母
44                         lastIndex = currentIndex;
45                     }
46                 }
47 
48                 break;
49             case MotionEvent.ACTION_MOVE:
50                 // 获取被点击到的字母索引
51                 x = event.getX();
52                 // 根据y值, 计算当前按下的字母位置
53                 currentIndex = (int) (x / cellWidth);
54                 if (currentIndex != lastIndex) {
55                     if (currentIndex >= 0 && currentIndex < LETTERS.length) {
56                         String letter = LETTERS[currentIndex];
57                         if (onLetterUpdateListener != null) {
58                             onLetterUpdateListener.onLetterUpdate(letter);
59                         }
60                         // 记录上一次触摸的字母
61                         lastIndex = currentIndex;
62                     }
63                 }
64 
65                 break;
66             case MotionEvent.ACTION_UP:
67                 lastIndex = -1;
68                 break;
69             default:
70                 break;
71         }
72 
73         return true;
74     }
75 
76     @Override
77     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
78         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
79         int mWidth = getMeasuredWidth();
80         cellWidth = mWidth * 1.0f / LETTERS.length;
81         cellHeight = getMeasuredHeight();
82     }

可以看到主要区别就是单元格的宽度和高度相应改变了;后面会补充一张计算草图.

 

转载于:https://www.cnblogs.com/fuyaozhishang/p/7110215.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql两个表查询修改_MySQL:查询、修改(二)

干货:使用SELECT查询的基本语句SELECT * FROM 可以查询一个表的所有行和所有列的数据。SELECT查询的结果是一个二维表。使用SELECT *表示查询表的所有列&#xff0c;使用SELECT 列1, 列2, 列3则可以仅返回指定列&#xff0c;这种操作称为投影。SELECT语句可以对结果集的列进行重…

Jython中文乱码问题

最近&#xff0c;在项目中需要用到Java代用Python的代码&#xff0c;并且需要传参数&#xff0c;因此选用了Jython包&#xff0c;但是&#xff0c;如果在调用python脚本时&#xff0c;出现了中文乱码的现象。代码如下&#xff1a; PythonInterpreter interpreter interpreter …

无规则弹窗自动点击插件_vscode 插件会了吧,英语不好的赶紧下载 自动分析源码中的陌生单词、点击朗读单词...

名字非常土&#xff1a;会了吧&#xff01;Solgan 还在因为 变量中 包含不认识的单词 头大吗&#xff1f;还在因为 看不懂 英文注释/文档 掉头发吗 &#xff1f;还在因为 各种机器翻译的内容 云里雾里吗 &#xff1f;您的救星来了&#xff01;&#xff01;&#xff01;用了“会…

Knozen:新型职场社交评论匿名应用,已获多家风投投资

Knozen是一款6月底新公布的职场匿名应用&#xff0c;能够展示你的同事朋友最赞赏、喜欢你什么。通过这款应用。能够匿名评价、分享、发现你的同事和朋友的个性。以及个性特征的比較。你的评价还能够被其它人匿名允许或反对&#xff1a;这个应用希望能够帮助你发现自己的个性长处…

mq幂等mysql_膜拜!看完这篇你还不懂RocketMQ算我输

RocketMQ 介绍Apache RocketMQ 是一款 低延迟、高并发、高可用、高可靠的分布式消息中间件。消息队列 RocketMQ 可为分布式应用系统提供异步解耦和削峰填谷的能力&#xff0c;同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性。RocketMQ 概念Topic&#xff1a;…

从一个数组中找出最接近目标_LeetCode每日一题 | 转变数组后最接近目标值的数组和...

题目来源&#xff1a;LC1300这道题目是一道比较经典的二分查找题。我们注意到&#xff0c;当value越大时&#xff0c;数组之和越大&#xff0c;当value越小时&#xff0c;数组之和越小。因此&#xff0c;我们可以利用数组之和是value的单调递增函数这个性质来进行二分查找。最大…

C++ 初始化列表初始化列表性能问题的简单的探索

C 初始化列表性能问题的简单的探索 从概念上来讲&#xff0c;构造函数的执行可以分成两个阶段&#xff0c;初始化阶段和计算阶段&#xff0c;初始化阶段先于计算阶段。 在执行构造函数时&#xff0c;如果没有给定初始值&#xff0c;那系统就会自动进行初始化。 #include <st…

mysql 5.5半同步复制_(5.5)mysql高可用系列——MySQL半同步复制(实践)

关键词&#xff0c;mysql半同步复制【0】实验环境操作系统&#xff1a;CentOS linux 7.5数据库版本&#xff1a;5.7.24数据库架构&#xff1a;主从复制&#xff0c;主库用于生产&#xff0c;从库用于数据容灾和主库备机&#xff0c;采用默认传统的异步复制。主库IP&#xff1a;…

Java+Jmeter接口测试

一、创建工程、引包1、创建JAVA工程2、引入Jmeter中lib\ext基础包&#xff1a;ApacheJMeter_java.jar、ApacheJMeter_core.jar3、引入Jmeter日志包&#xff1a;jorphan.jar&#xff0c;logkit-2.0.jar&#xff0c;commons-logging-1.1.1.jar&#xff0c;avalon-framework-4.1.4…

Discuz3.3精仿小米风格整站模板制作——1、新建模板方案

术语说明&#xff1a; 模板——模板是一堆按照规定命名方式的html文件&#xff0c;用于指定整个论坛不同页面的外观。标签——标签和模板共同作用以实现论坛换肤功能&#xff0c;其中标签主要控制页面显示什么数据&#xff0c;显示多少条等。风格——风格是一个xml配置文件&…

普元连接mysql_普元EOS 案例 - 还有一行代码的个人空间 - OSCHINA - 中文开源技术交流社区...

1 创建项目1) 进入EOS Studio开发透视图&#xff1b;单击主菜单项“文件”选择“新建”->“空EOS项目2) 在弹出的“创建空EOS项目”视图中&#xff0c;配置相关参数。“项目名称”&#xff1a;EOSTriping&#xff0c;3) 单击【完成】按钮&#xff0c;系统完成该项目框架…

十年WEB技术发展历程

Ajax03年的时候我上六年级。那时候网吧刚在小县城的角落萌生。传奇&#xff0c;大话西游第一代网游一时风靡。我抱着试一试的心态给了网吧老板两块钱想申请个号玩玩&#xff0c;然后接下来的一个小时我一直在&#xff0c;注&#xff0c;冊&#xff0c;账。号。彼时网吧用的512k…

Python之编写登陆接口

1.输入用户名密码&#xff1b; 2.认证成功后显示欢迎信息&#xff1b; 3.错误三次后&#xff0c;账号被锁定。 账号文件&#xff1a;user.txt 锁定文件&#xff1a;locked.txt 流程图如下&#xff1a; # -*- coding:utf-8 -*- # Author Caoxl import sysaccount_fileE:\user…

好全的Android面试题

转载&#xff1a;http://www.jianshu.com/p/84ee896c3329 需求描述 各种新技术接触渠道比较狭窄, 面试没有底气。 常见面试知识点及回答没有较系统的准备&#xff0c;就业指导提供的资料没时间看&#xff0c;看了记不住。 面试没有经验, 不清楚面试前要做的各种准备、面试过程…

JavaSE--类加载器

参考&#xff1a;http://www.importnew.com/6581.html Java 编译器会为虚拟机转换源指令。虚拟机代码存储在以 .class 为扩展名的类文件中&#xff0c;每个类文件都包含某个类或者接口的定义和代码实现。这些类文件必须由一个程序进行解释&#xff0c;该程序能够将虚拟机的指令…

java netbeans 教程_NetBeans 教程

NetBeans IDE Java 快速入门教程第一章本章通过指导您创建一个简单的 "Hello World" Java 控制台应用程序&#xff0c;简要介绍 NetBeans IDE 工作流。学习完本教程后&#xff0c;您将对如何在 IDE 中创建和运行应用程序有一个基本了解。学习完本教程所需的时间不到 …

几个python小程序

python小程序 1-100求和 1 def Sum(x, y):2 return xy3 print reduce(lambda x,y:xy,range(1,101))4 5 i 16 j 07 while i < 101:8 j i j9 i 1 10 print j View Code输出1-100之间的奇偶数1 i 1 2 a [] 3 while i < 100: 4 if i%2 0: 5 …

Linux下git使用

一、安装 本人使用的是centos 7&#xff0c;首先安装git 1.下载git&#xff1a;wget https://Github.com/Git/Git/archive/v2.3.0.tar.gz 2.下载之后解压&#xff1a;tar xvf v2.3.0.tar.gz 3.进入解押文件目录&#xff1a;cd git-2.3.0 4.依次运行如下命令&#xff1a; ./conf…

java 水表识别_一种水表数字的AI智能识别方法与流程

本发明涉及模式识别与人工智能技术领域&#xff0c;特别涉及一种直观的水表数字的AI智能识别方法。背景技术&#xff1a;深度学习在目标检测的应用发展迅速&#xff0c;在YOLO(You Only Look Once)之后又出现了升级版本YOLOv2&#xff0c;采用的是Darknet-19作为基础网络&#…

mysql.w002_mysql简单例子

登陆数据库&#xff1a;mysql -u用户名 -p密码 -P端口 -h数据库地址‍‍‍‍‍‍修改mysql提示符&#xff1a;(仅本次连接有效)‍‍‍‍‍‍方法一&#xff1a;执行mysql -uroot -proot -prompt \h结果为&#xff1a;localhost方法二&#xff1a;进入mysql后&#xff0c;执行PR…