一:简言

一个月没有写博客了,公司项目比较忙,最近发现公司用到一个知识点,所以抽时间通过博客的形式分享给大家,该知识点,模仿微信的好友列表,通过字母索引进行定位,该功能主要通过几个知识点实现。下面会一一讲解。

二:具体说下思路

  • 1 :整体用到的控件,list view(recyclerView原理一样),自定义view,汉字转拼音的utils工具类.
  • 2:创建一个自定义类继承view,实现侧面滑动字母显示字母索引数据,说下自定义View,首先自定义类继承View重写三个构造方法,重写
  • onMeasure()的方法用于测量View的宽高,onSizeChanged()方法改变当前控件大小的时候调用,onDarw()方法绘制View,
  • onTouchEvent()方法用于手势监听,自定义接口用于保存点击了那个字母的值。
  • 3:创建一个person的实体bean,实现列表数据的展示,
  • 4。通过将汉字通过拼音的形式进行分类,添加一个pinyinj-2.5.0.jar,实现转换,(稍后代码会详细介绍)。
  • 5:将数据显示出来,实现效果;

三:实现效果

 

  • 四:通过代码的形式介绍步骤:

1)首先实现实体bean(Person)

public class Person {private String name;private String pinyin;public Person(String name){this.name = name;this.pinyin = PinYinUtils.getPinYin(name);}public String getPinyin() {return pinyin;}public void setPinyin(String pinyin) {this.pinyin = pinyin;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", pinyin='" + pinyin + '\'' +'}';}
}

该类没有讲解的必要,直接刀币下一个类:

2)拼音转换工具类(PinYinUtils)

首先添加这个jar包(稍后分享)

然后创建该类(代码如下)

public class PinYinUtils {/*** 得到指定汉字的拼音* 注意:不应该被频繁调用,它消耗一定内存* @param hanzi* @return*/public static String getPinYin(String hanzi){String pinyin = "";HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//控制转换是否大小写,是否带音标format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//大写format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);//由于不能直接对多个汉字转换,只能对单个汉字转换char[] arr = hanzi.toCharArray();for (int i = 0; i < arr.length; i++) {if(Character.isWhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历//汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换if(arr[i]>127){try {//由于多音字的存在,单 dan shanString[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);if(pinyinArr!=null){pinyin += pinyinArr[0];}else {pinyin += arr[i];}} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();//不是正确的汉字pinyin += arr[i];}}else {//不是汉字,pinyin += arr[i];}}return pinyin;}
}

3)重点来了,主要实现的功能,自定义view(IndexView)

/*** Created by wk先森* 快速索引* 绘制快速索引的字母* 1.二十六个字母 放入集合中* 2.在onMeaus中计算每条的宽和高 itemHeight itemWidth wordHeight wordX wordY* <p>* 手指按下 文字变色* 重写onTouchEvent方法  返回true* 在Down和move中 计算* int touchIndex = Y/itemHeight  强制绘制* <p>* 2.在onDraw方法对于该下包画笔变色* <p>* 3。在Up的时候 touchIndex  = -1;* 强制绘制*/public class IndexView extends View {/*** 每条的宽和高*/private int itemWidth;private int itemHeight;Paint paint;private String[] words = {"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 int  touchIndex = -1;public IndexView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);initView(context);}private void initView(Context context) {paint = new Paint();paint.setColor(Color.BLACK);//设置颜色paint.setAntiAlias(true);paint.setTypeface(Typeface.DEFAULT_BOLD);}/*** 测量方法*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);itemWidth = getMeasuredWidth();itemHeight = getMeasuredHeight() / words.length;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for (int i = 0; i < words.length; i++) {if(touchIndex == i){//设置灰色paint.setColor(Color.GRAY);}else{//设置白色paint.setColor(Color.BLACK);}String word = words[i];Rect rect = new Rect();//0,1 取一个字母paint.getTextBounds(word, 0, 1, rect);int wordWidth = rect.width();int wordHeight = rect.height();//计算每个字母在视图上的坐标float wordX = itemWidth / 2 - wordWidth / 2;float wordY = itemHeight / 2 + wordHeight / 2 + i * itemHeight;canvas.drawText(word, wordX, wordY, paint);}}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:float Y= event.getY();int index = (int) (Y/itemHeight);//字母的索引if(index != touchIndex){touchIndex  = index;//强制绘制 onDraw();invalidate();if(onIndexChangeListener != null && touchIndex<words.length){onIndexChangeListener.OnIndexChange(words[touchIndex]);}}break;case MotionEvent.ACTION_UP :touchIndex = -1;invalidate();break;}return true;}/*** 字母下标索引变化监听器* */public interface OnIndexChangeListener{/*** 挡字幕下标位置发生变化时候回调* */void OnIndexChange(String word);}private OnIndexChangeListener onIndexChangeListener;public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener) {this.onIndexChangeListener = onIndexChangeListener;}
}

5)通过activity实现该功能(MainActivity)

