【Android联系人】仿小米联系人(MIUI8)
来源:互联网 发布:http网络协议 编辑:程序博客网 时间:2024/05/16 12:16
头一次写博客,文笔不好。
apk下载地址:https://www.pgyer.com/MiContacts
先上效果图:
既然是展示联系人信息,首先需要的是添加获取联系人权限:
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
主页面是自己写了一个滑动的tab+viewpager+fragment实现。接下来就是联系人页面,主要就以下几点:
①.获取系统联系人数据;
②.列表的滑动,头部字母悬浮;
③.右侧的索引栏;
④.文字图片的实现。
首先,分析布局,肯定需要用到列表,然后就是右侧的索引,还有就是点击索引时候出现的一个小提示。由于这方面网上有很多写好的,大家可以搜索一下。我这里用的是:
//字母索引compile 'com.bigkoo:quicksidebar:1.0.2'
接下来分析一下头部悬浮,做法有很多。说一个简单的,我们可以直接用listView的SectionIndexer来监听,滑动标题悬浮,然后再加上动画实现顶上去的效果。这里有一篇郭神的文章,里边说的很详细。有兴趣可以看一下:Android系统联系人全特效实现(上),分组导航和挤压动画
我呢,也直接用写好的,用recyclerview实现:
//recyclerview分组,顶部浮动compile 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar'
这样的话,基本上联系人页面的布局我们就可以直接写出来了:
<?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" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.bigkoo.quicksidebar.QuickSideBarTipsView android:id="@+id/quickSideBarTipsView" android:layout_width="@dimen/height_quicksidebartips" android:layout_height="match_parent" android:layout_toLeftOf="@+id/quickSideBarView" app:sidebarBackgroundColor="@color/colorPrimary" app:sidebarTextColor="@android:color/white" app:sidebarTextSize="@dimen/textSize_quicksidebartips" /> <com.bigkoo.quicksidebar.QuickSideBarView android:id="@id/quickSideBarView" android:layout_width="20dp" android:layout_height="match_parent" android:layout_alignParentRight="true" app:sidebarItemHeight="@dimen/height_quicksidebaritem" app:sidebarTextColor="@android:color/black" app:sidebarTextColorChoose="@color/colorPrimary" app:sidebarTextSize="@dimen/textSize_quicksidebar" app:sidebarTextSizeChoose="@dimen/textSize_quicksidebar_choose" /> </RelativeLayout></LinearLayout>
接下来就先撸代码吧。什么findViewby…..,这里介绍一个神器:Android Studio插件-自动根据布局生成Activity等代码(开源) 极大的提升效率。
获取系统联系人需要注意的是权限,在android6.0以上需要自己请求权限,这是跟6.0之前版本不同的地方。我就直接在onResume下面进行处理,然后做相应操作。
private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1; private void checkPermission() { //版本判断 if (Build.VERSION.SDK_INT >= 23) { //减少是否拥有权限 int checkCallPhonePermission = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CONTACTS); if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) { // Show our own UI to explain to the user why we need to read the contacts // before actually requesting the permission and showing the default UI ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_CONTACTS},READ_CONTACTS_PERMISSIONS_REQUEST); }else{ initContants(); } } else { initContants(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { // Make sure it's our original READ_CONTACTS request if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { initContants(); return; } else { Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }
接下来,就是上边代码中看到initContants()方法了,这里边主要就是获取联系人的数据,然后给recyclerview绑定adapter。具体代码:
private void initContants() { Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; Cursor cursor = getActivity().getContentResolver().query(uri, new String[]{"display_name", "sort_key"}, null, null, "sort_key"); if (cursor.moveToFirst()) { do { String name = cursor.getString(0); String sortKey = getSortKey(cursor.getString(1)); Contacts contact = new Contacts(); contact.setName(name); contact.setSortKey(sortKey); contacts.add(contact); } while (cursor.moveToNext()); } getActivity().startManagingCursor(cursor);//cursor的生命周期托管给activity //设置列表数据和浮动header final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(layoutManager); // Add the sticky headers decoration ContactsListWithHeadersAdapter adapter = new ContactsListWithHeadersAdapter(); ArrayList<String> customLetters = new ArrayList<>(); int position = 0; for (Contacts contact : contacts) { String letter = contact.getSortKey(); //如果没有这个key则加入并把位置也加入 if (!letters.containsKey(letter)) { letters.put(letter, position); customLetters.add(letter); } position++; } //不自定义则默认26个字母 quickSideBarView.setLetters(customLetters); adapter.addAll(contacts); recyclerView.setAdapter(adapter); final StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(adapter); recyclerView.addItemDecoration(headersDecor); // Add decoration for dividers between list items recyclerView.addItemDecoration(new DividerDecoration(getActivity())); }
还有一个部分就是汉字首字母的处理,这里直接用的是CharacterParser,网上很容易搜索到的。
接下来就是写适配器了,适配器的话主要有一个地方需要注意,就是圆形图片文字,在这里直接用的开源的CircleTextImageView,我们没必要自己写,嘿嘿。所以需要引入:
//圆形文字compile 'com.github.thinkcool:circletextimageview:1.0.20151218'
然后就是适配器的一些代码了:
private class ContactsListWithHeadersAdapter extends ContactsListAdapter<RecyclerView.ViewHolder> implements StickyRecyclerHeadersAdapter<RecyclerView.ViewHolder> { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.adapter_contacts_item, parent, false); return new RecyclerView.ViewHolder(view) { }; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { View itemView = holder.itemView; TextView mName = (TextView) itemView.findViewById(R.id.mName); CircleTextImageView mUserPhoto = (CircleTextImageView) itemView.findViewById(R.id.mUserPhoto); LinearLayout mBottomLayout=(LinearLayout)itemView.findViewById(R.id.mBottomLayout); if (position<contacts.size()-1){ if (getItem(position).getSortKey().equals(getItem(position+1).getSortKey())){ mBottomLayout.setVisibility(View.GONE); }else { mBottomLayout.setVisibility(View.VISIBLE); } }else { mBottomLayout.setVisibility(View.GONE); } String name = getItem(position).getName(); mName.setText(name); if (name.substring(name.length() - 1).equals("(") || name.substring(name.length() - 1).equals(")") || name.substring(name.length() - 1).equals("[") || name.substring(name.length() - 1).equals("]")|| name.substring(name.length() - 1).equals("(") || name.substring(name.length() - 1).equals(")") || name.substring(name.length() - 1).equals("【") || name.substring(name.length() - 1).equals("】")) { mUserPhoto.setText(name.substring(name.length() - 2,name.length() - 1)); } else { mUserPhoto.setText(name.substring(name.length() - 1)); } } @Override public long getHeaderId(int position) { return getItem(position).getSortKey().charAt(0); } @Override public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.adapter_contacts_head, parent, false); return new RecyclerView.ViewHolder(view) { }; } @Override public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) { View itemView = holder.itemView; TextView mHead = (TextView) itemView.findViewById(R.id.mHead); mHead.setText(String.valueOf(getItem(position).getSortKey()));// holder.itemView.setBackgroundColor(getRandomColor()); } private int getRandomColor() { SecureRandom rgen = new SecureRandom(); return Color.HSVToColor(150, new float[]{ rgen.nextInt(359), 1, 1 }); } }
头一次写博客,文笔不好,请见谅。
希望我的文章对你有帮助,有什么问题请留言。
附上源代码:https://github.com/NewsChen/MiContacts
- 【Android联系人】仿小米联系人(MIUI8)
- 仿小米联系人
- android 仿联系人UI
- Android 仿联系人字母索引
- 利用RadioButton以及ViewPager实现仿小米联系人页面
- 利用RecyclerView高仿小米联系人列表界面
- Android自定义控件之仿通讯录联系人
- Android仿QQ联系人分组悬停
- 【Android studio】使用小米手机(MIUI8)真机调试
- 仿QQ联系人列表
- 仿联系人的排序
- android 联系人
- android联系人
- 联系人
- 联系人
- 联系人
- 联系人
- Android 联系人开发- 查询联系人
- 数据存储方式
- 手把手教你提高英语能力
- java编程思想 bruce Eckel chapter10 内部类
- 编程之美3.7队列中取最大值操作问题Java版
- 数据库分库分表
- 【Android联系人】仿小米联系人(MIUI8)
- MySQL预处理 mysql_stmt_execute()
- 剑指Offer: 链表中环的入口结点
- 在Nodemcu开发板上运行MicroPython 1.8.2
- java代码模型6(异常处理格式)
- iOS 基本功能都有的音乐播放器 AVAudioPlayer
- 基于七牛和fresco的一整套安卓图片解决方案
- 常用技巧
- java.lang.NoSuchFieldError: INSTANCE异常问题