Android中索引关联联系人

时间:2022-08-31 23:49:37

今天,我将和大家分享如何在Android实现索引,并使用索引来关联电话联系人。

如果从头来说,可能需要很大的篇幅来讲解,我就长话短说,将原理告诉大家,并将核心代码贴出来,供大家参考。

一、实现索引

我们使用重写View的方式来实现索引。即继承View后,重写onDraw(Canvas canvas)方法将A-Z的字母使用Paint绘制出来,代码很简单,其中的核心点就是获取屏幕高度和宽度,并根据A-Z的字母长度来平均的画出来;实现onTouchEvent事件,并根据触摸的变化,来改变显示的状态。下面是实现代码:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


/**
 * 索引View
 * @author 宋小亮
 *
 */
public class IndexView extends View{


private int speration;//字母间距

private String[] word = new String[26];

private Paint paint;//画笔

private OnIndexListener onIndexListener;

public IndexView(Context context) {
super(context);
initViews();
}


public IndexView(Context context, AttributeSet attrs) {
super(context, attrs);
initViews();
}

public IndexView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initViews();
}



@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

//求出字母间距

int screenHight = this.getHeight();
int screenWidth = this.getWidth();

//字母之间的间隙大小
speration = screenHight/word.length;

//绘制字母
for (int i = 0; i < word.length; i++) {

canvas.drawText(word[i], screenWidth - getFontWidth(word[i]) >> 1, speration * (i + 1), paint);

}

}

/**
* 触摸字母事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch(action){
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float y = event.getY();
int index = (int)(y/speration);

if(index >= word.length){
index = word.length - 1 ;
}

String text = word[index];
//调用回调事件,显示TextView
onIndexListener.show(text);
break;
case MotionEvent.ACTION_UP:
//调用回调事件,隐藏TextView
onIndexListener.hide();
default:
break;
}

return true;
}


/**
*初始化view 
*/
private void initViews() {

//初始化字母
for (int i = 0; i < word.length; i++) {
word[i] = (char) (65+i) + "";

}

//初始化画笔,设置画笔属性
paint = new Paint();
paint.setTextSize(20.0f);
paint.setColor(0xff000000);

}

/**

* 得到字体的宽度

* @param str
* @return
*/
private int getFontWidth(String word) {

Rect rect = new Rect();
paint.getTextBounds(word, 0, word.length(), rect);
return rect.width();
}

/**
* 回调接口
* @author lenovo
*
*/
public interface OnIndexListener{
public void show(String word);
public void hide();
}

/**
* 设值回调
* @param onIndexListener
*/
public void setOnIndexListener(OnIndexListener onIndexListener){
this.onIndexListener = onIndexListener;
}


}

二、联系人

在Android中,我们都知道使用ContentResolver根据Contact Uri来查询系统联系人。返回的结果是一个Cursor结果集,通过该结果集,我们就可以获取联系人姓名,电话,头像,等等。

/** 得到手机通讯录联系人信息 **/
private void initDatas() {
//获取手机联系人
ContentResolver cr = this.getContentResolver();
Cursor cursor = cr.query(Phone.CONTENT_URI, PHONE_PROJECTION, null, null, null);
if(cursor != null){
while(cursor.moveToNext()){
/**手机号**/
String phoneNumber = cursor.getString(PHONES_NUMBER_INDEX);
/**得到联系人名称**/
String contactName = cursor.getString(PHONES_DISPLAY_NAME_INDEX);
/**联系人ID**/
Long contactId = cursor.getLong(PHONES_CONTACT_ID_INDEX);

/**联系人头像ID**/
Long contactPhotoId = cursor.getLong(PHONES_PHOTO_ID_INDEX);

Bitmap contactBm = null;

if(contactPhotoId > 0){
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactPhotoId);
InputStream is = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);

contactBm = BitmapFactory.decodeStream(is);
}else{
contactBm = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);;
}

