实现一个android拨号联系人

来源:互联网 发布:淘宝的安佳牛奶 编辑:程序博客网 时间:2024/05/02 06:11

工作之余捣鼓了一个类似安卓联系人的小应用,记录一下。


能够导入手机上的联系人并按拼音首字母排序,实现字母的索引。


有的算法很笨很麻烦,还得加油。


实现效果如下:




首先定义一个PeopleLoader类,用来读取联系人相关的姓名、电话:

public class PeopleLoader {

private static List<PeopleInfo> peopleList = new ArrayList<PeopleInfo>();//存储联系人对象的List


private static PeopleLoader peopleLoader;

private static ContentResolver contentResolver;//使用ContentResolver查询需要的数据

private Uri contentUri = Contacts.CONTENT_URI;//该URI用来查询联系人信息

public static PeopleLoader instance(ContentResolver pContentResolver){
if(peopleLoader == null){
contentResolver = pContentResolver;
peopleLoader = new PeopleLoader();
}
return peopleLoader;
}

public List<PeopleInfo> getPeopleList(){
return sort(peopleList);
}

public  String getPinYinHeadChar(String str) {//该方法用来获取联系人姓名首个汉字的首个拼音,需要在项目中导入pinyin4j的包
        
String convert = "";
        char word = str.charAt(0);
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
        if(pinyinArray != null){
        convert += pinyinArray[0].charAt(0); 
        }else{
        convert += word;
        }
        return convert;   
    }

public List<PeopleInfo> sort(List<PeopleInfo> l){//对获取的PeopleList重新排序
List<PeopleInfo> newList = new ArrayList<PeopleInfo>();
int[] position = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27};//该数组是插入数据的标志位0-26对应a-z、#
for(int i=0; i<27; i++){//该循环插入A-Z、#,联系人会根据首个拼音插在相应栏目下方
if(i!=26){
char A = (char) (65+i);
newList.add(new PeopleInfo(String.valueOf(A), String.valueOf(A)));
}else{
newList.add(new PeopleInfo("#", "#"));
}
}
for(int i=0; i<l.size(); i++){//将联系人插入相应栏目,应该注意各个标志位的增加(希望有人能教我简单点的方法,感觉很麻烦)
String first = getPinYinHeadChar(l.get(i).getName());
switch (first){
case "a":
newList.add(position[0], l.get(i));
newList.get(position[0]).setId("a");
for(int j=0; j<27; j++){
position[j]++;
}
break;
case "b":
newList.add(position[1], l.get(i));
newList.get(position[1]).setId("b");
for(int j=0; j<27; j++){
position[j]++;
}
break;
case "c":
newList.add(position[2], l.get(i));
newList.get(position[2]).setId("c");
for(int j=2; j<27; j++){
position[j]++;
}
break;
case "d":
newList.add(position[3], l.get(i));
newList.get(position[3]).setId("d");
for(int j=3; j<27; j++){
position[j]++;
}
break;
case "e":
newList.add(position[4], l.get(i));
newList.get(position[4]).setId("e");
for(int j=4; j<27; j++){
position[j]++;
}
break;
case "f":
newList.add(position[5], l.get(i));
newList.get(position[5]).setId("f");
for(int j=5; j<27; j++){
position[j]++;
}
break;
case "g":
newList.add(position[6], l.get(i));
newList.get(position[6]).setId("g");
for(int j=6; j<27; j++){
position[j]++;
}
break;
case "h":
newList.add(position[7], l.get(i));
newList.get(position[7]).setId("h");
for(int j=7; j<27; j++){
position[j]++;
}
break;
case "i":
newList.add(position[8], l.get(i));
newList.get(position[8]).setId("i");
for(int j=8; j<27; j++){
position[j]++;
}
break;
case "j":
newList.add(position[9], l.get(i));
newList.get(position[9]).setId("j");
for(int j=9; j<27; j++){
position[j]++;
}
break;
case "k":
newList.add(position[10], l.get(i));
newList.get(position[10]).setId("k");
for(int j=10; j<27; j++){
position[j]++;
}
break;
case "l":
newList.add(position[11], l.get(i));
newList.get(position[11]).setId("l");
for(int j=11; j<27; j++){
position[j]++;
}
break;
case "m":
newList.add(position[12], l.get(i));
newList.get(position[12]).setId("m");
for(int j=12; j<27; j++){
position[j]++;
}
break;
case "n":
newList.add(position[13], l.get(i));
newList.get(position[13]).setId("n");
for(int j=13; j<27; j++){
position[j]++;
}
break;
case "o":
newList.add(position[14], l.get(i));
newList.get(position[14]).setId("o");
for(int j=14; j<27; j++){
position[j]++;
}
break;
case "p":
newList.add(position[15], l.get(i));
newList.get(position[15]).setId("p");
for(int j=15; j<27; j++){
position[j]++;
}
break;
case "q":
newList.add(position[16], l.get(i));
newList.get(position[16]).setId("q");
for(int j=16; j<27; j++){
position[j]++;
}
break;
case "r":
newList.add(position[17], l.get(i));
newList.get(position[17]).setId("r");
for(int j=17; j<27; j++){
position[j]++;
}
break;
case "s":
newList.add(position[18], l.get(i));
newList.get(position[18]).setId("s");
for(int j=18; j<27; j++){
position[j]++;
}
break;
case "t":
newList.add(position[19], l.get(i));
newList.get(position[19]).setId("t");
for(int j=19; j<27; j++){
position[j]++;
}
break;
case "u":
newList.add(position[20], l.get(i));
newList.get(position[20]).setId("u");
for(int j=20; j<27; j++){
position[j]++;
}
break;
case "v":
newList.add(position[21], l.get(i));
newList.get(position[21]).setId("v");
for(int j=21; j<27; j++){
position[j]++;
}
break;
case "w":
newList.add(position[22], l.get(i));
newList.get(position[22]).setId("w");
for(int j=22; j<27; j++){
position[j]++;
}
break;
case "x":
newList.add(position[23], l.get(i));
newList.get(position[23]).setId("x");
for(int j=23; j<27; j++){
position[j]++;
}
break;
case "y":
newList.add(position[24], l.get(i));
newList.get(position[24]).setId("y");
for(int j=24; j<27; j++){
position[j]++;
}
break;
case "z":
newList.add(position[25], l.get(i));
newList.get(position[25]).setId("z");
for(int j=25; j<27; j++){
position[j]++;
}
break;
default:
newList.add(position[26], l.get(i));
newList.get(position[26]).setId("#");
position[26]++;
break;
}
}
return newList;//返回排序后的PeopleList

}

