自定义通讯录字母索引
来源:互联网 发布:塑料卡扣连接技术 淘宝 编辑:程序博客网 时间:2024/06/01 12:03
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()方法,将字母纵向排列均匀地绘制在画布上:
@Override protected 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)
@Override public 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
@Override public void onLetterChanged(String letter) { tvCurrentLetter.setText(letter); } @Override public void onFingerDown(boolean fingerDown) { if(fingerDown){ tvCurrentLetter.setVisibility(View.VISIBLE); }else { tvCurrentLetter.setVisibility(View.GONE); } }
letterIndexView.setCallback(this);
效果如下:
0 0
- 自定义通讯录字母索引
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- 自定义通讯录索引
- 自定义view____通讯录字母特效
- Andorid使用自定义View实现通讯录,媒体文件等等的ListView的字母索引
- Android自定义控件5----继承View通讯录索引功能之1初始化显示字母列表
- 自定义字母索引View
- 自定义SlideBar (字母索引)
- android仿微信通讯录字母索引控件
- Android ListView字母索引(仿微信通讯录列表)
- 【笔记】通讯录使用侧栏字母索引
- Android实现通讯录功能,排序+字母索引
- 自定义字母索引的案例
- 自定义tableview索引,字母搜索
- Android获取通讯录联系人,右侧字母滑动索引
- Android仿微信通讯录功能,好友排序+字母索引
- Android获取通讯录联系人,右侧字母滑动索引
- c的动态内存管理
- 《深入分析JavaWeb技术内幕》读书笔记二.磁盘IO
- emojicon表情客户端和服务端的传递
- strncmp函数的使用
- HOOK钩子函数
- 自定义通讯录字母索引
- 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
- Git 用命令提交代码
- download from free electrons
- 基数排序
- 解决ie下ajaxsubmit上传文件提示下载文件问题
- 支持“EFDBContext”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库
- spring相关jar包下载地址
- scala学习(01)