也是忙忙碌碌好几天,今天又有时间了,继续这个文章的编写。

阅读这篇文章之前,请先阅读

联系人列表字母排序索引(一)

联系人列表字母排序索引(二)

今天是这篇文章的最后一部分,主要内容包括以下几点:

1.将中文名字转化成拼音,并提取首字母,进行排序。

2.实现分组列表Adapter模板。

3.将列表与索引结合在一起。

pinyin4j是一个将中文转化成拼音的高效工具,我的源码中带了这个依赖包。通过这个工具,可以先获取一个中文的拼音。

    public static String getLetter(String name) {StringBuilder sb = new StringBuilder();for (int i = 0; i < name.length(); i++) {char c = name.charAt(i);String[] str = PinyinHelper.toHanyuPinyinStringArray(c);if (str != null && str.length >= 1) {sb.append(str[0].charAt(0));} else {sb.append(c);}}return sb.toString();}

PinyinHelper.tohanyuPinyinStringArray(),将每个char转化成拼音,我这里只提取每个汉字的第一个拼音字母,最后返回的结果是字符串的拼音简写。比如:张三丰---zsf

上面的步骤,已经可以将中文转化成拼音简写了,下面,要做的是什么呢?

下面的思路是这样的:

1.先对列表数据按字母顺序排序。

2.adapter的每一个itemView都是带字母分组头和内容的。只是,只有在一组中文开头的首个位置才显示。也就是说,张三丰,张君宝等,排在第一个的显示头部,也就是z,其他的隐藏头部。所以这个位置要计算出来。

3.因为每一个item包含了头部,所以,点击事件需要在真实内容区域,不在头部。因此,ListView的点击事件需要禁用,把事件写在adapter的内容控件上。

1.1.先对字母排序,排序需要知道排序的内容,先定义一个接口:

package com.mjc.contactlistdemo.sort_by_letter;/*** Created by mjc on 2016/5/24.*/
public interface ISort {String getSortName();
}

之后,我们需要使用的数据,只要继承他,就可以使用我的带字母索引列表。

1.2.自定义排序方法:

排序的方法,需要我们借助Collections的sorts方法来排序:

/*** 按照字母排序** @param list* @return*/public static <T extends ISort> void sortByLetter(ArrayList<T> list) {Collections.sort(list, new Comparator<T>() {@Overridepublic int compare(T lhs, T rhs) {String l = getLetter(lhs.getSortName());String r = getLetter(rhs.getSortName());int minLength = Math.min(l.length(), r.length());int result = 0;for (int i = 0; i < minLength; i++) {if (l.charAt(i) < r.charAt(i)) {result = -1;break;} else if (l.charAt(i) > r.charAt(i)) {result = 1;break;} else {result = 0;continue;}}if (result == 0) {return l.length() > r.length() ? 1 : -1;}return result;}});}

用的是泛型,只要实现了Isort的实体类,都可以用它来排序。排序的过程,主要是compare方法,这个方法的返回值,决定了你的排序。每次比较两个数值,结果由返回值决定。具体的说,就是lhs要排在rhs左边,返回值就要小于0,;反之,一样。

2.1.Adapter的实现。

我将计算都提取到了一个BaseSortByLetterAdapter里面,但是在子Adapter里面,需要调用BaseSortByLetterAdapter的方法,得到第一个分组的位置。