private PeopleLoader(){
Cursor cursor = contentResolver.query(contentUri, new String[]{Contacts._ID,Contacts.DISPLAY_NAME}, null, null, null);//获得所有联系人游标
if(cursor == null){//判断游标

}else if(!cursor.moveToFirst()){//将游标返回到第一项,可以不用else if

}else{
int mName = cursor.getColumnIndex(Contacts.DISPLAY_NAME);//获取联系人名字所在列号
do{//将所有数据存入PeopleList
String name = cursor.getString(mName);//根据列号获取名字
int ID = cursor.getInt(cursor.getColumnIndex(Contacts._ID));//根据联系人id列号获取联系人id
Cursor c1 = contentResolver.query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, 
Phone.CONTACT_ID+"="+ID, null, null);//根据id获取联系人电话

PeopleInfo peopleInfo = new PeopleInfo("", name);//以下插入数据到PeopleList
if(c1!=null){
while(c1.moveToNext()){
peopleInfo.setPhone(c1.getString(c1.getColumnIndex(Phone.NUMBER)));
}
}
//peopleInfo.setPhone(c1.getString(c1.getColumnIndex(Phone.NUMBER)));
peopleList.add(peopleInfo);
}while(cursor.moveToNext());


}
cursor.close();
}


//PeopleInfo实现parcelable接口,用来保存联系人的信息:


static class PeopleInfo implements Parcelable{

private String name;
private String phone;
private String id;//此处id值是后面判断的一个标志

public String getId(){
return id;
}

public String getName(){
return name;
}

public String getPhone(){
return phone;
}

public PeopleInfo(){

}

public PeopleInfo(String pId, String pName){
id = pId;
name = pName;
}

public void setId(String id){
this.id = id;
}

public void setName(String name){
this.name = name;
}

public void setPhone(String phone){
this.phone = phone;
}

//要实现的三个方法
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}


@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(id);
dest.writeString(name);
dest.writeString(phone);
}

public static final Parcelable.Creator<PeopleInfo> 
CREATOR = new Creator<PeopleLoader.PeopleInfo>(){


@Override
public PeopleInfo createFromParcel(Parcel source) {
// TODO Auto-generated method stub
PeopleInfo peopleInfo = new PeopleInfo();
peopleInfo.setId(source.readString());
peopleInfo.setName(source.readString());
peopleInfo.setPhone(source.readString());
return peopleInfo;
}


@Override
public PeopleInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new PeopleInfo[size];
}

};

}
}


MainActivity中代码如下:


public class MainActivity extends Activity {


    private  GroupListAdapter adapter = null;
    private ListView listView = null;
    public List<String> listName = new ArrayList<String>();
    public static List<String> listPhone = new ArrayList<String>();
    private List<PeopleInfo> peopleList;
    
    private LinearLayout layoutIndex;
    private boolean flag = false; 
    private int height;
    private String[] indexStr = {"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", "#" };
    
    class GroupListAdapter extends BaseAdapter{//定义一个适配器继承BaseAdapter


    private View.OnClickListener myListener = new View.OnClickListener() {//实现一个OnClickListener用来监听点击的对象,避免重复new多个监听器

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
if(v.getId() == R.id.ivPhn){//根据id判断是拨号还是发短信
intent.setAction(Intent.ACTION_CALL);
}else{
intent.setAction(Intent.ACTION_SENDTO);
//intent.putExtra("smsto:", "Hello");
}
intent.setData(Uri.parse(v.getTag().toString()));//去除Tag中存入的相应Uri
startActivity(intent);
}
};
   
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
       