mContactsName.add(contactName);
mContactsNumber.add(phoneNumber);
mContactsPhonto.add(contactBm);
}
}


}

此时,在获取完结果后,我们需要对结果进行排序,此时,我们使用了第三方的一个Jar包,(pinyin4j-2.5.0.jar )通过该jar包可以起送的实现中文转拼音,拼音转中文,两者之间的切换。

package com.example.t3;


import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;


/**
 * 
 * 中文拼音工具类
 * 
 * 
 * @author 宋小亮
 * 
 */
public class PingYinUtil {
/**
* 将字符串中的中文转化为拼音,其他字符不变

* 张三--->zhangsan

* @param inputString
* @return
*/
public static String getPingYin(String inputString) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);


char[] input = inputString.trim().toCharArray();
String output = "";


try {
for (int i = 0; i < input.length; i++) {
if (java.lang.Character.toString(input[i]).matches(
"[\\u4E00-\\u9FA5]+")) {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(
input[i], format);
output += temp[0];
} else
output += java.lang.Character.toString(input[i]);
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return output;
}


/**
* 汉字转换位汉语拼音首字母,英文字符不变


* 张三--->ZS

* @param chines
*            汉字
* @return 拼音
*/
public static String converterToFirstSpell(String chines) {
String pinyinName = "";
char[] nameChar = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < nameChar.length; i++) {
if (nameChar[i] > 128) {
try {
pinyinName += PinyinHelper.toHanyuPinyinStringArray(
nameChar[i], defaultFormat)[0].charAt(0);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinyinName += nameChar[i];
}
}
return pinyinName;
}
}

在我们根据联系人名称获取到首字母进行排序,并得到排序后的结果,此时我们就完成了该功能,其中的难点是:将联系人名称转换为拼音,并根据首字母进行排序;下面是核心代码:

package com.example.t3;


import java.io.InputStream;
import java.util.ArrayList;


import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;


import com.example.t3.view.IndexView;
import com.example.t3.view.IndexView.OnIndexListener;




public class MainActivity extends Activity implements OnIndexListener{


private TextView tv_show;
private ListView lv_contact;
private IndexView indexView;

private String[] title;
private static final String[] PHONE_PROJECTION = new String[]{
Phone.DISPLAY_NAME,Phone.NUMBER,Photo.PHOTO_ID,Phone.CONTACT_ID
};

/** 联系人显示名称 **/
private static final int PHONES_DISPLAY_NAME_INDEX = 0;


/** 电话号码 **/
private static final int PHONES_NUMBER_INDEX = 1;


/** 头像ID **/
private static final int PHONES_PHOTO_ID_INDEX = 2;


/** 联系人的ID **/
private static final int PHONES_CONTACT_ID_INDEX = 3;

/** 联系人名称 **/
private ArrayList<String> mContactsName = new ArrayList<String>();


/** 联系人号码 **/
private ArrayList<String> mContactsNumber = new ArrayList<String>();


/** 联系人头像 **/
private ArrayList<Bitmap> mContactsPhonto = new ArrayList<Bitmap>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initDatas();


title = new String[mContactsName.size()];
DataInit();
MyAdapter adapter = new MyAdapter();
lv_contact.setAdapter(adapter);
}


/** 得到手机通讯录联系人信息 **/
private void initDatas() {
//获取手机联系人
ContentResolver cr = this.getContentResolver();
Cursor cursor = cr.query(Phone.CONTENT_URI, PHONE_PROJECTION, null, null, null);
if(cursor != null){
while(cursor.moveToNext()){
/**手机号**/
String phoneNumber = cursor.getString(PHONES_NUMBER_INDEX);
/**得到联系人名称**/
String contactName = cursor.getString(PHONES_DISPLAY_NAME_INDEX);
/**联系人ID**/
Long contactId = cursor.getLong(PHONES_CONTACT_ID_INDEX);

/**联系人头像ID**/
Long contactPhotoId = cursor.getLong(PHONES_PHOTO_ID_INDEX);

Bitmap contactBm = null;

if(contactPhotoId > 0){
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactPhotoId);
InputStream is = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);

contactBm = BitmapFactory.decodeStream(is);
}else{
contactBm = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);;
}