package com.mjc.contactlistdemo.sort_by_letter;import android.widget.BaseAdapter;
import android.widget.SectionIndexer;import java.util.ArrayList;/*** Created by mjc on 2016/5/24.*/
public abstract class BaseSortByLetterAdapter<T> extends BaseAdapter implements SectionIndexer {protected String[] sections;protected ArrayList<T> datas;public BaseSortByLetterAdapter(ArrayList<T> datas) {sections = 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","#"};this.datas = datas;}@Overridepublic String[] getSections() {return sections;}//需要进行排序的字符串protected abstract String getSortString(T bean);//通过section位置,获取首个position位置@Overridepublic int getPositionForSection(int sectionIndex) {String section = sections[sectionIndex];//todo ListView的数据要按照字母顺序排列for (int i = 0; i < getCount(); i++) {T bean = datas.get(i);String headerLetter = SortUtil.getLetter(getSortString(bean));if (String.valueOf(headerLetter.charAt(0)).equalsIgnoreCase(section)) {return i;} else if (sectionIndex == 0) {return 0;}}return -1;}//通过位置获取sectionIndex位置@Overridepublic int getSectionForPosition(int position) {T bean = datas.get(position);String name = getSortString(bean);String letter = SortUtil.getLetter(name);String header = String.valueOf(letter.charAt(0));for (int i = 0; i < sections.length; i++) {if (sections[i].equalsIgnoreCase(header)) {return i;}}return 0;}public int getSectionIndex(String section) {for (int i = 0; i < sections.length; i++) {if (section.equalsIgnoreCase(sections[i])) {return i;}}return 0;}}

implements SectionIndexer,这个东西不是重点,他的作用是,当你开启ListView的快速滑动后,拖动滑动条是可以显示当前所处的数据的字母。只不过我这里实现方式,和系统的原理差不多,因此也是实现了这个接口,之后用到我们的IndexView上就好。

这里面重要的一点是:我们需要知道第一个字母出现的位置,以便于我们现实这个位置的title字母,其他位置隐藏。这样我们的分组效果就能实现了。   为了获取这个位置,我们的逻辑是这样的:通过位置获取当前位置的字母,再通过这个字母获取这个字母在列表中的第一个位置,如果第一个位置和当前位置相同则表示是第一个位置。上面的主要两个方法就是为这个服务的。

通过位置获取对应的字母字母的位置,原理很简单,先获取当前数据的排序字母,然后和字母列表比较,得到字母的位置。

  @Overridepublic int getSectionForPosition(int position) {T bean = datas.get(position);String name = getSortString(bean);String letter = SortUtil.getLetter(name);String header = String.valueOf(letter.charAt(0));for (int i = 0; i < sections.length; i++) {if (sections[i].equalsIgnoreCase(header)) {return i;}}return 0;}

再通过字母的位置,获取列表中第一个数据的位置,之后在getView中将这个位置和当前位置做比较,如果相等,就显示title,不相等就隐藏。

