码迷,mamicode.com
首页 > 移动开发 > 详细

安卓用QuickContactBadge和AsyncQueryHandler实现联系人列表的完美实现

时间:2015-04-28 18:42:39      阅读:274      评论:0      收藏:0      [点我收藏+]

标签:android   自定义控件   quickcontactbadge   sparsearray   asyncqueryhandler   

                                                               打造你自己的个性联系人列表

     在公司开发这么久了,发现好多的控件没有用过,然后发现了一些新的知识感觉还是很不错的,今天在这里我就来用一下QuickContactBadge的控件和AsyncQueryHandler,说到底QuickContactBadge这个控件我也是偶然发现的,然后乘着现在公司的工作不忙,然后也准备换工作温习一下知识点罢了。

一、介绍QuickContactBadge用法

    1、  先看一下它的结构

<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">public class </span><span style="font-family: Arial, Helvetica, sans-serif;">QuickContactBadge </span><span style="font-family: Arial, Helvetica, sans-serif;">extends ImageView</span></div><div style="text-align: center;"><span style="font-family: Arial, Helvetica, sans-serif;"></span><div style="text-align: justify;">java.lang.Object</div></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">implements View.O</span><span style="font-family: Arial, Helvetica, sans-serif;">n<span style="text-align: justify; white-space: pre; background-color: rgb(240, 240, 240);">ClickListener</span></span></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"> ?    android.view.View.</span><span style="font-family: Arial, Helvetica, sans-serif;">mageView</span></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;">       ?    android.widget</span><span style="font-family: Arial, Helvetica, sans-serif;">.QuickContactBadge</span></div>


      说到底QuickContactBadge就是我们经常用到的那个通讯录里面的那个头像,看过源码的都知道它是继承ImageView的并且是自带了点击事件的,所以我们用它的时候也就不用我们去自定义的布局,然后我们点击图像也会弹出一个popwindow来,然后里面就会有什么邮件,电话,短信的这些功能,效果还是可以的,功能很强大吧。

  2、看下QuickContactBadge的使用方法和介绍

(1)email调用
<div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">public void assignContactFromEmail (String emailAddress, boolean lazyLookup)</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">//指定联系人的电子邮箱地址。(注:它会先搜索这个号码,如果没有会提醒你是否添加到联系人</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">置为true,将不//会立即查找这个邮箱地址,直到View被点击时。(注:是否延迟匹配电子邮件)</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">//参数 :  emailAddress:联系人的电子邮箱地址lazyLookup:如果</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">设</span></div>
(2)电话的调用
<div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">public void assignContactFromPhone (String phoneNumber, boolean lazyLookup)</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">//为联系人指定一个电话号码</span></div>//参数 
<div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">eNumber : 联系人的电话号码
</span></div>//pho
n<div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">被点击时。</span></div><div style="text-align: justify;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">//lazyLookup  : 如果设置为true,将不会立即查找这个电话号码,直到Vie</span><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;">w</span></div>
public void assignContactUri(Uri contactUri)
//这方法用得比较多,指定一个uri
 public void setMode(int size) ;//设计它的模式好像是3种(MODE_SMALL,MODE_MEDIUM,MODE_LARGE),这个是设计弹出dialog的大小
注意(优点):使用QuickContactBadge并不需要加入READ_CONTACTS权限。但是在无权限的情况下,如果联系人在通讯录里,则会直接进入查看联系人的界面,而不会有“拨打、查看、短信”三个选项。加入权限后则会出现

二、AsyncQueryHandler

因为QuickContactBadge是一个专门针对联系人所特制的控件,然后源码里也是使用AsyncQueryHandler来进行数据的操作,所以我们就来学习下
AsyncQueryHandler。

AsyncQueryHandler:异步的查询操作帮助类,其实它同样可以处理增删改

1。AsyncQueryHandler的作用

查询其API便可知,它担供:

startInsert,startDelete,startUpdate,startQuery

这四个操作,并提供相对应的onXXXComplete方法,以供操作完数据库后进行其它的操作,这四个onXXXComplete方法都是空实现,以便我们只需要去实现我们关注的操作。

2。为什么要使用AsyncQueryHandler

当然你也可以使用ContentProvider去操作数据库。这在数据量很小的时候是没有问题的,但是如果数据量大了,可能导致UI线程发生ANR事件。当然你也可以写个Handler去做这些操作,只是你每次使用ContentProvider时都要再写个Handler,必然降低了效率。

因此API提供了一个操作数据库的通用方法。

3。如何使用AsyncQueryHandler

你只需要继承AsyncQueryHandler类,并提供onXXXComplete方法的实现(可以实现任何一个或多个,当然你也可以一个也不实现,如果你不关注操作数据库的結果),在你的实现中做一些对数据库操作完成的处理。

