二、友录项目-联系人界面搭建

来源:互联网 发布:protel软件下载流程 编辑:程序博客网 时间:2024/06/12 23:58

本节实现的内容为:

进入默认的页面为联系人页面,接下来需要完善联系人页面。联系人页面功能为:

1,手机中所有联系人均以网格状排布在本页面中。

2,能正确显示联系人对应的头像,名字,无头像使用默认头像。

3,能添加新的联系人。

-------------------------------------------------------------------------------------------------------

在ContactFragment中要以网格形式显示联系人,首先我们需要构建布局文件,可以用一个linearlayout内嵌套一个标题栏和gridview

布局文件:

<LinearLayout     .....................

    >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal" 
        android:background="#ff000000">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:textColor="#ffffffff"
            android:textSize="20sp"
            android:text="联系人" />
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="10dp"
            android:src="@drawable/ic_search" />
    </RelativeLayout>
<GridView 
   android:id="@+id/gv_contact_gridview"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:numColumns="3"
   ></GridView>
</LinearLayout>

GridView 中的小条目布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ImageView 
        android:id="@+id/ivphoto_contact_item"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@drawable/ic_launcher"
        android:layout_gravity="center_horizontal"/>
<TextView 
   android:id="@+id/tvname_contact_item"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="张三"
   android:textSize="15dp"
   android:layout_gravity="center_horizontal"/>
</LinearLayout>

构建好联系人布局页面后,接下来就是往页面中填充数据了,需要

1,初始化ContactFragment

2,数据源联系人的一个实体类Contact,将联系人信息装入List<Contact> contacts 中,,

3,将条目一一对应填充进去需要一个适配器ContactAdapter,

4,另外还需要一个处理和联系人业务功能相关的业务类ContactBiz,

5,具体业务功能实现类util


具体如下:

1,ContactFragment初始化:

public class ContactFragment extends Fragment {
GridView gridView;

List<Contact> contacts;
ContactAdapter adapter;

ContactBiz biz;
public ContactFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.fragment_contact, container, false);
biz = new ContactBiz(getActivity());
initGridView(view);

return view;
}
private void initGridView(View view) {
gridView=(GridView) view.findViewById(R.id.gv_contact_gridview);
contacts=new ArrayList<Contact>();
adapter=new ContactAdapter(getActivity(),contacts);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new OnItemClickListener() {


@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
//将第一个位置设置为添加联系人的功能
if (position==0) {
//发送一个intent ,打开安卓系统的添加联系人页面,以下代码是安卓官方规定的访问方法
Intent intent=new Intent(ContactsContract.Intents.Insert.ACTION);
intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
//API15以后添加联系人界面有bug,点击完成无法回到我们的app,故添加如下代码
intent.putExtra("finishActivityOnSaveCompleted", true);
startActivity(intent);
}else{
Contact contact=adapter.getItem(position);
biz.showDetail(contact);
}

}
});
//添加长按监听器,长按则删除联系人
gridView.setOnItemLongClickListener(new OnItemLongClickListener() {


@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
if (position>0) {
Contact contact=adapter.getItem(position);
biz.showDelete(contact,adapter);
}
return true;
}
});

}
@Override
public void onResume() {
super.onResume();
refresh();
}
private void refresh() {
//异步刷新
biz.asyncGetAllContacts(new OnLoadContactsFinishListener() {

@Override
public void onLoadFinish(List<Contact> contacts) {
adapter.addAll(contacts, true);
}

});

}
}

2,联系人实体类Contact:

public class Contact {
private int _id;//联系人id
private String name;//联系人姓名
private String number;//联系人电话号码
private String email;//联系人邮件
private String address;//联系人地址
private String company;//联系人公司
private int photo_id;//联系人头像
private String lookupKey;//
//get,set方法可由系统生成
},

3,适配器的创建ContactAdapter