 //通过section位置,获取首个position位置@Overridepublic int getPositionForSection(int sectionIndex) {String section = sections[sectionIndex];//todo ListView的数据要按照字母顺序排列for (int i = 0; i < getCount(); i++) {T bean = datas.get(i);String headerLetter = SortUtil.getLetter(getSortString(bean));if (String.valueOf(headerLetter.charAt(0)).equalsIgnoreCase(section)) {return i;} else if (sectionIndex == 0) {return 0;}}return -1;}

到这里,基本是结束了,接下来是使用方法:

1.定义一个实体类,实现Isort接口。

2.定义一个Adpater,继承BaseSortByLetterAdapter

3.Activity中,setAdapter之前,先使用SortUtil对数据进行排序。

ContactEntity.class

package com.mjc.contactlistdemo.core.contact.entity;import com.mjc.contactlistdemo.sort_by_letter.ISort;/*** Created by mjc on 2016/5/12.*/
public class ContactEntity implements ISort {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String getSortName() {return name;}
}

ContactAdapter.class

package com.mjc.contactlistdemo.core.contact;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import com.mjc.contactlistdemo.R;
import com.mjc.contactlistdemo.core.contact.entity.ContactEntity;
import com.mjc.contactlistdemo.sort_by_letter.BaseSortByLetterAdapter;import java.util.ArrayList;/*** Created by mjc on 2016/5/24.*/
public class ContactAdapter extends BaseSortByLetterAdapter<ContactEntity> {public ContactAdapter(ArrayList<ContactEntity> datas) {super(datas);}@Overrideprotected String getSortString(ContactEntity bean) {return bean.getSortName();}@Overridepublic int getCount() {return datas.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {Holder mHolder;if (convertView == null) {mHolder = new Holder();convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_contact, null);mHolder.mNameTv = (TextView) convertView.findViewById(R.id.tv_name);mHolder.mIndexTv = (TextView) convertView.findViewById(R.id.tv_index);convertView.setTag(mHolder);} else {mHolder = (Holder) convertView.getTag();}//强转需要注意原来的类型ContactEntity bean =  datas.get(position);//获取对应字母的位置int index = getSectionForPosition(position);//比较列表中第一个字母的位置和这个位置是否相等if (getPositionForSection(index) == position) {mHolder.mIndexTv.setVisibility(View.VISIBLE);mHolder.mIndexTv.setText(sections[index]);} else {mHolder.mIndexTv.setVisibility(View.GONE);}mHolder.mNameTv.setText(bean.getName());return convertView;}class Holder {public TextView mNameTv;public TextView mIndexTv;}
}

item_contact.xml

<?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="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/tv_index"style="@style/KeyStyle"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#f4f6f3"android:paddingTop="12dp"android:paddingBottom="4dp"android:textSize="14sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#fdfdfd"android:gravity="center_vertical"android:orientation="horizontal"><ImageViewandroid:layout_width="50dp"android:layout_height="50dp"android:paddingBottom="5dp"android:paddingLeft="10dp"android:paddingTop="5dp"android:src="@mipmap/ic_launcher"android:visibility="gone" /><TextViewandroid:id="@+id/tv_name"style="@style/InputStyle"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:padding="10dp"android:textSize="16sp" /></LinearLayout>
</LinearLayout>

MainActivity.class

package com.mjc.contactlistdemo.core.contact;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;import com.mjc.contactlistdemo.R;
import com.mjc.contactlistdemo.core.contact.entity.ContactEntity;
import com.mjc.contactlistdemo.sort_by_letter.IndexView;
import com.mjc.contactlistdemo.sort_by_letter.LetterWindow;
import com.mjc.contactlistdemo.sort_by_letter.SortUtil;import java.util.ArrayList;public class MainActivity extends AppCompatActivity implements IndexView.OnCharTouchEvent {private LetterWindow mLetterWindow;private ContactAdapter mContactAdapter;private IndexView mIndexView;private ListView mList;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mList = (ListView) findViewById(R.id.list);mIndexView = (IndexView) findViewById(R.id.civ);mIndexView.setOnLetterTouchedListener(this);mLetterWindow = new LetterWindow(this);ArrayList<ContactEntity> list = new ArrayList<>();ContactEntity bean1 = new ContactEntity();bean1.setName("单熊信");ContactEntity bean2 = new ContactEntity();bean2.setName("谢天华");ContactEntity bean3 = new ContactEntity();bean3.setName("李自成");ContactEntity bean4 = new ContactEntity();bean4.setName("段天涯");ContactEntity bean5 = new ContactEntity();bean5.setName("张无忌");ContactEntity bean6 = new ContactEntity();bean6.setName("小红");ContactEntity bean7 = new ContactEntity();bean7.setName("李寻欢");ContactEntity bean8 = new ContactEntity();bean8.setName("王小亚");ContactEntity bean9 = new ContactEntity();bean9.setName("夏冬青");ContactEntity bean10 = new ContactEntity();bean10.setName("上官锦");ContactEntity bean11 = new ContactEntity();bean11.setName("炎亚纶");ContactEntity bean12 = new ContactEntity();bean12.setName("刘德华");ContactEntity bean13 = new ContactEntity();bean13.setName("陈浩民");ContactEntity bean14 = new ContactEntity();bean14.setName("马云");ContactEntity bean15 = new ContactEntity();bean15.setName("雷军");ContactEntity bean16 = new ContactEntity();bean16.setName("周宏伟");ContactEntity bean17 = new ContactEntity();bean17.setName("李易峰");ContactEntity bean18 = new ContactEntity();bean18.setName("鹿晗");ContactEntity bean19 = new ContactEntity();bean19.setName("邓超");ContactEntity bean20 = new ContactEntity();bean20.setName("李晨");ContactEntity bean21 = new ContactEntity();bean21.setName("张翰");ContactEntity bean22 = new ContactEntity();bean22.setName("邓丽君");ContactEntity bean23 = new ContactEntity();bean23.setName("曾志伟");ContactEntity bean24 = new ContactEntity();bean24.setName("阿甘");ContactEntity bean25 = new ContactEntity();bean25.setName("爸比");ContactEntity bean26 = new ContactEntity();bean26.setName("东方彧卿");ContactEntity bean27 = new ContactEntity();bean27.setName("方世玉");ContactEntity bean28 = new ContactEntity();bean28.setName("高芳");ContactEntity bean29 = new ContactEntity();bean29.setName("海大富");ContactEntity bean30 = new ContactEntity();bean30.setName("江离");ContactEntity bean31 = new ContactEntity();bean31.setName("康辉");ContactEntity bean32 = new ContactEntity();bean32.setName("牛郎");ContactEntity bean33 = new ContactEntity();bean33.setName("谢天华");ContactEntity bean34 = new ContactEntity();bean34.setName("单雄心");ContactEntity bean35 = new ContactEntity();bean35.setName("赛华佗");list.add(bean1);list.add(bean2);list.add(bean3);list.add(bean4);list.add(bean5);list.add(bean6);list.add(bean7);list.add(bean8);list.add(bean9);list.add(bean10);list.add(bean11);list.add(bean12);list.add(bean13);list.add(bean14);list.add(bean15);list.add(bean16);list.add(bean17);list.add(bean18);list.add(bean19);list.add(bean20);list.add(bean21);list.add(bean22);list.add(bean23);list.add(bean24);list.add(bean25);list.add(bean26);list.add(bean27);list.add(bean28);list.add(bean29);list.add(bean30);list.add(bean31);list.add(bean32);list.add(bean33);list.add(bean34);list.add(bean35);SortUtil.sortByLetter(list);mContactAdapter = new ContactAdapter(list);mList.setAdapter(mContactAdapter);}@Overridepublic void onTouch(String s) {mLetterWindow.show(s);int index = mContactAdapter.getSectionIndex(s);int position = mContactAdapter.getPositionForSection(index);if (position != -1)mList.setSelection(position);}@Overridepublic void onLetterChanged(String preLetter, String letter) {mLetterWindow.update(letter);int index = mContactAdapter.getSectionIndex(letter);int position = mContactAdapter.getPositionForSection(index);if (position != -1)mList.setSelection(position);}@Overridepublic void onRelease() {mLetterWindow.hide();}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"><FrameLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"><ListViewandroid:id="@+id/list"style="@style/CustomList"android:visibility="gone"android:layout_width="match_parent"android:layout_height="match_parent" /><com.mjc.contactlistdemo.sort_by_letter.IndexViewandroid:id="@+id/civ"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="right" /></FrameLayout>
</LinearLayout>

以上就是使用的过程,还是很简便的。

到这里,这个字母索引排序就算是写完了,谢谢!

联系人列表字母排序索引(三)相关推荐