mContactsName.add(contactName);
mContactsNumber.add(phoneNumber);
mContactsPhonto.add(contactBm);
}
}


}
public void DataInit() {
// 中文排序
// Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
// Arrays.sort(name, cmp);
for (int i = 0; i < mContactsName.size(); i++) {
String str = PingYinUtil.converterToFirstSpell(mContactsName.get(i)
.substring(0, 1));
title[i] = str;
}


for (int i = 0; i < title.length; i++) {
for (int j = i + 1; j < title.length; j++) {
if (title[i].charAt(0) > title[j].charAt(0)) {
String str = title[i];
title[i] = title[j];
title[j] = str;

String str2 = mContactsName.get(i);
mContactsName.set(i, mContactsName.get(j));
mContactsName.set(j, str2);

String str3 = mContactsNumber.get(i);
mContactsNumber.set(i, mContactsNumber.get(j));
mContactsNumber.set(j, str3);

Bitmap temp = mContactsPhonto.get(i);
mContactsPhonto.set(i, mContactsPhonto.get(j));
mContactsPhonto.set(j, temp);
}
}
}
}
private void initViews() {
tv_show = (TextView)findViewById(R.id.tv1);
lv_contact = (ListView)findViewById(R.id.lv_contact);
indexView = (IndexView)findViewById(R.id.indexView);
indexView.setOnIndexListener(this);


}


@Override
public void show(String word) {
tv_show.setText(word);
tv_show.setVisibility(View.VISIBLE);

for (int i = 0; i < title.length; i++) {
if(title[i].equals(word)){
lv_contact.setSelection(i);
break;
}
}
}


@Override
public void hide() {
tv_show.setVisibility(View.GONE);
}


public class MyAdapter extends BaseAdapter{


@Override
public int getCount() {
// TODO Auto-generated method stub
return mContactsName.size();
}


@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return mContactsName.get(position);
}


@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}


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


if (convertView == null) {


convertView = getLayoutInflater().inflate(R.layout.list_item,
null);


viewOptimize = new ViewOptimize();


viewOptimize.tv_name = (TextView) convertView
.findViewById(R.id.dianhua_name);


viewOptimize.tv_phonoNum = (TextView) convertView
.findViewById(R.id.dianhua_number);


viewOptimize.img_photo = (ImageView) convertView
.findViewById(R.id.dianhua_photo);


viewOptimize.tv_title = (TextView) convertView
.findViewById(R.id.title);
convertView.setTag(viewOptimize);
} else {
viewOptimize = (ViewOptimize) convertView.getTag();
}


String text = mContactsName.get(position);
viewOptimize.tv_name.setText(text);
viewOptimize.tv_phonoNum.setText(mContactsNumber.get(position));
// if (mContactsPhonto.get(position) == null) {
// Log.e("  ", "  2222222222222222");
// }
viewOptimize.img_photo
.setImageBitmap(mContactsPhonto.get(position));
String str2 = title[position];
if (position > 0) {
String str1 = title[position - 1];
if (str2.equals(str1)) {
viewOptimize.tv_title.setVisibility(View.GONE);
} else {
viewOptimize.tv_title.setVisibility(View.VISIBLE);
viewOptimize.tv_title.setText(str2);
}
} else {
viewOptimize.tv_title.setVisibility(View.VISIBLE);
viewOptimize.tv_title.setText(str2);
}
return convertView;

}
public class ViewOptimize {


TextView tv_title;


TextView tv_name;


/** 电话号码 */
TextView tv_phonoNum;
/** 头像 */
ImageView img_photo;


}


}

}

到此为止,我们就轻松实现了炫酷的功能!

Android中索引关联联系人