public class ContactAdapter extends BaseAdapter{
Context context;
List<Contact> contacts;
LayoutInflater inflater;
ContactBiz biz;
public ContactAdapter(Context context, List<Contact> contacts) {
super();
this.context = context;
this.contacts = contacts;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
biz = new ContactBiz(context);
}
@Override
public int getCount() {
return contacts.size();
}
@Override
public Contact getItem(int position) {
return contacts.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder vh;
if(convertView==null){
convertView = inflater.inflate(R.layout.contact_gridview_item, parent,false);
vh = new ViewHolder();
vh.ivAvatar = (ImageView) convertView.findViewById(R.id.ivphoto_contact_item);
vh.tvName = (TextView) convertView.findViewById(R.id.tvname_contact_item);
convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
}
Contact contact = getItem(position);
vh.tvName.setText(contact.getName());
//根据contact对象的photo_id属性,去获得头像图片
if(position==0){
//如果是第一个联系人,头像用"加号"
vh.ivAvatar.setImageResource(R.drawable.ic_add_contact);
}else{
// vh.ivAvatar.setImageBitmap(biz.getAvatar(contact.getPhoto_id()));
biz.asyncGetAvatar(contact.getPhoto_id(), new OnLoadAvatarFinishListener() {

@Override
public void onLoadAvatarFinish(Bitmap bitmap) {
vh.ivAvatar.setImageBitmap(bitmap);
}
});
}
return convertView;
}
public void addAll(List<Contact> list,boolean isClear){
if(isClear){
contacts.clear();
}
contacts.addAll(list);
notifyDataSetChanged();
}
public void remove(Contact contact){
contacts.remove(contact);
notifyDataSetChanged();
}
public class ViewHolder{
TextView tvName;
ImageView ivAvatar;
}
}

3,创建业务类ContactBiz

public class ContactBiz {
private Context context;
public ContactBiz(Context context){
this.context = context;
}
/**
* 获取设备上所有的联系人信息
* 并且按照姓名排序

* @return
*/
public List<Contact> getAllContacts(){
List<Contact> list = YouluUtil.getAllContacts(context);
Collections.sort(list,new Comparator<Contact>() {
@Override
public int compare(Contact lhs, Contact rhs) {
return lhs.getName().toUpperCase().compareTo(rhs.getName().toUpperCase());
}
});
Contact contact = new Contact();
contact.setName("添加联系人");
list.add(0,contact);
return list;
}

//以下具体方法均丢给具体实现功能类YouluUtil去实现
public void showDelete(Contact contact,ContactAdapter adapter) {
YouluUtil.showDelete(context,contact,adapter);
}
public void asyncGetAllContacts(OnLoadContactsFinishListener listener){
YouluUtil.asyncGetAllContacts(context, listener);
}
public void asyncGetAvatar(int photoId,OnLoadAvatarFinishListener listener){
YouluUtil.asyncGetAvatar(context, photoId, listener);
}
public void showDetail(Contact contact) {
YouluUtil.showDetail(context,contact);

}
}

4,YouluUtil具体功能实现类