  1. 联系人列表字母排序索引(一)

    很久没有写博客了,对自己又放松了很多.这篇博客本来早就要写了,迟迟拖到现在.今天这里要说的是,联系人列表,分组带索引,即联系人按字母顺序排列并分组,右边还有索引条.先看下效果: 就是这么一个效果,想必 ...

  2. Android 通过ListView实现联系人列表字母索引

    转载:Android自定义View--实现联系人列表字母索引_Code-Porter的博客-CSDN博客_android 字母索引 学习大神的思路和逻辑,很清晰. 这篇博文也不错:安卓仿手机联系人右侧 ...

  3. HTML 标签列表(字母排序)

    HTML 标签列表(字母排序) 标签 描述 <!--...--> 定义注释 <!DOCTYPE> 定义文档类型 <a> 定义超文本链接 <abbr> 定 ...

  4. 实现联系人列表字母索引

    相信大家对这个列表字母索引已经不陌生了,在很多app中也随处可见,像没团的城市地址选择,微信联系人列表,手机通讯录-等等.既然是个这么nb这么实用的功能我们怎么能不Get到来呢,下面就让我们一起造一个 ...

  5. Android自定义View——实现联系人列表字母索引

    相信大家对这个列表字母索引已经不陌生了,在很多app中也随处可见,像没团的城市地址选择,微信联系人列表,手机通讯录-等等.既然是个这么nb这么实用的功能我们怎么能不Get到来呢,下面就让我们一起造一个 ...