该类需要关注的点:

Toast显示的时间

public class MainActivity extends AppCompatActivity {private ListView lvMain;private TextView tvWord;private IndexView ivWords;private Handler handler = new Handler();/*** 联系人的集合*/private ArrayList<Person> persons;private  IndexAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {lvMain = findViewById(R.id.lv_main);tvWord = findViewById(R.id.tv_word);ivWords = findViewById(R.id.iv_words);//设置监听字母下标索引变化ivWords.setOnIndexChangeListener(new IndexView.OnIndexChangeListener() {/*** 回传是字母* */@Overridepublic void OnIndexChange(String word) {updateWord(word);updateListView(word);//A~Z}});initData();adapter = new IndexAdapter();lvMain.setAdapter(adapter);}private void updateListView(String word) {for(int i=0;i<persons.size();i++){String listWord = persons.get(i).getPinyin().substring(0,1);//YANGGUANGFU-->Yif (word.equals(listWord)) {//i是listView中的位置lvMain.setSelection(i);//定位到ListVeiw中的某个位置return;}}}private void updateWord(String word){//显示tvWord.setVisibility(View.VISIBLE);tvWord.setText(word);handler.removeCallbacksAndMessages(null);handler.postDelayed(new Runnable() {@Overridepublic void run() {//也是运行在主线程中tvWord.setVisibility(View.GONE);}},500);}/*** 初始化数据*/private void initData() {persons = new ArrayList<>();persons.add(new Person("张晓飞"));persons.add(new Person("杨光福"));persons.add(new Person("胡继群"));persons.add(new Person("刘畅"));persons.add(new Person("钟泽兴"));persons.add(new Person("尹革新"));persons.add(new Person("安传鑫"));persons.add(new Person("张骞壬"));persons.add(new Person("温松"));persons.add(new Person("李凤秋"));persons.add(new Person("刘甫"));persons.add(new Person("娄全超"));persons.add(new Person("张猛"));persons.add(new Person("王英杰"));persons.add(new Person("李振南"));persons.add(new Person("孙仁政"));persons.add(new Person("唐春雷"));persons.add(new Person("牛鹏伟"));persons.add(new Person("姜宇航"));persons.add(new Person("刘挺"));persons.add(new Person("张洪瑞"));persons.add(new Person("张建忠"));persons.add(new Person("侯亚帅"));persons.add(new Person("刘帅"));persons.add(new Person("乔竞飞"));persons.add(new Person("徐雨健"));persons.add(new Person("吴亮"));persons.add(new Person("王兆霖"));persons.add(new Person("阿三"));persons.add(new Person("李博俊"));//排序Collections.sort(persons, new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.getPinyin().compareTo(o2.getPinyin());}});}class  IndexAdapter extends BaseAdapter{@Overridepublic int getCount() {return persons.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder;if(convertView == null){convertView = View.inflate(MainActivity.this,R.layout.item_main,null);viewHolder = new ViewHolder();viewHolder.tv_word =  convertView.findViewById(R.id.tv_word);viewHolder.tv_name =  convertView.findViewById(R.id.tv_name);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder) convertView.getTag();}String name = persons.get(position).getName();//阿福String word = persons.get(position).getPinyin().substring(0,1);//AFU->AviewHolder.tv_word.setText(word);viewHolder.tv_name.setText(name);if(position ==0){viewHolder.tv_word.setVisibility(View.VISIBLE);}else{//得到前一个位置对应的字母,如果当前的字母和上一个相同,隐藏;否则就显示String preWord = persons.get(position-1).getPinyin().substring(0,1);//A~Zif(word.equals(preWord)){viewHolder.tv_word.setVisibility(View.GONE);}else{viewHolder.tv_word.setVisibility(View.VISIBLE);}}return convertView;}}static class ViewHolder{TextView tv_word;TextView tv_name;}}

到这里功能可以说已经介绍完了。把剩下的xml文件赠送给大家

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns: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.zzsy.quickindex.MainActivity"><ListViewandroid:id="@+id/lv_main"android:layout_width="match_parent"android:layout_height="match_parent"/><TextViewandroid:id="@+id/tv_word"android:visibility="gone"android:layout_centerInParent="true"android:layout_width="80dp"android:layout_height="80dp"android:gravity="center"android:background="#44000000"android:textColor="#000000"android:text="A"android:textSize="30sp"android:textStyle="bold"/><com.zzsy.quickindex.IndexViewandroid:id="@+id/iv_words"android:layout_width="35dp"android:layout_height="match_parent"android:layout_alignParentEnd="true"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:background="#10000000" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/tv_word"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#22000000"android:text="A"android:paddingLeft="5dp"android:textColor="#000000"android:textSize="25sp" /><TextViewandroid:id="@+id/tv_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="阿福"android:padding="5dp"android:textColor="#dd000000"android:textSize="22sp" /></LinearLayout>

上面的xml文件分别是main,item_main

五。jar包地址:

https://download.csdn.net/download/wk_beicai/11635244

android 自定义view,字母排序(仿微信好友列表)相关推荐

