今天,我将和大家分享如何在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;
}
}
}
到此为止,我们就轻松实现了炫酷的功能!