前言
在之前搭建的简易微信界面的基础上,实现了将手机通讯录通过RecyclerView进行调用并展示到联系人的fragment中,并点击右上角加号实现添加联系人,并传值到手机通讯录中。
简易微信界面项目
项目参考
项目源码
项目编写
布局文件
top.xml//在原来的基础上添加了+图标
item_swipe.xml//点击后展开具体信息
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ID_TOP"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#372c2c"
android:orientation="horizontal">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="150dp"
android:text="MyWechat"
android:textColor="#ffffff"
android:textSize="25sp" />
<ImageButton
android:id="@+id/id_add_img"
android:layout_width="26dp"
android:layout_height="31dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="80dp"
android:background="#00000000"
android:clickable="false"
android:scaleType="centerInside"
android:src="@drawable/add2" />
</LinearLayout>
item_expand.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:layout_margin="5dp"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_parent"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#03A9F4">
<TextView
android:id="@+id/tv_team"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
tools:text="主布局" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_child"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FC0000"
android:visibility="gone">
<TextView
android:id="@+id/tv_team_child"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
tools:text="副布局" />
</RelativeLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
xmlns:tools="http://schemas.android.com/tools"
android:layout_margin="8dp"
android:background="@drawable/common_bg"
android:orientation="vertical">
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
tools:text="内容" />
</LinearLayout>
联系人权限获取
在Mainfest文件中添加下述两行注册信息,获取对联系人的读写权限。(如果依旧出现权限错误,可以尝试clean project,博主在这里卡住近两小时…)
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
contactFragment
这里注意由于RecyclerView是在Fragment中进行设置的,因此要在这里进行数据的刷新。
package com.example.weixinapplication;
import android.animation.Animator;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A simple {@link Fragment} subclass.
*/
public class contactFragment extends Fragment {
private RecyclerView recyclerView;
//private List<String> mList = new ArrayList<>();
private List<Map<String,String>>data=new ArrayList<Map<String, String>>();
private HashMap<String, String> item;
private Context context;
private adapter_expand adapter;
private boolean isGetData = false;
public contactFragment() {
// Required empty public constructor
}
@Override
//切换fragment时对contanct进行刷新,先清空数据,再重新获取联系人数据
public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
if(enter&&!isGetData){
isGetData = true;
data.clear();
initexpandData();
}else {
isGetData = false;
}
return super.onCreateAnimator(transit, enter, nextAnim);
}
public void onPause(){
super.onPause();
isGetData = false;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.tab03, container, false);
recyclerView=view.findViewById(R.id.rcv_expandcollapse);
context=this.getActivity();
initexpandData();
adapter=new adapter_expand(context,data);
LinearLayoutManager manager=new LinearLayoutManager(context);
manager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(manager);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL));
return view;
}
public void initexpandData(){
Uri uri= ContactsContract.Contacts.CONTENT_URI;
ContentResolver resolver = context.getContentResolver();
Cursor cursor=resolver.query(uri, null, null, null, null); //得到记录集
if(cursor!=null){
while(cursor.moveToNext()){
//先获取联系人_id字段的索引号后再获取_id值
int idFieldIndex=cursor.getColumnIndex("_id");
int id=cursor.getInt(idFieldIndex);
//先获取联系人姓名字段的索引号后再获取姓名字段值
int nameFieldIndex = cursor.getColumnIndex("display_name");
String name=cursor.getString(nameFieldIndex);
int numCountFieldIndex=cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
int numCount=cursor.getInt(numCountFieldIndex); //获取联系人的电话号码个数
String phoneNumber="";
if(numCount>0){ //联系人有至少一个电话号码
//在类ContactsContract.CommonDataKinds.Phone中根据id查询相应联系人的所有电话;
Cursor phonecursor=getActivity().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"=?",
new String[]{Integer.toString(id)}, null);
if(phonecursor!=null){
if(phonecursor.moveToFirst()){ //仅读取第一个电话号码
int numFieldIndex=phonecursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
phoneNumber=phonecursor.getString(numFieldIndex);
}
phonecursor.close();
}
}
item=new HashMap<String,String>(); //必须循环创建
item.put("name", name);
item.put("phoneNumber", phoneNumber);
data.add(item);
}
cursor.close();
}
}
}
MainActivity
在主界面中点击按钮时触发弹框AlertDialog,在弹框中输入添加的联系人信息,并通过确定提交数据,传至手机的联系人中。
package com.example.weixinapplication;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.RawContacts.Data;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class MainActivity extends Activity implements View.OnClickListener {
private Fragment mTab01 = new wechatFragment();
private Fragment mTab02 = new frdFragment();
private Fragment mTab03 = new contactFragment();
private Fragment mTab04 = new settingsFragment();
private FragmentManager fm;
private LinearLayout mTabWeixin;
private LinearLayout mTabFrd;
private LinearLayout mTabContact;
private LinearLayout mTabSettings;
private ImageButton mImgWeixin;
private ImageButton mImgFrd;
private ImageButton mImgContact;
private ImageButton mImgSettings;
private ImageButton mImgAdd;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 1:
if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();
finish();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1);
}else{
initView();
initFragment();
selectFragment(0);
initEvent();
}
}
private void initFragment(){
fm =getFragmentManager();
FragmentTransaction transaction=fm.beginTransaction();
transaction.add(R.id.id_content,mTab01);
transaction.add(R.id.id_content,mTab02);
transaction.add(R.id.id_content,mTab03);
transaction.add(R.id.id_content,mTab04);
transaction.commit();
}
private void initView(){
mTabWeixin=(LinearLayout)findViewById(R.id.id_tab_weixin);
mTabFrd=(LinearLayout)findViewById(R.id.id_tab_frd);
mTabContact=(LinearLayout)findViewById(R.id.id_tab_contact);
mTabSettings=(LinearLayout)findViewById(R.id.id_tab_settings);
mImgWeixin=(ImageButton)findViewById(R.id.id_tab_weixin_img);
mImgFrd=(ImageButton)findViewById(R.id.id_tab_frd_img);
mImgContact=(ImageButton)findViewById(R.id.id_tab_contact_img);
mImgSettings=(ImageButton)findViewById(R.id.id_tab_settings_img);
mImgAdd=(ImageButton)findViewById(R.id.id_add_img);
}
private void hideFragment(FragmentTransaction transaction){
transaction.hide(mTab01);
transaction.hide(mTab02);
transaction.hide(mTab03);
transaction.hide(mTab04);
}
private void selectFragment(int i){
FragmentTransaction transaction=fm.beginTransaction();
hideFragment(transaction);
switch (i){
case 0:
transaction.show(mTab01);
mImgWeixin.setImageResource(R.drawable.tab_weixin_pressed);
break;
case 1:
transaction.show(mTab02);
mImgFrd.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case 2:
transaction.show(mTab03);
mImgContact.setImageResource(R.drawable.tab_address_pressed);
break;
case 3:
transaction.show(mTab04);
mImgSettings.setImageResource(R.drawable.tab_settings_pressed);
break;
default:
break;
}
transaction.commit();
}
@Override
public void onClick(View v) {
resetImgs();
switch(v.getId()){
case R.id.id_tab_weixin:
selectFragment(0);
break;
case R.id.id_tab_frd:
selectFragment(1);
break;
case R.id.id_tab_contact:
selectFragment(2);
break;
case R.id.id_tab_settings:
selectFragment(3);
break;
case R.id.id_add_img:
final View addDialog=getLayoutInflater().inflate(R.layout.add_contact,null);
new AlertDialog.Builder(MainActivity.this).setView(addDialog).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
EditText mname=(EditText)addDialog.findViewById(R.id.name);
EditText mphone=(EditText)addDialog.findViewById(R.id.phone);
final String name=mname.getText().toString();
final String phone=mphone.getText().toString();
// 创建一个空的ContentValues
ContentValues values = new ContentValues();
// 向RawContacts.CONTENT_URI执行一个空值插入
// 目的是获取系统返回的rawContactId
Uri rawContactUri = getContentResolver().insert(
ContactsContract.RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
// 设置内容类型
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
// 设置联系人名字
values.put(StructuredName.GIVEN_NAME, name);
// 向联系人URI添加联系人名字
getContentResolver().insert(ContactsContract
.Data.CONTENT_URI, values);
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
// 设置联系人的电话号码
values.put(Phone.NUMBER, phone);
// 设置电话类型
values.put(Phone.TYPE, Phone.TYPE_MOBILE);
// 向联系人电话号码URI添加电话号码
getContentResolver().insert(ContactsContract
.Data.CONTENT_URI, values);
values.clear();
contactFragment a = new contactFragment();
selectFragment(2);
Toast.makeText(MainActivity.this, "联系人数据添加成功",
Toast.LENGTH_SHORT).show();
}
}).show();
break;
}
}
private void resetImgs(){
mImgWeixin.setImageResource(R.drawable.tab_weixin_normal);
mImgFrd.setImageResource(R.drawable.tab_find_frd_normal);
mImgContact.setImageResource(R.drawable.tab_address_normal);
mImgSettings.setImageResource(R.drawable.tab_settings_normal);
}
private void initEvent(){
mTabWeixin.setOnClickListener(this);
mTabFrd.setOnClickListener(this);
mTabContact.setOnClickListener(this);
mTabSettings.setOnClickListener(this);
mImgAdd.setOnClickListener(this);
}
}
项目心得
在多个fragment中实现不同的功能,最困难的还是对RecyclerView做出的各种操作。由于是在contactFragment中对RecyclerView进行的适配,因此我无法在点击确定按钮时通过notifyitemchanged()来更新recyclerview中的数据,所以我在contactfragment中通过点击contact后触发清除data和再次获取联系人信息的方式实现刷新,如果有更好的方法,请在留言区赐教!