1. 程式人生 > >仿微信的聯絡人列表實現

仿微信的聯絡人列表實現

  之前一直覺得微信的聯絡人列表挺難實現的,無意中看了別人模仿微信的一個專案,看了一下他的聯絡人列表實現方式,參照他的思路,自己做了一個。其實聯絡人列表主要就是一個普通的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;
   
}
}