  6. 联系人排序java代码_Android仿微信联系人按字母排序_脚本之家

    App只要涉及到联系人的界面,几乎都是按照字母排序以及导航栏的方式.既然这个需求这么火,于是开始学习相关内容,此篇文章是我通过参考网上资料独立编写和总结的,希望多多少少对大家有所帮助,写的不好,还请各 ...

  7. 联系人排序java代码_Android仿微信联系人按字母排序

    App只要涉及到联系人的界面,几乎都是按照字母排序以及导航栏的方式.既然这个需求这么火,于是开始学习相关内容,此篇文章是我通过参考网上资料独立编写和总结的,希望多多少少对大家有所帮助,写的不好,还请各 ...

  8. Android 使用RecyclerView实现(仿微信)的联系人A-Z字母排序和过滤搜索功能

    之前做项目的时候遇到一个需求是实现品牌的字母排序功能,网上的资料很多,但是有一部分有bug,这篇文章是我学习和解决部分bug之后的总结.今天带来的是RecyclerView的A-Z字母排序和过滤搜索功 ...

  9. android 好友字母分组,Android好友联系人按字母排序分组,自定义通讯录导航栏View...

    Android中仿微信实现联系人列表 按字母排序分组 自定义通讯录导航栏View,下边是效果图: 1. 自定义View public class SideBar extends View { // 触 ...

最新文章

  1. C语言文件操作解析(二)【转载】
  2. linux 文本搜索命令 grep egrep fgrep 区别
  3. 潘越云《面朝海子》:诗里的人都会终成眷属
  4. python爬虫(五)_urllib2:urlerror和httperror
  5. 线性Transformer应该不是你要等的那个模型
  6. python图形化界面开发工具_图形用户界面(GUI)常见问题
  7. python棋盘最短路径_【leetcode】64. Minimum Path Sum 棋盘最短路径
  8. Android之集成友盟推送功能
  9. Homebrew是什么?怎么关闭自动更新?
  10. 入我新美大的Java后台开发面试题总结
  11. 类似Windows开始菜单的右键菜单
  12. bat批量修改文件后缀名
  13. PAT L1 007 念数字
  14. Windows变慢原因分析
  15. ccsa安学网小程序_CCSA安学网题库及答案
  16. 《线性代数》随笔:积沙成塔
  17. 【转载】世界十大名咖啡
  18. 贝尔-S-010W-A-芯片RK3228B卡刷固件
  19. Day06-Python文件和数据格式化
  20. html实战:用html编写游戏

热门文章

  1. 一行代码随意编辑网站
  2. 最小二乘法拟合正弦函数
  3. 用jQuery事件写Tab选项卡
  4. 【点云系列】PoinNetVLAD:Deep Point Cloud Based Retrieval for Large-Scale Place Recognition
  5. Wiki with Fake AKGPLT
  6. python终结一个循环额_103.md · 小小懒羊羊/StarterLearningPython - Gitee.com
  7. 读书笔记:《代码大全第2版》布局与风格
  8. LINUX学记笔记16
  9. jzxx1087歌德巴赫猜想
  10. 程序媛小姐姐甜甜恋爱过程