使用时直接调用startXXX方法即可。传入的通用参数如下:

int token,一个令牌,需要跟onXXXComplete方法传入的一致。(当然你也可以不一致,同样在数据库的操作结束后会调用对应的onXXXComplete方法 )

Object cookie,你想传给onXXXComplete方法使用的一个对象。(没有的话传递null即可。基本发现这个变量没太大作用)

Uri uri,操作数据的URi

4。AsyncQueryHandler还为我们做了什么

AsyncQueryHandler中使用了一个WeakReference<ContentResolver>对象,即 ContentResolver的弱引用  作用:当contentProvied发生变化时候同步更新仍可以通过使用 AsyncQueryHandler类来达到这一要求(暂时还没理解这个作用)

同时,在它执行操作数据库时,吃掉了所有的异常。见如下代码。

 catch (Exception e) {
                        Log.w(TAG, e.toString());
                        cursor = null;
                    }

所以我们用他代替了contentProvider.

三、SparseArray的使用

SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类。SparseArray实现了Cloneable接口,还可以调用clone方法,它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseArray不需要对key和value进行auto- boxing(将原始类型封装为对象类型,比如把int类型封装成Integer类型),结构比HashMap简单(SparseArray内部主要使用 两个一维数组来保存数据,一个用来存key,一个用来存value)不需要额外的额外的数据结构(主要是针对HashMap中的HashMapEntry 而言的)。
<div style="text-align: justify;"><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;">SparseArrays map integers to Objects.  Unlike a normal array of Objects,</span></div><div style="text-align: justify;"><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;"> * there can be gaps in the indices.  It is intended to be more memory efficient</span></div><div style="text-align: justify;"><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;"> * than using a HashMap to map Integers to Objects, both because it avoids</span></div><div style="text-align: center;"><div style="text-align: justify;"><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;">object</span></div><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;"></span><div style="text-align: justify;"> * for each mapping.</div></div><div style="text-align: justify;"><span style="background-color: rgb(240, 240, 240); font-family: 'Microsoft YaHei', Verdana, sans-serif, SimSun;"> * auto-boxing keys and its data structure doesn't rely on an extra entry </span></div><div style="text-align: justify;">
</div>
上面是谷歌对SparseArrays 的原话介绍,“It is intended to be more memory efficient than using a HashMap to map Integers to Object”虽然英语不是很好但是我想原意就是“的目的是要比使用一个HashMap整数映射到对象有效”,所以性能我就不测了反正用法和hashMap差不多但是性能好很多。
不多说下面直接上代码:
acitivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/contact_list_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E1E6F6" >
    <ListView
        android:id="@+id/contact_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="#7690A5"
        android:divider="#7690A5"
        android:fadingEdge="none"
        android:scrollbars="none"
        android:scrollingCache="false"
        android:visibility="visible" />
    <com.zy.quilkycontact.AlphabeticBar
        android:id="@+id/fast_scroller"
        android:layout_width="22dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_gravity="top|right|center"
        android:layout_marginTop="0dip"
        android:background="@null"
        android:scaleType="centerInside"
        android:src="@drawable/dic_background" >
    </com.zy.quilkycontact.AlphabeticBar>
    <TextView
        android:id="@+id/fast_position"
        android:layout_width="70dip"
        android:layout_height="70dip"
        android:layout_centerInParent="true"
        android:layout_gravity="center_horizontal|top"
        android:layout_margin="34dip"
        android:background="@drawable/flag"
        android:gravity="center"
        android:padding="2dip"
        android:textColor="#404040"
        android:textSize="48dip"
        android:visibility="invisible" />
</RelativeLayout>
然后是item的布局:contact_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
    <!-- 首字母 -->
    <TextView
        android:id="@+id/alpha"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#7690A5"
        android:paddingLeft="10dip"
        android:textColor="#FFFFFF"
        android:visibility="gone" />
    <!-- 联系人信息 -->
    <QuickContactBadge
        android:id="@+id/contact"
        android:layout_width="75dip"
        android:layout_height="75dip"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/alpha"
        android:layout_marginBottom="3dip"
        android:layout_marginTop="3dip"
        android:src="@drawable/login_icon_member"
        style="?android:attr/quickContactBadgeStyleWindowSmall"  />
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/contact"
        android:singleLine="true"
        android:layout_marginLeft="50dp"
        android:textAppearance="?android:textAppearanceLarge"
        android:textColor="#FFFFFF" />
    <TextView
        android:id="@+id/number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_toRightOf="@+id/contact"
        android:singleLine="true"
         android:layout_marginLeft="50dp"
        android:textAppearance="?android:textAppearanceSmall"
        android:textColor="#FFFFFF" />
