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

来源:互联网 发布:最新滤镜软件 编辑:程序博客网 时间:2024/05/17 23:44

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

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

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

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


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

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>() {            @Override            public 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;    }    @Override    public String[] getSections() {        return sections;    }    //需要进行排序的字符串    protected abstract String getSortString(T bean);    //通过section位置,获取首个position位置    @Override    public 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位置    @Override    public 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字母,其他位置隐藏。这样我们的分组效果就能实现了。   为了获取这个位置,我们的逻辑是这样的:通过位置获取当前位置的字母,再通过这个字母获取这个字母在列表中的第一个位置,如果第一个位置和当前位置相同则表示是第一个位置。上面的主要两个方法就是为这个服务的。


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

  @Override    public 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位置    @Override    public 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;    }    @Override    public 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);    }    @Override    protected String getSortString(ContactEntity bean) {        return bean.getSortName();    }    @Override    public int getCount() {        return datas.size();    }    @Override    public Object getItem(int position) {        return null;    }    @Override    public long getItemId(int position) {        return 0;    }    @Override    public 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">    <TextView        android: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" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#fdfdfd"        android:gravity="center_vertical"        android:orientation="horizontal">        <ImageView            android:layout_width="50dp"            android:layout_height="50dp"            android:paddingBottom="5dp"            android:paddingLeft="10dp"            android:paddingTop="5dp"            android:src="@mipmap/ic_launcher"            android:visibility="gone" />        <TextView            android: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;    @Override    protected 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);    }    @Override    public void onTouch(String s) {        mLetterWindow.show(s);        int index = mContactAdapter.getSectionIndex(s);        int position = mContactAdapter.getPositionForSection(index);        if (position != -1)            mList.setSelection(position);    }    @Override    public 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);    }    @Override    public 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">    <FrameLayout        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1">        <ListView            android: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.IndexView            android:id="@+id/civ"            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:layout_gravity="right" />    </FrameLayout></LinearLayout>


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


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


1 0