public class YouluUtil {

//使用缓存加载,提高效率
private static int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
public static LruCache<Integer, Bitmap> cache = new LruCache<Integer, Bitmap>(maxSize){
protected int sizeOf(Integer key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
};
};
public static List<Contact> getAllContacts(Context context) {
List<Contact> contacts = new ArrayList<Contact>();
ContentResolver cr = context.getContentResolver();
//从contacts数据表中查询回来的全部内容
Cursor cursor = cr.query(Contacts.CONTENT_URI, new String[]{Contacts._ID,Contacts.PHOTO_ID,Contacts.LOOKUP_KEY}, null, null, null);
while(cursor.moveToNext()){
Contact contact = new Contact();
contact.set_id(cursor.getInt(0));
contact.setPhoto_id(cursor.getInt(1));
contact.setLookupKey(cursor.getString(2));
//从Data表中查询这个联系人的姓名、电话、邮件等详细信息
ContentResolver cr2 = context.getContentResolver();
Cursor c = cr2.query(Data.CONTENT_URI, 
new String[]{Data.MIMETYPE,Data.DATA1}, 
Data.RAW_CONTACT_ID + " = ?", 
new String[]{String.valueOf(contact.get_id())}, 
null);
while(c.moveToNext()){
String mimeType = c.getString(0);
if(mimeType.equals("vnd.android.cursor.item/email_v2")){
contact.setEmail(c.getString(1));
}else if(mimeType.equals("vnd.android.cursor.item/organization")){
contact.setCompany(c.getString(1));
}else if(mimeType.equals("vnd.android.cursor.item/phone_v2")){
contact.setNumber(c.getString(1));
}else if(mimeType.equals("vnd.android.cursor.item/name")){
contact.setName(c.getString(1));
}else if(mimeType.equals("vnd.android.cursor.item/postal-address_v2")){
contact.setAddress(c.getString(1));
}
}
c.close();
contacts.add(contact);
}
cursor.close();
return contacts;
}
public static void showDelete(final Context context, final Contact contact,
final ContactAdapter adapter) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(android.R.drawable.ic_menu_info_details);
builder.setTitle("确认删除");
builder.setMessage("您确实要删除"+contact.getName()+"吗?");
builder.setNegativeButton("再想想", null);
builder.setPositiveButton("删之", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//删除联系人的具体逻辑
//删除不能直接删除contacts表中该联系人的内容
//而是去删除raw_contacts和data表中该联系人的内容
ContentResolver cr = context.getContentResolver();
//从raw_contacts表中删除内容
cr.delete(ContactsContract.RawContacts.CONTENT_URI,
RawContacts.CONTACT_ID + " = ?", 
new String[]{String.valueOf(contact.get_id())});
//从data表中删除内容
cr.delete(ContactsContract.Data.CONTENT_URI, 
Data.CONTACT_ID + " = ?", 
new String[]{String.valueOf(contact.get_id())});
adapter.remove(contact);
}
});
builder.create().show();
}
public static void asyncGetAllContacts(final Context context,
final OnLoadContactsFinishListener listener) {
new AsyncTask<Void, Void, List<Contact>>() {
@Override
protected List<Contact> doInBackground(Void... params) {
return getAllContacts(context);
}
protected void onPostExecute(List<Contact> result) {
//1)排序
Collections.sort(result, new Comparator<Contact>() {
@Override
public int compare(Contact lhs, Contact rhs) {
return lhs.getName().toUpperCase().compareTo(rhs.getName().toUpperCase());
}
});
//2)添加"添加联系人"
Contact contact = new Contact();
contact.setName("添加联系人");
result.add(0,contact);
//3)利用接口来"通知"GridView去刷新界面
listener.onLoadFinish(result);
};
}.execute();

}
public static void asyncGetAvatar(final Context context, final int photoId,
final OnLoadAvatarFinishListener listener) {
new AsyncTask<Void, Void, Bitmap>(){
@Override
protected Bitmap doInBackground(Void... params) {
return getAvatar(context, photoId);
}
protected void onPostExecute(Bitmap result) {
listener.onLoadAvatarFinish(result);
};
}.execute();
}
protected static Bitmap getAvatar(Context context, int photoId) {
//优先从缓存中取photoId所对应的头像图片
Bitmap bitmap = cache.get(photoId);
if(bitmap==null){
if(photoId==0){
//没有为联系人设置头像
//手动指定一个头像
//bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
bitmap = getMyAvatar(context);
//把头像存储到缓存中
cache.put(photoId, bitmap);
}else{
//有头像,DATA数据表中的data15列
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(Data.CONTENT_URI, 
new String[]{Data.DATA15}, 
Data._ID + " = ?", 
new String[]{String.valueOf(photoId)}, 
null);
cursor.moveToNext();//指向第一条数据
byte[] bytes = cursor.getBlob(0);
//方形图
Bitmap avatar = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
cursor.close();
bitmap = getCircleAvatar(context,avatar);
//把获得的头像放到缓存中存储起来
cache.put(photoId, bitmap);
}
}
return bitmap;
}
private static Bitmap getCircleAvatar(Context context, Bitmap avatar) {
Bitmap bitmap = Bitmap.createBitmap(avatar.getWidth(), avatar.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
float radius = Math.min(avatar.getWidth(), avatar.getHeight())/2;
//混合模式中的DST
canvas.drawCircle(avatar.getWidth()/2, avatar.getHeight()/2, radius , paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
//混合模式中的SRC
canvas.drawBitmap(avatar, 0, 0, paint);
//画白边
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics());
paint.setStrokeWidth(strokeWidth);
canvas.drawCircle(avatar.getWidth()/2, avatar.getHeight()/2, radius-strokeWidth/2, paint);
return bitmap;
}
private static Bitmap getMyAvatar(Context context) {
Bitmap bitmap = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
//绘制图形需要2个对象
//画布Canvas
Canvas canvas = new Canvas(bitmap);
//画笔Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.DKGRAY);
paint.setStyle(Style.FILL);
canvas.drawCircle(75, 75, 75, paint);
paint.setColor(Color.WHITE);
//sp--屏幕的密度-->px
int sp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, context.getResources().getDisplayMetrics());
paint.setTextSize(sp);
Rect bounds = new Rect();
paint.getTextBounds("友录", 0, 2, bounds );
float x = 75 - bounds.width()/2;
float y = 75 + bounds.height()/2;
canvas.drawText("友录", x, y, paint);
//画白边
paint.setStyle(Paint.Style.STROKE);
float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, context.getResources().getDisplayMetrics());
paint.setStrokeWidth(strokeWidth);
canvas.drawCircle(75, 75, 75-strokeWidth/2, paint);
return bitmap;
}
}

读取手机上联系人等信息千万记得在AndroidMnifest.xml中加权限

    <uses-permission android:name="android.permission.READ_CONTACTS"/>

费劲千辛万苦,终于能看到结果了,~~~~(>_<)~~~~。

实现效果图如下:








就到这里啦~~~~thank you!!












































0 0
原创粉丝点击