        if(convertView == null){
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.group_list_item,null);
ImageView photo = (ImageView) convertView.findViewById(R.id.iv);
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView phone = (TextView) convertView.findViewById(R.id.phone);
ImageView btnCall = (ImageView) convertView.findViewById(R.id.ivPhn);
ImageView btnMsg = (ImageView) convertView.findViewById(R.id.ivMsg); 
viewHolder = new ViewHolder(photo, name, phone, btnCall, btnMsg);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder)convertView.getTag();
}
       
        if(peopleList.get(position).getName().length()==1){//判断是不是A-Z、#等栏目标题(此处应该有更得体的方法而不是简单的判定长度,毕竟用户也有可能输入长度为1的对象)
       
        viewHolder.name.setText(peopleList.get(position).getName());//设置完显示的A-Z、#字母后,简单的将其他对象置为空,应该可以用setVisible一类的方法让其直接消失
        viewHolder.phone.setText(null);
        viewHolder.photo.setImageResource(0);
        viewHolder.btnCall.setImageResource(0);
        viewHolder.btnMsg.setImageResource(0);
       
        viewHolder.btnCall.setOnClickListener(null);
        viewHolder.btnMsg.setOnClickListener(null);
       
        viewHolder.name.setTextSize(40);
        }else{//不是字母标题栏则插入相应联系人数据
       
        viewHolder.name.setTextSize(15);
        viewHolder.photo.setImageResource(0);
        //viewHolder.photo.setImageResource(R.drawable.list_icon);
        viewHolder.btnCall.setImageResource(R.drawable.call);
        viewHolder.btnMsg.setImageResource(R.drawable.msg);
       
        viewHolder.name.setText(peopleList.get(position).getName());
        viewHolder.phone.setText(peopleList.get(position).getPhone());

        viewHolder.btnCall.setTag( "tel:"+peopleList.get(position).getPhone());//将拨号、发短信要用到的数据存入Tag


        viewHolder.btnMsg.setTag( "smsto:"+peopleList.get(position).getPhone());


        viewHolder.btnCall.setOnClickListener(myListener);//设置监听
        viewHolder.btnMsg.setOnClickListener(myListener);
        }
return convertView;
        }


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


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


@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
    }
    
    class ViewHolder{
public ViewHolder(ImageView photo,TextView name, TextView phone, ImageView call, ImageView msg){
this.photo = photo;
this.name = name;
this.phone = phone;
this.btnCall = call;
this.btnMsg = msg;
}
ImageView photo;
TextView name;
TextView phone;
ImageView btnCall;
ImageView btnMsg;
}

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

layoutIndex = (LinearLayout)findViewById(R.id.layout); //该layout用来插入右侧字母索引

PeopleLoader peopleLoader = PeopleLoader.instance(getContentResolver());
peopleList = peopleLoader.getPeopleList();

adapter = new GroupListAdapter();
                listView = (ListView)findViewById(R.id.group_list);
                 listView.setAdapter(adapter);
      

}

@Override  
public void onWindowFocusChanged(boolean hasFocus) {  
       if (!flag) {// flag确保if内容只执行一次,避免重复操作 
           height = layoutIndex.getMeasuredHeight() / indexStr.length; //高度/数据项数目得到每个TextView的长宽
           getIndexView();  
           flag = true;  
       }  
   }


private void getIndexView() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, height);  
       for (int i = 0; i < indexStr.length; i++) { //此循环插入字母索引
           final TextView tv = new TextView(this);  
           tv.setLayoutParams(params);  //设置插入TextView参数
           tv.setText(indexStr[i]);  
           tv.setPadding(10, 0, 10, 0);  
           layoutIndex.addView(tv);  
          
           layoutIndex.setOnTouchListener(new OnTouchListener() { //设置监听,让触摸某个字母索引时,ListView定位到相应字母栏
 
               @Override  
               public boolean onTouch(View v, MotionEvent event)  
 
               {  
                   float y = event.getY();  
                   int index = (int) (y / height);  
                   if (index > -1 && index < indexStr.length) {// 防止越界 
                       String key = indexStr[index];
                       for(int i=0; i<peopleList.size(); i++){
                       if(peopleList.get(i).getName().equalsIgnoreCase(key)&&peopleList.get(i).getId().equalsIgnoreCase(key)){//找到相应的字母栏(此处应有简单方法,很麻烦)
                       listView.setSelectionFromTop(i, 0); // 滑动到第一项 
                       break;
                       }
                       }
                        
                         
                         
                   }  
                   return true;  
               }  
           });  
       } 


}


学到了contentresolver对象、Parcelable接口、适配器的使用,listview的布局,根据拼音首字母的索引,侧边索引的实现。

布局文件没贴了,下载链接http://download.csdn.net/detail/u012951394/8938043

0 0
原创粉丝点击