仿微信的联系人列表实现

 

 

  之前一直觉得微信的联系人列表挺难实现的,无意中看了别人模仿微信的一个项目,看了一下他的联系人列表实现方式,参照他的思路,自己做了一个。其实联系人列表主要就是一个普通的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;
   
}
}

 

 

 

 

 


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值