</RelativeLayout>
接下来是代码的编写:
1.先准备一个实体bean:联系人的实体类Contact.java
<div style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; text-align: justify; line-height: 13.75px; white-space: pre !important;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;"><span style="font-size:14px;">package com.zy.quilkycontact;</span></span></div><div style="text-align: justify;"><span style="font-size:14px;"><span style="line-height: 13.75px;"></span></span></div><span style="font-size:14px;">

public class Contact {
<span style="white-space: pre;">	</span>private int contactId; //id
<span style="white-space: pre;">	</span>private String desplayName;//姓名
<span style="white-space: pre;">	</span>private String phoneNum; // 电话号码
<span style="white-space: pre;">	</span>private String sortKey; // 排序用的
<span style="white-space: pre;">	</span>private Long photoId; // 图片id
<span style="white-space: pre;">	</span>private String lookUpKey; 
<span style="white-space: pre;">	</span>private int selected = 0;
<span style="white-space: pre;">	</span>private Strin</span><span style="font-size:12px;">g formattedNumber;
</span><span style="font-size:12px; white-space: pre;">	</span><span style="font-size:12px;">private String pinyin; // 姓名拼音
   </span><span style="font-size:14px;"> private String email;
<span style="white-space: pre;">	</span>public int getContactId() {
<span style="white-space: pre;">		</span>return contactId;
<span style="white-space: pre;">	</span>}
       public void setContactId(int contactId) {
<span style="white-space: pre;">		</span>this.contactId = contactId;
<span style="white-space: pre;">	</span>}
        public String getDesplayName() {
<span style="white-space: pre;">		</span>return desplayName;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setDesplayName(String desplayName) {
<span style="white-space: pre;">		</span>this.desplayName = desplayName;
<span style="white-space: pre;">	</span>}

</span><span style="font-size:12px;">
</span><span style="font-size:12px; white-space: pre;">	</span><span style="font-size:14px;">public String getPhoneNum() {
<span style="white-space: pre;">		</span>return phoneNum;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setPhoneNum(String phoneNum) {
<span style="white-space: pre;">		</span>this.phoneNum = phoneNum;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public String getSortKey() {
<span style="white-space: pre;">		</span>return sortKey;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setSortKey(String sortKey) {
<span style="white-space: pre;">		</span>this.sortKey = sortKey;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public Long getPhotoId() {
<span style="white-space: pre;">		</span>return photoId;
<span style="white-space: pre;">	</span>}</span><span style="font-size:12px;">


</span><span style="font-size:12px; white-space: pre;">	</span><span style="font-size:14px;">public void setPhotoId(Long photoId) {
<span style="white-space: pre;">		</span>this.photoId = photoId;
<span style="white-space: pre;">	</span>}


<span style="white-space: pre;">	</span>public String getLookUpKey() {
<span style="white-space: pre;">		</span>return lookUpKey;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setLookUpKey(String lookUpKey) {
<span style="white-space: pre;">		</span>this.lookUpKey = lookUpKey;
<span style="white-space: pre;">	</span>}
       public int getSelected() {
<span style="white-space: pre;">		</span>return selected;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setSelected(int selected) {
<span style="white-space: pre;">		</span>this.selected = selected;
<span style="white-space: pre;">	</span>}

<span style="white-space: pre;">	</span>public String getFormattedNumber() {
<span style="white-space: pre;">		</span>return formattedNumber;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setFormattedNumber(String formattedNumber) {
<span style="white-space: pre;">		</span>this.formattedNumber = formattedNumber;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public String getPinyin() {
<span style="white-space: pre;">		</span>return pinyin;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setPinyin(String pinyin) {
<span style="white-space: pre;">		</span>this.pinyin = pinyin;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public String getEmail() {
<span style="white-space: pre;">		</span>return email;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public void setEmail(String email) {
<span style="white-space: pre;">		</span>this.email = email;
<span style="white-space: pre;">	</span>}
}</span><span style="font-size:12px; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; line-height: 13.75px;"></span>
2.仿通讯录的带拼音的字母滑块控件AlphabeticBar.java
<div style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; text-align: justify; line-height: 13.75px; white-space: pre !important;"><span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;"><span style="font-size:14px;">package com.zy.quilkycontact;</span></span></div><span style="font-size:14px;">import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
/**
 * 字母索引条
 * 
 * 
 */
public class AlphabeticBar extends ImageButton {
<span style="white-space: pre;">	</span>private TextView mDialogText; // 中间显示字母的文本框
<span style="white-space: pre;">	</span>private Handler mHandler; // 处理UI的句柄
<span style="white-space: pre;">	</span>private ListView mList; // 列表
<span style="white-space: pre;">	</span>private float mHight; // 高度
<span style="white-space: pre;">	</span>// 字母列表索引
<span style="white-space: pre;">	</span>private String[] letters = new String[] { "#", "A", "B", "C", "D", "E",
<span style="white-space: pre;">			</span>"F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
<span style="white-space: pre;">			</span>"S", "T", "U", "V", "W", "X", "Y", "Z" };
<span style="white-space: pre;">	</span>// 字母索引哈希表
<span style="white-space: pre;">	</span>private HashMap<String, Integer> alphaIndexer;
<span style="white-space: pre;">	</span>Paint paint = new Paint();
<span style="white-space: pre;">	</span>boolean showBkg = false;
<span style="white-space: pre;">	</span>int choose = -1;
<span style="white-space: pre;">	</span>public AlphabeticBar(Context context) {
<span style="white-space: pre;">		</span>this(context, null);
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>public AlphabeticBar(Context context, AttributeSet attrs) {
<span style="white-space: pre;">		</span>this(context, attrs, 0);
<span style="white-space: pre;">	</span>}

<span style="white-space: pre;">	</span>public AlphabeticBar(Context context, AttributeSet attrs, int defStyle) {
<span style="white-space: pre;">		</span>super(context, attrs, defStyle);
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>// 初始化
<span style="white-space: pre;">	</span>public void init(Activity ctx) {
<span style="white-space: pre;">		</span>mDialogText = (TextView) ctx.findViewById(R.id.fast_position);
<span style="white-space: pre;">		</span>mDialogText.setVisibility(View.INVISIBLE);
<span style="white-space: pre;">		</span>mHandler = new Handler();
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>// 设置需要索引的列表
<span style="white-space: pre;">	</span>public void setListView(ListView mList) {
<span style="white-space: pre;">		</span>this.mList = mList;
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>// 设置字母索引哈希表
<span style="white-space: pre;">	</span>public void setAlphaIndexer(HashMap<String, Integer> alphaIndexer) {
<span style="white-space: pre;">		</span>this.alphaIndexer = alphaIndexer;
<span style="white-space: pre;">	</span>}


<span style="white-space: pre;">	</span>// 设置字母索引条的高度
<span style="white-space: pre;">	</span>public void setHight(float mHight) {
<span style="white-space: pre;">		</span>this.mHight = mHight;
<span style="white-space: pre;">	</span>}


<span style="white-space: pre;">	</span>@Override
<span style="white-space: pre;">	</span>public boolean onTouchEvent(MotionEvent event) {
<span style="white-space: pre;">		</span>int act = event.getAction();
<span style="white-space: pre;">		</span>float y = event.getY();
<span style="white-space: pre;">		</span>final int oldChoose = choose;
<span style="white-space: pre;">		</span>// 计算手指位置,找到对应的段,让mList移动段开头的位置上
<span style="white-space: pre;">		</span>int selectIndex = (int) (y / (mHight / letters.length));
<span style="white-space: pre;">		</span>if (selectIndex > -1 && selectIndex < letters.length) { // 防止越界
<span style="white-space: pre;">			</span>String key = letters[selectIndex];
<span style="white-space: pre;">			</span>if (alphaIndexer.containsKey(key)) {
<span style="white-space: pre;">				</span>int pos = alphaIndexer.get(key);
<span style="white-space: pre;">				</span>if (mList.getHeaderViewsCount() > 0) { // 防止ListView有标题栏,本例中没有
<span style="white-space: pre;">					</span>this.mList.setSelectionFromTop(
<span style="white-space: pre;">							</span>pos + mList.getHeaderViewsCount(), 0);
<span style="white-space: pre;">				</span>} else {
<span style="white-space: pre;">					</span>this.mList.setSelectionFromTop(pos, 0);
<span style="white-space: pre;">				</span>}
<span style="white-space: pre;">			</span>}
<span style="white-space: pre;">		</span>}
<span style="white-space: pre;">		</span>switch (act) {
<span style="white-space: pre;">		</span>case MotionEvent.ACTION_DOWN:
<span style="white-space: pre;">			</span>showBkg = true;
<span style="white-space: pre;">			</span>if (oldChoose != selectIndex) {
<span style="white-space: pre;">				</span>if (selectIndex > 0 && selectIndex < letters.length) {
<span style="white-space: pre;">					</span>choose = selectIndex;
<span style="white-space: pre;">					</span>invalidate();
<span style="white-space: pre;">				</span>}
<span style="white-space: pre;">			</span>}
<span style="white-space: pre;">		</span>
<span style="white-space: pre;">			</span>break;
<span style="white-space: pre;">		</span>case MotionEvent.ACTION_MOVE:
<span style="white-space: pre;">			</span>if (oldChoose != selectIndex) {
<span style="white-space: pre;">				</span>if (selectIndex > 0 && selectIndex < letters.length) {
<span style="white-space: pre;">					</span>choose = selectIndex;
<span style="white-space: pre;">					</span>invalidate();
<span style="white-space: pre;">				</span>}
<span style="white-space: pre;">			</span>}
<span style="white-space: pre;">			</span>break;
<span style="white-space: pre;">		</span>case MotionEvent.ACTION_UP:
<span style="white-space: pre;">			</span>showBkg = false;// 不显示
<span style="white-space: pre;">			</span>choose = -1;
<span style="white-space: pre;">			</span>break;
<span style="white-space: pre;">		</span>default:
<span style="white-space: pre;">			</span>break;
<span style="white-space: pre;">		</span>}
<span style="white-space: pre;">		</span>return super.onTouchEvent(event);
<span style="white-space: pre;">	</span>}
<span style="white-space: pre;">	</span>@Override
<span style="white-space: pre;">	</span>protected void onDraw(Canvas canvas) {
<span style="white-space: pre;">		</span>super.onDraw(canvas);
<span style="white-space: pre;">		</span>int height = getHeight();
<span style="white-space: pre;">		</span>int width = getWidth();
<span style="white-space: pre;">		</span>int sigleHeight = height / letters.length; // 单个字母占的高度
<span style="white-space: pre;">		</span>for (int i = 0; i < letters.length; i++) {
<span style="white-space: pre;">			</span>paint.setColor(Color.WHITE);
<span style="white-space: pre;">			</span>paint.setTextSize(20);
<span style="white-space: pre;">			</span>paint.setTypeface(Typeface.DEFAULT_BOLD);
<span style="white-space: pre;">			</span>paint.setAntiAlias(true);
<span style="white-space: pre;">			</span>if (i == choose) {
<span style="white-space: pre;">				</span>paint.setColor(Color.parseColor("#00BFFF")); // 滑动时按下字母颜色
<span style="white-space: pre;">				</span>paint.setFakeBoldText(true);
<span style="white-space: pre;">				</span>//选中后先显示选中的字目
<span style="white-space: pre;">				</span>mHandler.post(new Runnable() {
<span style="white-space: pre;">					</span>@Override
<span style="white-space: pre;">					</span>public void run() {
<span style="white-space: pre;">						</span>if (mDialogText != null) {
<span style="white-space: pre;">							</span>mDialogText.setVisibility(VISIBLE);
<span style="white-space: pre;">							</span>mDialogText.setText(letters[choose]);// 设置选中的滑动字母
<span style="white-space: pre;">						</span>}
<span style="white-space: pre;">					</span>}
<span style="white-space: pre;">				</span>});
<span style="white-space: pre;">				</span>//o.3秒后隐藏
<span style="white-space: pre;">				</span>mHandler.postDelayed(new Runnable() {
<span style="white-space: pre;">					</span>
<span style="white-space: pre;">					</span>@Override
<span style="white-space: pre;">					</span>public void run() {
<span style="white-space: pre;">						</span>mDialogText.setVisibility(INVISIBLE);
<span style="white-space: pre;">					</span>}
<span style="white-space: pre;">				</span>}, 300);<span style="white-space: pre;">	</span>
<span style="white-space: pre;">			</span>}
<span style="white-space: pre;">			</span>// 绘画的位置
<span style="white-space: pre;">			</span>float xPos = width / 2 - paint.measureText(letters[i]) / 2;
<span style="white-space: pre;">			</span>float yPos = sigleHeight * i + sigleHeight;
<span style="white-space: pre;">			</span>canvas.drawText(letters[i], xPos, yPos, paint);
<span style="white-space: pre;">			</span>paint.reset();
<span style="white-space: pre;">		</span>}
<span style="white-space: pre;">	</span>}
}</span><span style="font-size:12px; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; line-height: 13.75px;"></span>

3.接下来我们就写联系人的适配器ContactListAdapter.java
<div style="text-align: justify; white-space: pre !important;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:14px;"></span></span></div><span style="font-size:14px;">package com.zy.quilkycontact;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import android.content.ContentUris;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.QuickContact;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.QuickContactBadge;
import android.widget.TextView;
public class ContactListAdapter extends BaseAdapter {
<span style="white-space:pre">	</span>private LayoutInflater inflater;
<span style="white-space:pre">	</span>private SparseArray<Contact> list;
<span style="white-space:pre">	</span>private HashMap<String, Integer> alphaIndexer; // 字母索引
<span style="white-space:pre">	</span>private String[] sections; // 存储每个章节
<span style="white-space:pre">	</span>private Context ctx; // 上下文
<span style="white-space:pre">	</span>public ContactListAdapter(Context context, SparseArray<Contact> list,
<span style="white-space:pre">			</span>AlphabeticBar alpha) {
<span style="white-space:pre">		</span>this.ctx = context;
<span style="white-space:pre">		</span>this.inflater = LayoutInflater.from(context);
<span style="white-space:pre">		</span>this.list = list;
<span style="white-space:pre">		</span>this.alphaIndexer = new HashMap<String, Integer>();
<span style="white-space:pre">		</span>this.sections = new String[list.size()];
        int count=list.size();
<span style="white-space:pre">		</span>for (int i = 0; i <count; i++) {
<span style="white-space:pre">			</span>// 得到字母字符串的首字母
<span style="white-space:pre">			</span>String name = getAlpha(list.get(i).getSortKey());
<span style="white-space:pre">			</span>if (!alphaIndexer.containsKey(name)) {
<span style="white-space:pre">				</span>alphaIndexer.put(name, i);
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>Set<String> sectionLetters = alphaIndexer.keySet();//获取所有的key值
<span style="white-space:pre">		</span>ArrayList<String> sectionList = new ArrayList<String>(sectionLetters);
<span style="white-space:pre">		</span>Collections.sort(sectionList); // 根据首字母进行排序
<span style="white-space:pre">		</span>sections = new String[sectionList.size()];
<span style="white-space:pre">		</span>sectionList.toArray(sections);//转化为数组
<span style="white-space:pre">		</span>alpha.setAlphaIndexer(alphaIndexer);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public int getCount() {
<span style="white-space:pre">		</span>return list.size();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public Object getItem(int position) {
<span style="white-space:pre">		</span>return list.get(position);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public long getItemId(int position) {
<span style="white-space:pre">		</span>return position;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>public void remove(int position) {
<span style="white-space:pre">		</span>list.remove(position);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public View getView(int position, View convertView, ViewGroup parent) {
<span style="white-space:pre">		</span>ViewHolder holder;
<span style="white-space:pre">		</span>if (convertView == null) {
<span style="white-space:pre">			</span>convertView = inflater.inflate(R.layout.contact_list_item, parent,false);
<span style="white-space:pre">			</span>holder = new ViewHolder();
<span style="white-space:pre">			</span>holder.quickContactBadge = (QuickContactBadge) convertView
<span style="white-space:pre">					</span>.findViewById(R.id.contact);
<span style="white-space:pre">			</span>holder.alpha = (TextView) convertView.findViewById(R.id.alpha);
<span style="white-space:pre">			</span>holder.name = (TextView) convertView.findViewById(R.id.name);
<span style="white-space:pre">			</span>holder.number = (TextView) convertView.findViewById(R.id.number);
<span style="white-space:pre">			</span>convertView.setTag(holder);
<span style="white-space:pre">		</span>} else {
<span style="white-space:pre">			</span>holder = (ViewHolder) convertView.getTag();
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>Contact contact = list.get(position);
<span style="white-space:pre">		</span>String name = contact.getDesplayName();
<span style="white-space:pre">		</span>String number = contact.getPhoneNum();
<span style="white-space:pre">		</span>holder.name.setText(name);
<span style="white-space:pre">		</span>holder.number.setText(number);
<span style="white-space:pre">		</span>holder.quickContactBadge.assignContactUri(Contacts.getLookupUri(
<span style="white-space:pre">				</span>contact.getContactId(), contact.getLookUpKey()));
<span style="white-space:pre">		</span>//holder.quickContactBadge.assignContactFromEmail(contact.getEmail(),false);//关联emali
<span style="white-space:pre">		</span>holder.quickContactBadge.setMode(ContactsContract.QuickContact.MODE_SMALL);
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>if (0 == contact.getPhotoId()) {
<span style="white-space:pre">			</span>holder.quickContactBadge.setImageResource(R.drawable.login_icon_member);
<span style="white-space:pre">		</span>} else {
<span style="white-space:pre">			</span>Uri uri = ContentUris.withAppendedId(
<span style="white-space:pre">					</span>ContactsContract.Contacts.CONTENT_URI,
<span style="white-space:pre">					</span>contact.getContactId());
<span style="white-space:pre">			</span>InputStream input = ContactsContract.Contacts
<span style="white-space:pre">					</span>.openContactPhotoInputStream(ctx.getContentResolver(), uri);
<span style="white-space:pre">			</span>Bitmap contactPhoto = BitmapFactory.decodeStream(input);
<span style="white-space:pre">			</span>holder.quickContactBadge.setImageBitmap(contactPhoto);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>// 当前显示的首字母
<span style="white-space:pre">		</span>String currentStr = getAlpha(contact.getSortKey());
<span style="white-space:pre">		</span>// 前面的字母
<span style="white-space:pre">		</span>String previewStr = (position - 1) >= 0 ? getAlpha(list.get(
<span style="white-space:pre">				</span>position - 1).getSortKey()) : " ";


<span style="white-space:pre">		</span>if (!previewStr.equals(currentStr)) {//如果当前显示的首字母和以前的首字母不同
<span style="white-space:pre">			</span>holder.alpha.setVisibility(View.VISIBLE);//显示
<span style="white-space:pre">			</span>holder.alpha.setText(currentStr);
<span style="white-space:pre">		</span>} else {//相同时顶部栏不显示
<span style="white-space:pre">			</span>holder.alpha.setVisibility(View.GONE);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>return convertView;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>private static class ViewHolder {
<span style="white-space:pre">		</span>QuickContactBadge quickContactBadge;
<span style="white-space:pre">		</span>TextView alpha;
<span style="white-space:pre">		</span>TextView name;
<span style="white-space:pre">		</span>TextView number;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 获取首字母
<span style="white-space:pre">	</span> * 
<span style="white-space:pre">	</span> * @param str
<span style="white-space:pre">	</span> * @return
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private String getAlpha(String str) {
<span style="white-space:pre">		</span>if (str == null) {//字母不存在返回为#号
<span style="white-space:pre">			</span>return "#";
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>if (str.trim().length() == 0) {
<span style="white-space:pre">			</span>return "#";
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>char c = str.trim().substring(0, 1).charAt(0);//获取首字母
<span style="white-space:pre">		</span>// 正则表达式匹配(从a到z的字母)
<span style="white-space:pre">		</span>Pattern pattern = Pattern.compile("^[A-Za-z]+$");
<span style="white-space:pre">		</span>if (pattern.matcher(c + "").matches()) {//如果首字母是a-z里面的任一字母
<span style="white-space:pre">			</span>return (c + "").toUpperCase(); // 将小写字母转换为大写
<span style="white-space:pre">		</span>} else {
<span style="white-space:pre">			</span>return "#";
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}</span>
4.最后我们就可以书写mainActivity.java的代码:
<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:14px;"></span></span></div><span style="font-size:14px;">package com.zy.quilkycontact;
import java.util.HashMap;
import java.util.Map;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.SparseArray;
import android.view.View;
import android.view.Window;
import android.widget.ListView;

/**
 * 联系人列表
 * 
 * 
 */
public class MainActivity extends Activity {
<span style="white-space:pre">	</span>private ContactListAdapter adapter;
<span style="white-space:pre">	</span>private ListView contactListView;
<span style="white-space:pre">	</span>private SparseArray<Contact> list;
<span style="white-space:pre">	</span>private AsyncQueryHandler asyncQueryHandler; // 异步查询数据库类对象
<span style="white-space:pre">	</span>private AlphabeticBar alphabeticBar; // 快速索引条
<span style="white-space:pre">	</span>private Map<Integer, Contact> contactIdMap = null;
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>protected void onCreate(Bundle savedInstanceState) {
<span style="white-space:pre">		</span>super.onCreate(savedInstanceState);
<span style="white-space:pre">		</span>requestWindowFeature(Window.FEATURE_NO_TITLE);
<span style="white-space:pre">		</span>setContentView(R.layout.activity_main);
<span style="white-space:pre">		</span>contactListView = (ListView) findViewById(R.id.contact_list);
<span style="white-space:pre">		</span>alphabeticBar = (AlphabeticBar) findViewById(R.id.fast_scroller);
<span style="white-space:pre">		</span>// 实例化
<span style="white-space:pre">		</span>asyncQueryHandler = new MyAsyncQueryHandler(getContentResolver());
<span style="white-space:pre">		</span>initDatas();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 初始化数据库查询参数
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private void initDatas() {
<span style="white-space:pre">		</span>Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; // 联系人Uri;
<span style="white-space:pre">		</span>// 查询的字段
<span style="white-space:pre">		</span>String[] projection = { ContactsContract.CommonDataKinds.Phone._ID,
<span style="white-space:pre">				</span>ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
<span style="white-space:pre">				</span>ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key",
<span style="white-space:pre">				</span>ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
<span style="white-space:pre">				</span>ContactsContract.CommonDataKinds.Phone.PHOTO_ID,
<span style="white-space:pre">				</span>ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY };
<span style="white-space:pre">		</span>// 按照sort_key升序查詢
<span style="white-space:pre">		</span>asyncQueryHandler.startQuery(0, null, uri, projection, null, null,
<span style="white-space:pre">				</span>"sort_key COLLATE LOCALIZED asc");
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 使用异步方式对DB数据库进行基本的增,删,改,查
<span style="white-space:pre">	</span> * */
<span style="white-space:pre">	</span>private class MyAsyncQueryHandler extends AsyncQueryHandler {
<span style="white-space:pre">		</span>public MyAsyncQueryHandler(ContentResolver cr) {
<span style="white-space:pre">			</span>super(cr);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>@SuppressLint("UseSparseArrays") 
<span style="white-space:pre">		</span>protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
<span style="white-space:pre">			</span>if (cursor != null && cursor.getCount() > 0) {
<span style="white-space:pre">				</span>contactIdMap = new HashMap<Integer, Contact>();
<span style="white-space:pre">				</span>list = new SparseArray<Contact>();
<span style="white-space:pre">				</span>cursor.moveToFirst(); // 游标移动到第一项
<span style="white-space:pre">				</span>for (int i = 0; i < cursor.getCount(); i++) {
<span style="white-space:pre">					</span>cursor.moveToPosition(i);
<span style="white-space:pre">					</span>String name = cursor.getString(1);
<span style="white-space:pre">					</span>String number = cursor.getString(2);
<span style="white-space:pre">					</span>String sortKey = cursor.getString(3);//首字母
<span style="white-space:pre">					</span>int contactId = cursor.getInt(4);
<span style="white-space:pre">					</span>Long photoId = cursor.getLong(5);
<span style="white-space:pre">					</span>String lookUpKey = cursor.getString(6);
<span style="white-space:pre">					</span>String email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
<span style="white-space:pre">					</span>if (contactIdMap.containsKey(contactId)) {
<span style="white-space:pre">						</span>// 无操作
<span style="white-space:pre">					</span>} else {
<span style="white-space:pre">						</span>// 创建联系人对象
<span style="white-space:pre">						</span>Contact contact = new Contact();
<span style="white-space:pre">						</span>contact.setDesplayName(name);
<span style="white-space:pre">						</span>contact.setPhoneNum(number);
<span style="white-space:pre">						</span>contact.setSortKey(sortKey);
<span style="white-space:pre">						</span>contact.setPhotoId(photoId);
<span style="white-space:pre">						</span>contact.setLookUpKey(lookUpKey);
<span style="white-space:pre">						</span>contact.setEmail(email);
                        list.put(i, contact);
<span style="white-space:pre">						</span>contactIdMap.put(contactId, contact);
<span style="white-space:pre">					</span>}
<span style="white-space:pre">				</span>}
<span style="white-space:pre">				</span>if (list.size() > 0) {
<span style="white-space:pre">					</span>setAdapter(list);
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>super.onQueryComplete(token, cookie, cursor);
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>private void setAdapter(SparseArray<Contact> list) {
<span style="white-space:pre">		</span>adapter = new ContactListAdapter(this, list, alphabeticBar);
<span style="white-space:pre">		</span>contactListView.setAdapter(adapter);
<span style="white-space:pre">		</span>alphabeticBar.init(MainActivity.this);
<span style="white-space:pre">		</span>alphabeticBar.setListView(contactListView);
<span style="white-space:pre">		</span>alphabeticBar.setHight(alphabeticBar.getHeight());
<span style="white-space:pre">		</span>alphabeticBar.setVisibility(View.VISIBLE);
<span style="white-space:pre">	</span>}
}</span>

好了所有的代码都写完了然后我们的清单文件可别忘记配置了
<div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"><!-- 读联系人权限 --></span></span></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"><uses-permission android:name="android.permission.READ_CONTACTS" /></span></span></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"><!-- 写联系人权限 --></span></span></div><div style="text-align: center;"><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"> <span style="font-size:12px; text-align: justify; white-space: pre; background-color: rgb(240, 240, 240);"><uses-permissio </span>android:name="android.permission.WRITE_CONTACTS" /></span></span></div><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"></span></span><div style="text-align: justify;"><!-- 拨号权限 --></div></div><div style="text-align: justify;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;"><span style="font-size:12px; text-align: justify; white-space: pre; background-color: rgb(240, 240, 240);"><uses-permissio</span> android:name="android.permission.CALL_PHONE" /></span></span></div><span style="font-size:12px;"><!-- 读短信权限 -->
</span><div style="text-align: center;"></div><span style="font-size:12px;"><uses-permission android:name="android.permission.READ_SMS" /></span>
好了,所有的代码也是写完了,我们看下运行效果
技术分享技术分享技术分享
这就是效果,功能还是比较渣渣,那个QuickContactBadge的图像你可以换张好看点的图片,那个弹出的dialog里面3个图标是可以点击的,点了后回去对应的程序里面运行,图不太好截,所以就不给了。
要下源码:请戳》》》下载地址(0积分)

安卓用QuickContactBadge和AsyncQueryHandler实现联系人列表的完美实现

标签:android   自定义控件   quickcontactbadge   sparsearray   asyncqueryhandler   

原文地址:http://blog.csdn.net/u013278099/article/details/45335299

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!