热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自定义View实现联系人快速查找

这个功能也经常用到比如:微信好友列表,联系人通讯录,应用管理,文件管理等效果图:实现步骤:-绘制A-Z.的索引,处理Touch事件-根据回调回调显示当前索引

这个功能也经常用到比如:微信好友列表, 联系人通讯录, 应用管理, 文件管理等

效果图:
这里写图片描述

实现步骤:
- 绘制 A-Z.的索引,处理Touch事件
- 根据回调回调显示当前索引
- 汉字转换成拼音,将数据进行分组
- 在ListView中使用自定义控件

自定义View代码:

public class QuickIndexView extends View {

int touchIndex = -1;
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 mPaint;
private int cellWidth;
private float cellHeight;
private OnLetterIndexChangeListener mLetterIndexChangeListener;


public interface OnLetterIndexChangeListener {
void onLetterIndexChange(String letter);
}

public void setOnLetterIndexChangeListener(OnLetterIndexChangeListener mLetterIndexChangeListener) {
this.mLetterIndexChangeListener = mLetterIndexChangeListener;
}

public QuickIndexView(Context context) {
this(context, null);
}

public QuickIndexView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public QuickIndexView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Paint.ANTI_ALIAS_FLAG 字体抗锯齿
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.GRAY);
// 粗体
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setTextSize(DensityUtils.dp2px(getContext(), 12));
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

for (int i = 0; i String letter = LETTERS[i];
// 计算字体放置x坐标
int x = (int) (cellWidth / 2.0f - mPaint.measureText(letter) / 2.0f);
// 获取文本的高度
Rect rect = new Rect();// 矩形
mPaint.getTextBounds(letter, 0, letter.length(), rect);
int letterHeight = rect.height();
// 每个text单元格增加高度
int y = (int) (cellHeight / 2.0f + letterHeight / 2.0f + i * cellHeight);
// 根据按下的字母, 设置画笔颜色
mPaint.setColor(touchIndex == i ? Color.BLACK : Color.GRAY);
canvas.drawText(letter, x, y, mPaint);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {

int index = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 得到index值,总高度/每个单元格的高度
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index // 判断是否同个一index,是就不再显示
if (touchIndex != index) {
if (mLetterIndexChangeListener != null) {
mLetterIndexChangeListener.onLetterIndexChange(LETTERS[index]);
}
// 记录当前index
touchIndex = index;
}
}
break;
case MotionEvent.ACTION_MOVE:
index = (int) (event.getY() / cellHeight);
if (index >= 0 && index if (touchIndex != index) {
if (mLetterIndexChangeListener != null) {
mLetterIndexChangeListener.onLetterIndexChange(LETTERS[index]);
}
touchIndex = index;
}
}
break;
case MotionEvent.ACTION_UP:
touchIndex = -1;
break;
}
invalidate();
return true;
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 获取单元格的宽
cellWidth = getMeasuredWidth();
int mHeight = getMeasuredHeight();
// 获取单元格的高
cellHeight = mHeight * 1.0f / LETTERS.length;
}
}

MainActivity:

public class MainActivity extends AppCompatActivity {

private ArrayList datas;
private TextView tv_center;
private Animation alpha_show;
private Animation alpha_die;
private boolean animatiOnState= true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alpha_show = AnimationUtils.loadAnimation(this, R.anim.alpha_show);
alpha_die = AnimationUtils.loadAnimation(this, R.anim.alpha_die);
datas = new ArrayList<>();
QuickIndexView qi_view = (QuickIndexView) findViewById(R.id.qi_view);
tv_center = (TextView) findViewById(R.id.tv_center);
final ListView lv_itme = (ListView) findViewById(R.id.lv_itme);
qi_view.setOnLetterIndexChangeListener(new QuickIndexView.OnLetterIndexChangeListener() {
@Override
public void onLetterIndexChange(String letter) {
showCenterIndex(letter);
for (int i = 0; i Person person = datas.get(i);
String index = person.getPinYin().charAt(0)+"";
if (TextUtils.equals(index,letter)){
lv_itme.setSelection(i);
break;
}
}
}
});
datas = fillAndSortData();
lv_itme.setAdapter(new MainAdapter(datas, getApplicationContext()));

}
private Handler mHandler = new Handler();
private void showCenterIndex(String letter) {
tv_center.setText(letter);
if (animationState){
tv_center.startAnimation(alpha_show);
animatiOnState= false;
}

tv_center.setVisibility(View.VISIBLE);
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
animatiOnState= true;
tv_center.startAnimation(alpha_die);
tv_center.setVisibility(View.GONE);
}
},1000);
}


private ArrayList fillAndSortData() {
ArrayList PersOns= new ArrayList<>();
for (int i = 0; i String name = Cheeses.NAMES[i];
Persons.add(new Person(name));
}
Collections.sort(Persons);
return Persons;
}
}

Adapter:

public class MainAdapter extends BaseAdapter {

private ArrayList datas;
Context context;

public MainAdapter(ArrayList datas, Context context) {
this.datas = datas;
this.cOntext= context;
}

@Override
public int getCount() {
return datas.size();
}

@Override
public Object getItem(int position) {
return datas.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder mHolder = null;
if (cOnvertView== null) {
mHolder = new ViewHolder();
}else{
mHolder = (ViewHolder) convertView.getTag();
}

String str = null;
String index = datas.get(position).getPinYin().charAt(0) + "";
if (position == 0) {
str = index;
} else {
//获取上一个inedx判断时否相等
String preIndex = datas.get(position - 1).getPinYin().charAt(0) + "";
if (!TextUtils.equals(preIndex, index)) {
str = index;
}
}

// 根据str是否为空缺定是否显示
mHolder.lv_index.setVisibility(str == null?View.GONE: View.VISIBLE);
mHolder.lv_index.setText(index);
mHolder.lv_name.setText(datas.get(position).getName().trim());
return mHolder.getView();
}


class ViewHolder {

public TextView lv_index;
public TextView lv_name;
public View view;

public ViewHolder() {
view = View.inflate(context, R.layout.list_itme, null);
lv_index = (TextView) view.findViewById(R.id.lv_index);
lv_name = (TextView) view.findViewById(R.id.lv_name);
view.setTag(this);
}
public View getView() {
return view;
}
}
}

获取拼音:

public class PinYinHelper {

public static String getPinyin(String text) {
HanyuPinyinOutputFormat hFormat = new HanyuPinyinOutputFormat();
// 大写
hFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
// 没有声调
hFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
char[] charArray = text.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i char c = charArray[i];
// 空格跳过
if (Character.isWhitespace(c)) {
continue;
}
if (c >= -127 && c <128) {
// 不是汉字
sb.append(c);
} else {
String pinYin = "";
try {
pinYin = PinyinHelper.toHanyuPinyinStringArray(c, hFormat)[0];
sb.append(pinYin);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
sb.append(pinYin);
}
}
}

return sb.toString();
}
}

推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 本文整理了Java中org.apache.hadoop.hive.ql.plan.ExprNodeColumnDesc.getTypeInfo()方法的一些代码示例,展 ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
author-avatar
mobiledu2502926247
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有