  1. android的实现关注好友功能,android仿微信好友列表功能

    android studio实现微信好友列表功能,注意有一个jar包我没有放上来,请大家到MainActivity中的那个网址里面下载即可,然后把pinyin4j-2.5.0.jar复制粘贴到项目的a ...

  2. android仿微信好友列表

    android studio实现微信好友列表功能,注意有一个jar包我没有放上来,请大家到MainActivity中的那个网址里面下载即可,然后把pinyin4j-2.5.0.jar复制粘贴到项目的a ...

  3. android 自定义特效,Android自定义View之高仿QQ健康

    我们都知道自定义View一般有三种直接继承View.继承原有的控件对控件的进行修改.重新拼装组合,最后一种主要针对于ViewGroup.具体的怎么做不是本文的所涉及的内容(本文是基于第一种方式实现的) ...

  4. android 字母索引三方,Android ListView字母索引(仿微信通讯录列表)

    布局代码 xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_paren ...

  5. Android自定义view之实现仿抖音双击点赞单击暂停特效

    2018年抖音.快手.火山等短视频App比较火,最近自己做短视频项目时有个需求,就是类似抖音的点赞特效,单击屏幕时视频暂停,再次点击时视频恢复播放,双击或者连续多次点击时出现点赞特效(飘小心心特效), ...

  6. android listview qq,Android中使用listview实现qq/微信好友列表

    首先附上运行结果: 如果你没有学过listview请你先看一看基本知识.不想再说的那么细了 太多了. 首先是listview布局 android:id="@+id/lv_view" ...

  7. Android自定义A_Z字母排序ListView,悬停Listview

    近期项目有个功能,要开发一个通讯录,什么样的通讯录呢: 1.带字母分组的悬停 2.右边带字母索引的侧边栏 3.与顶部搜索框进行动态变化 4.点击Item可以直接拨电话.复制.发邮件 想想一个通讯录要求 ...

  8. Android 自定义View修炼-高仿猎豹清理大师自定义内存开口圆环比例进度View

    一.概述 看见猎豹清理大师的内存开口圆环比例进度 挺有意思的,于是就是想自己实现下这样的效果,于是反编译了猎豹清理 大师的app看了下,原来是有两张图,于是脑子里就过了下思路,利用上下两张图,旋转上面 ...

  9. Android自定义View,高仿QQ音乐歌词滚动控件!

    最近在以QQ音乐为样板做一个手机音乐播放器,源码下篇博文放出.今天我想聊的是这个QQ音乐播放器中歌词显示控件的问题,和小伙伴们一起来探讨怎么实现这个歌词滚动的效果.OK,废话不多说,先来看看效果图: ...

最新文章

  1. 《0day安全:软件漏洞分析技术》的一点总结
  2. WebServices中使用cxf开发日志拦截器以及自定义拦截器
  3. 使用while循环输入 1 2 3 4 5 6 8 9 10
  4. Linux minicom串口通讯
  5. 单词搭配用法查询网站
  6. 类里面没有参缺省构造函数 的带来的问题
  7. php 批量删除挂马文件夹,PHP批量挂马脚本
  8. 一张图看懂BGP邻居关系建立过程和BGP报文简介
  9. 8.分布式服务架构:原理、设计与实战 --- 敏捷开发2.0的自动化工具
  10. python图像边缘检测报告_python计算机视觉2:图像边缘检测
  11. MapControl与PageLayoutControl联动
  12. VB.net绘制tan函数图像
  13. matlab实现振动弹簧的实时动画,仿真动画软件设计作品--理想弹簧振子简谐振动...
  14. 多元相关与回归分析及R使用
  15. R语言使用rbind函数将两个dataframe数据纵向合并起来(vertically)
  16. animation unity 速度_Unity中用Timeline实现动画特写(上)
  17. 小程序的支付以及取消之后再次支付
  18. 【PHP】关于系统性能追踪工具molten
  19. Kubernetes 亲和性与反亲和性
  20. 计算机的防呆接口,PC接口全释:防呆口很重要,小心硬插烧硬件!

热门文章

  1. CVPR2021目标检测方向论文
  2. 简述相关与回归分析的关系_相关分析与回归分析的联系与区别
  3. 如何在JavaScript中直观地设计状态
  4. SQL查询学生表中每课大于85分的同学名称
  5. 你需要这样一个Ros软路由—— 路由器+外网+一号通ip线路=动态ip的WiFi信号
  6. 计算机与航空方向专业,2018航空航天工程专业就业前景和就业方向分析
  7. 使用hutool-poi在未安装Office或wps软件的电脑中生成Excel的xls后缀消失问题
  8. Swift 3.0 语法
  9. 计算机教育学研究方法,广西师大 教育学 孙杰远《教育研究方法》知识点笔记1.pdf...
  10. TDSQL PG 版企业级分布式数据库技术创新实践