仿微信的聯絡人列表實現
之前一直覺得微信的聯絡人列表挺難實現的,無意中看了別人模仿微信的一個專案,看了一下他的聯絡人列表實現方式,參照他的思路,自己做了一個。其實聯絡人列表主要就是一個普通的listview,最關鍵的就是在item的佈局上面。Item佈局如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"> <!--這個是上面的大寫的A B C D等分隔項,每個item上面都有, 如果在一組的話,就只顯示第一個的,比如說 adfd 和 ae 就在一組 就只顯示 adfd 上面的A,而不顯示ae上面的A--> <TextView android:id="@+id/text_index" android:layout_width="match_parent" android:layout_height="wrap_content"android:padding="10dp" android:background="#c5c5c5"/> <!--頭像和名稱所在的佈局--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/img_head"android:layout_width="80dp" android:layout_height="80dp" android:src="@mipmap/xj"/> <TextView android:id="@+id/text_name" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>
聯絡人列表的activity的佈局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_contact"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
<com.example.widgets.SideBar
android:id="@+id/side_bar"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_marginTop="30dp"
android:background="@color/colorPrimary"/>
</FrameLayout>
</LinearLayout>
就是一個listview和一個自定義的側邊欄。
Listview的adapter的主要思路:如果後面的item和前面的item屬於同一個組,則隱藏後面的item的上面的分類,比如ag 和ah 都屬於A 這個組,則隱藏ah上面的A。 程式碼如下:
public class ContactAdapter extends BaseAdapterimplements SectionIndexer{
private Contextcontext;
private List<String> names;
private LayoutInflater layoutInflater;
public ContactAdapter(Context context, List<String> names) {
this.context = context;
this.names= names;
layoutInflater = LayoutInflater.from(context);
//對名字進行排序,本程式只支援英文,如果需要中文的話
//可以使用Pinyin4j類庫對中文姓名進行處理
Collections.sort(names, new Comparator<String>(){
@Override
public int compare(String s1, Strings2) {
s1 = s1.toUpperCase();
s2 = s2.toUpperCase();
return s1.compareTo(s2);
}
});
}
@Override
public int getCount() {
return names.size();
}
@Override
public ObjectgetItem(int position) {
return names.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public ViewgetView(int position, ViewconvertView, ViewGroup parent) {
View v = convertView;
ViewHolder viewHolder = null;
if(v == null){
v = layoutInflater.inflate(R.layout.list_item_contact, parent, false);
viewHolder = new ViewHolder();
viewHolder.textIndex= (TextView) v.findViewById(R.id.text_index);
viewHolder.textName= (TextView) v.findViewById(R.id.text_name);
v.setTag(viewHolder);
}else{
viewHolder = (ViewHolder)v.getTag();
}
//獲取該位置的名字的首字母的大寫
String catalog = NameUtil.getCatalog(names.get(position));
if(position == 0){
viewHolder.textIndex.setVisibility(View.VISIBLE);
viewHolder.textIndex.setText(catalog);
}else{
//獲取該位置的前一個位置的首字母的大寫
String previousCatalog = NameUtil.getCatalog(names.get(position - 1));
if(previousCatalog.equals(catalog)){
viewHolder.textIndex.setVisibility(View.GONE);
}else{
viewHolder.textIndex.setVisibility(View.VISIBLE);
viewHolder.textIndex.setText(catalog);
}
}
viewHolder.textName.setText(names.get(position));
return v;
}
@Override
public Object[]getSections() {
return new Object[0];
}
@Override
public int getPositionForSection(int sectionIndex) {
for(int i = 0; i < names.size(); i++){
if(names.get(i).toUpperCase().charAt(0) ==sectionIndex){
return i;
}
}
return 0;
}
@Override
public int getSectionForPosition(int position) {
return 0;
}
private class ViewHolder{
TextView textIndex;
TextView textName;
}
}
自定義的側邊欄的實現如下,程式碼的邏輯比較簡單,應該很容易看懂
public class SideBar extends View{
private static final String TAG = "SideBar";
private static char[] initials = new char[]{'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'};
private Paint mPaint;
private ListView mListView;
private MyDialog dialog;
private int itemHeight;
public SideBar(Contextcontext) {
this(context, null);
}
public SideBar(Context context, AttributeSetattrs) {
this(context, attrs, 0);
}
public SideBar(Context context, AttributeSetattrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(18);
mPaint.setColor(Color.GREEN);
dialog = new MyDialog(getContext());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
itemHeight =height / initials.length;
Log.d(TAG, "height = " + height + "........" + "itemHeight= " + itemHeight);
for(int i = 0; i < initials.length; i++){
canvas.drawText(String.valueOf(initials[i]), width / 2, (i + 1) * itemHeight, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEventevent) {
int action= event.getAction();
if(action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE){
int y =(int) event.getY();
int index = y / itemHeight; //注意這個地方的除數
Log.d(TAG, "y = " + y + "...."+ "index = " + index);
char content = initials[index];
SectionIndexer sectionIndexer = (SectionIndexer) mListView.getAdapter();
int position = sectionIndexer.getPositionForSection(content);
mListView.setSelection(position);
dialog.setMsg("" + content);
dialog.show();
}elseif(action == MotionEvent.ACTION_UP){
dialog.dismiss();
}
return true;
}
public void setmListView(ListViewmListView) {
this.mListView = mListView;
}
}