欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

联系人 列表

程序员文章站 2024-03-21 14:19:22
...

最近仿照联系人列表页,发现有现成的组件

需要组件包括:

1.pinned-section-listview   (https://github.com/beworker/pinned-section-listview)

2.IndexBar        (http://git.oschina.net/droideep/IndexBar)

3.pinyin4j.jar 拼音包    http://vdisk.weibo.com/s/JfPk1

 

开始码.......

package com.weidingqiang.customchinacar.activities;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.hb.views.PinnedSectionListView;
import com.weidingqiang.customchinacar.R;
import com.weidingqiang.customchinacar.base.BaseKJActivity;
import com.weidingqiang.customchinacar.models.Contact;

import net.sourceforge.pinyin4j.PinyinHelper;

import org.kymjs.kjframe.ui.BindView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import io.github.brightyoyo.IndexBar;

public class ContactActivity extends BaseKJActivity {

    /**
     * 选择乘车人列表有三部分组成
     * 1.读取联系人数据
     * 2.联系人列表组件
     * 3.左边选择组件
     */

    private static final String TAG = ContactActivity.class.getSimpleName();

    private ArrayList<Contact> contacts;

    //数据集。
    private ArrayList<Item> items = null;

    // ListView之Item的View Type数量。
    private final int VIEW_TYPE_COUNT = 2;

    //已经添加的组
    private Map<String,String> addgroups;

    @BindView(id=R.id.pinnedlist)
    PinnedSectionListView listView;

    @BindView(id=R.id.index_bar)
    IndexBar mIndexBar;

    @BindView(id=R.id.previewText)
    TextView mPreviewText;

    private Map<String, Integer> mSections = new HashMap<String, Integer>();

    @Override
    public void setRootView() {
        super.setRootView();
        setContentView(R.layout.activity_contact);
    }

    @Override
    public void initWidget() {
        super.initWidget();

        listView.setShadowVisible(false);

        mIndexBar.setIndexBarFilter(new IndexBar.IIndexBarFilter() {
            @Override
            public void filterList(float sideIndex, int position, String previewText) {
                Integer selection = mSections.get(previewText);
                if (selection != null) {
                    mPreviewText.setVisibility(View.VISIBLE);
                    mPreviewText.setText(previewText);
                    listView.setSelection(selection);
                } else {
                    mPreviewText.setVisibility(View.GONE);
                }
            }
        });
    }

    @Override
    public void initData() {
        super.initData();

        contacts = new ArrayList<Contact>();


        addgroups = new HashMap<String,String>();

        items = new ArrayList<Item>();

        mIndexBar.setSections(alphabets());
    }

    /**
     * 执行在异步,用于做耗时操作
     */
    @Override
    public void initDataFromThread() {
        super.initDataFromThread();

        readContacts(contacts);

    }

    /**
     *(initDataFromThread() 执行完成后将会回调)
     */
    @Override
    protected void threadDataInited() {
        super.threadDataInited();

        int target = 0;

        for (int k=0;k<contacts.size();k++)
        {
            boolean showline = true;
            //判断是否增加了组
            Contact contact = contacts.get(k);
            if(!isaddGroup(contact.firstLetterOfName())){

                mSections.put(contact.firstLetterOfName(), target);

                showline = false;

                addgroups.put(contact.firstLetterOfName(),contact.firstLetterOfName());

                Item group = new Item();
                group.type = Item.GROUP;
                group.text = contact.firstLetterOfName();
                group.showline = showline;
                items.add(group);
                target++;
            }

            Item child = new Item();
            child.type = Item.CHILD;
            child.text = contact.name;
            child.phone = contact.getPhone();
            child.showline = showline;
            items.add(child);
            target++;
        }

        listView.setAdapter(new MyAdapter(this, -1));
    }

    private String[] alphabets() {
        final int length = 26;
        final String[] alphabets = new String[length];
        char c = 'A';
        for (int i = 0; i < length; i++) {
            alphabets[i] = String.valueOf(c++);
        }
        return alphabets;
    }

    private boolean isaddGroup(String name){
        boolean boo = addgroups.containsKey(name);
        return boo;
    }

    //-------------------------------------------------------------------------------------------//
    private class MyAdapter extends ArrayAdapter<Item> implements
            PinnedSectionListView.PinnedSectionListAdapter {

        private LayoutInflater inflater = null;

        public MyAdapter(Context context, int resource) {
            super(context, resource);
            inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            int type = this.getItemViewType(position);

            if (type == Item.GROUP) {
                convertView = inflater.inflate(
                        R.layout.contact_list_group_item, null);
                TextView tv = (TextView) convertView
                        .findViewById(R.id.group_text);

                tv.setText(getItem(position).text);
                //tv.setBackgroundColor(getResources().getColor(R.color.contact_list_group_color));

                // 将背景设置为半透明,更好的观察效果。
                //tv.getBackground().setAlpha(128);
            }

            if (type == Item.CHILD) {
                convertView = inflater.inflate(
                        R.layout.contact_list_item, null);
                TextView tv = (TextView) convertView
                        .findViewById(R.id.contact_name);
                tv.setText(getItem(position).text);

                TextView tvphone = (TextView) convertView
                        .findViewById(R.id.contact_phone);
                tvphone.setText(getItem(position).phone);


                if(getItem(position).showline)
                {
                    View showline = (View) convertView.findViewById(R.id.showlineview);
                    showline.setVisibility(View.VISIBLE);
                }

            }

            return convertView;
        }

        @Override
        public int getItemViewType(int position) {
            return getItem(position).type;
        }

        // 2个type:GROUP或者CHILD。
        @Override
        public int getViewTypeCount() {
            return VIEW_TYPE_COUNT;
        }

        @Override
        public Item getItem(int position) {
            Item item = items.get(position);
            return item;
        }

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

        // 假设此方法返回皆为false。那么PinnedSectionListView将退化成为一个基础的ListView.
        // 只不过退化后的ListView只是一个拥有两个View Type的ListView。
        // 从某种角度上讲,此方法对于PinnedSectionListView至关重要,因为返回值true或false,将直接导致PinnedSectionListView是一个PinnedSectionListView,还是一个普通的ListView。
        @Override
        public boolean isItemViewTypePinned(int viewType) {
            boolean type = false;
            switch (viewType) {
                case Item.GROUP:
                    type = true;
                    break;
                case Item.CHILD:
                    type = false;
                    break;
                default:
                    type = false;
                    break;
            }

            return type;
        }
    }


    //区分组

    // 用于承载数据块的类。
    // 字段分为类型(type)和值(text)。
    private class Item {
        public static final int GROUP = 0;
        public static final int CHILD = 1;

        public int type;
        public String text;
        public String phone;
        public Boolean showline;
    }
    //-------------------------------------------------------------------------------------------//
    // 读取设备联系人的一般方法。大致流程就是这样,模板化的操作代码。
    private void readContacts(ArrayList<Contact> contacts) {
        Uri uri = Uri.parse("content://com.android.contacts/contacts");
        ContentResolver reslover = this.getContentResolver();

        // 在这里我们给query传递进去一个SORT_KEY_PRIMARY。
        // 告诉ContentResolver获得的结果安装联系人名字的首字母有序排列。
        Cursor cursor = reslover.query(uri, null, null, null,
                android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY);
        while (cursor.moveToNext()) {

            // 联系人ID
            String id = cursor
                    .getString(cursor
                            .getColumnIndex(android.provider.ContactsContract.Contacts._ID));

            // Sort Key,读取的联系人按照姓名从 A->Z 排序分组。
            String sort_key_primary = cursor
                    .getString(cursor
                            .getColumnIndex(android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY));

            // 获得联系人姓名
            String name = cursor
                    .getString(cursor
                            .getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME));

            Contact mContact = new Contact();
            mContact.id = id;
            mContact.name = name;
            mContact.sort_key_primary = getPinYinHeadChar(sort_key_primary);

            // 获得联系人手机号码
            Cursor phone = reslover.query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="
                            + id, null, null);

            // 取得电话号码(可能存在多个号码)
            // 因为同一个名字下,用户可能存有一个以上的号,
            // 遍历。
            ArrayList<String> phoneNumbers = new ArrayList<String>();
            while (phone.moveToNext()) {
                int phoneFieldColumnIndex = phone
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                String phoneNumber = phone.getString(phoneFieldColumnIndex);
                phoneNumbers.add(phoneNumber);
            }
            mContact.phoneNumbers = phoneNumbers;

            contacts.add(mContact);
        }
    }

    /**
     * 提取每个汉字的首字母
     * 用了一个拼音包
     * @param str
     * @return String
     */
    public static String getPinYinHeadChar(String str) {
        String convert = "";
        for (int j = 0; j < str.length(); j++) {
            char word = str.charAt(j);
            // 提取汉字的首字母

            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
            if (pinyinArray != null) {
                convert += pinyinArray[0].charAt(0);
            } else {
                convert += word;
            }
        }
        return convert;
    }
}

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aCar="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical"
    >

    <com.weidingqiang.customchinacar.views.topbar.BaseTopBar
        android:id="@+id/baseTopBar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/topbar_hight"
        aCar:isShowMiddleTextView = "true"
        aCar:middleText = "@string/qctivity_contact_title"
        aCar:isShowRight = "false"
        >
    </com.weidingqiang.customchinacar.views.topbar.BaseTopBar>


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        >
        <com.hb.views.PinnedSectionListView
            android:id="@+id/pinnedlist"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginRight="26dp"
            />

        <TextView
            android:id="@+id/previewText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="40sp"
            android:textStyle="bold"
            android:textColor="@color/black"
            />

        <io.github.brightyoyo.IndexBar
            android:id="@+id/index_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_margin="5dp"
            aCar:alphabetPadding="5dp"
            aCar:alphabetTextColor="#DFAF3F"
            aCar:alphabetTextSize="12sp"
            aCar:indexBarColorNormal="@android:color/transparent"
            aCar:indexBarColorPressed="#56000000"
            aCar:indexBarRound="5dp"
            aCar:withinIndexBar="true" />
    </RelativeLayout>

</LinearLayout>
package com.weidingqiang.customchinacar.models;

import java.util.ArrayList;

/**
 * Created by weidingqiang on 15/11/12.
 */
// 用于装载从联系人数据库中读取到的数据。
// 结构化数据,便于数据操作和访问。
public class Contact {
    public String id;
    public String name;
    public String sort_key_primary;
    public ArrayList<String> phoneNumbers;

    //获得一个联系人名字的首字符。
    //比如一个人的名字叫“安卓”,那么这个人联系人的首字符是:A。
    public	String	firstLetterOfName(){
        String s=sort_key_primary.charAt(0)+"";
        return	s.toUpperCase();
    }

    public String getPhoneNumbers() {
        String phones = " ";
        for (int i = 0; i < phoneNumbers.size(); i++) {
            phones += "号码" + i + ":" + phoneNumbers.get(i);
        }

        return phones;
    }

    public String getPhone(){
        if(phoneNumbers.size() == 0)
            return "";
        return phoneNumbers.get(0);
    }
}