自定义通讯录字母索引

2024-05-27 01:48

本文主要是介绍自定义通讯录字母索引,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、先来看下布局的效果

布局的代码如下,其中LetterIndexView为我们将要自定义的控件,使用相对布局置于界面的右侧;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.itemp.letterindexview.MainActivity"><ListView
        android:id="@+id/lvFriends"android:layout_width="match_parent"android:layout_height="match_parent"/><TextView
        android:id="@+id/tvCurrentLetter"android:layout_width="100dp"android:layout_height="100dp"android:background="@drawable/shape_letterindexview_bg_pressed"android:gravity="center"android:textSize="50sp"android:layout_centerInParent="true"android:textColor="@color/white"android:textStyle="bold"android:visibility="visible"android:text="A" /><com.itemp.letterindexview.LetterIndexView
        android:id="@+id/liv"android:layout_width="35dp"android:layout_height="match_parent"android:layout_margin="5dp"android:layout_alignParentRight="true"/></RelativeLayout>

2、继承于View并使用绘图法在画布上绘制字母:

public class LetterIndexView extends View

3、实现构造方法,在其中初始化画笔,并为控件设置背景图(shape资源制作的圆角矩形)

    public LetterIndexView(Context context) {this(context, null);}public LetterIndexView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public LetterIndexView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//setBackgroundResourece();setBackgroundResource(R.drawable.shape_letterindexview_bg);paint = new Paint();paint.setAntiAlias(true);//抗锯齿}

4、shape资源的定义代码:res/drawable/shape_letterindexview_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#fff" /><stroke
        android:width="1dp"android:color="#ddd" /><corners android:radius="10dp" />
</shape>

这是一个白色实心的圆角矩形,按下后将其变为黄色实心的圆角矩形,文件为res/drawable/shape_letterindexview_bg_pressed.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="#ff0" /><stroke
        android:width="1dp"android:color="#ddd" /><corners android:radius="10dp" />
</shape>

5、定义字符串数组作为索引的文本:

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", "#",
};

6、覆写onDraw()方法,将字母纵向排列均匀地绘制在画布上:

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (width == 0) {width = getWidth();height = getHeight();}//把字母画在控件上,【选中字母】用红色画笔,否则黑色for (int i = 0; i < letters.length; i++) {//计算startX,控件宽度的一半减去字母宽度的一半String letter = letters[i];float letterSize = paint.measureText(letter);float startX = (width - letterSize) / 2;//startY,上方所有单元格的高度之和+(单元格高度的一半+字母高度的一半)float unitHeight = (height - 40) / 27f;float startY = 20 + i * unitHeight + (unitHeight + letterSize) / 2;//高亮字母为红色,否则为黑色if(i == currentPosition){paint.setColor(Color.RED);}else {paint.setColor(Color.BLACK);}paint.setTextSize(35);paint.setStyle(Paint.Style.FILL_AND_STROKE);//使用加粗效果canvas.drawText(letter, startX, startY, paint);//绘制字母}}

7、接下来覆写onTouchEvent()定义手指在控件上的滑动响应,逻辑为:
·手指按下,整个控件的背景色变为黄色,并根据手指按下的y的位置,确认哪个字母为选中字母,并重绘以将该字母高亮显示,并通知外界响应按下事件(比如显示小窗口见本文末尾GIF)
·手指滑动,动态改变选中字母,并重绘以将该字母高亮显示
·手指抬起,控件背景恢复为默认的白色,并通知外界响应(比如隐藏小窗口见文章末尾GIF)

    @Overridepublic boolean onTouchEvent(MotionEvent event) {float y = event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN://改变背景效果setBackgroundResource(R.drawable.shape_letterindexview_bg_pressed);//根据手指位置设置高亮字母并重绘invalidateCurrentPosition(y);//通知外界手指按下if (callback != null) {callback.onFingerDown(true);}break;case MotionEvent.ACTION_MOVE://根据手指位置设置高亮字母并重绘invalidateCurrentPosition(y);//通知外界字母变化if (callback != null) {callback.onLetterChanged(letters[currentPosition]);}break;case MotionEvent.ACTION_UP://恢复背景效果setBackgroundResource(R.drawable.shape_letterindexview_bg);//通知外界手指抬起if (callback != null) {callback.onFingerDown(false);}break;}return true;}/*** 根据手指位置动态设置高亮字母并重绘* @param y*/private void invalidateCurrentPosition(float y) {currentPosition = (int) ((y / height) * letters.length);if(currentPosition > 26){currentPosition = 26;}invalidate();}

11、以接口的方式通知外界:手指按下或抬起,高亮字母发生改变:

    LetterIndexCallback callback;public void setCallback(LetterIndexCallback callback) {this.callback = callback;}public interface LetterIndexCallback {void onFingerDown(boolean down);void onLetterChanged(String letter);}

12、最后当外界ListView主动滚动时,字母索引的选中字母也随之变化,我们为外界提供公共方法,用于更新选中字母的位置:

    /*** 供外界ListView滚动时通知到当前控件* @param firstLetter*/public void setCurrentLetter(String firstLetter) {for (int i = 0; i < letters.length; i++) {if(letters[i].equals(firstLetter)){setCurrentPosition(i);return;}}}

13、Activity实现【索引控件】的回调接口,并将自身设置给【索引控件】:

public class MainActivity extends AppCompatActivity implements LetterIndexView.LetterIndexCallback 
@Overridepublic void onLetterChanged(String letter) {tvCurrentLetter.setText(letter);}@Overridepublic void onFingerDown(boolean fingerDown) {if(fingerDown){tvCurrentLetter.setVisibility(View.VISIBLE);}else {tvCurrentLetter.setVisibility(View.GONE);}}
letterIndexView.setCallback(this);

效果如下:
这里写图片描述

这篇关于自定义通讯录字母索引的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

浅谈mysql的not exists走不走索引

《浅谈mysql的notexists走不走索引》在MySQL中,​NOTEXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引,下面就来介绍一下mysql的notexists走不走索... 在mysql中,​NOT EXISTS子句是否使用索引取决于子查询中关联字段是否建立了合适的索引。以下

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

python3如何找到字典的下标index、获取list中指定元素的位置索引

《python3如何找到字典的下标index、获取list中指定元素的位置索引》:本文主要介绍python3如何找到字典的下标index、获取list中指定元素的位置索引问题,具有很好的参考价值,... 目录enumerate()找到字典的下标 index获取list中指定元素的位置索引总结enumerat

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

如何自定义一个log适配器starter

《如何自定义一个log适配器starter》:本文主要介绍如何自定义一个log适配器starter的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求Starter 项目目录结构pom.XML 配置LogInitializer实现MDCInterceptor