Android 高仿微信通讯录

本文介绍了一位新手开发者如何模仿微信的通讯录界面,包括自定义View实现右侧字母栏、顶部搜索框功能及好友列表的ListView排序与适配。详细讲述了数据检索、ListView排序和Adapter的配置过程,但未实现挤压效果,待技术提升后再补充。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模仿了一下微信的联系人界面UI,由于是新手,所以看起来很简单的界面,结果被搞得半死,弄到凌晨5点,实在吃不消了,就睡了,早上9点又有小伙伴过来找我,约好了下午出去爬山的,没睡醒就出去玩了,一下午头都很痛,整个人也很晕,简直日了狗。。。不过还好,现在回来了,就迫不及待打开电脑写博客了,怕以后会忘。好了,废话不多说,开始切入正题!

先来一张原版的微信通讯录截图

对,界面就是这样的,很熟悉的界面吧,下面就开始写我是如何模仿的,先贴一下我的成果图


我只是模仿了一个大概,界面很简单,顶部是一个搜索框,然后下面是一个ListView用来显示好友列表,最右边有一排英文字母,用来快速定位的,我就不多做介绍了,这种功能如果还不清楚的话,就打开手机微信自己感受一下吧

1.自定义View-屏幕最右边的一排英文字母

public class LetterView extends View {

    private OnTouchingLetterChangedListener mOnTouchingLetterChangedListener;
    private String[] letters = { "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 TextView tv;

    public void setTextView(TextView tv) {
        this.tv = tv;
    }

    public LetterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public LetterView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LetterView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 每一个字母的高度
        int letter_height = getHeight() / letters.length;
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setColor(Color.BLACK);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        paint.setTextAlign(Align.CENTER);
        paint.setTextSize(Math.min(getWidth(), getHeight() / 27) - 2);
        // drawText方法可以把26个英文字母画到控件上
        for (int i = 0, current_height = 0; i < 27; i++) {
            current_height += letter_height;
            canvas.drawText(letters[i], getWidth() / 2, current_height, paint);
        }
    }

    /** 当手指在该控件上拖动的时候,字母会改变 **/
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            tv.setVisibility(View.INVISIBLE);
            break;
        default:
            float y = event.getY();
            int position = (int) (y / (getHeight() / 27));
            if (position < 27 && position >= 0) {
                tv.setText(letters[position]);
                tv.setVisibility(View.VISIBLE);
                mOnTouchingLetterChangedListener.onTouchingLetterChanged(letters[position].charAt(0));
            } else {
                tv.setVisibility(View.INVISIBLE);
            }
            break;
        }
        return true;
    }

    public void setOntouchingLetterChangedListener(OnTouchingLetterChangedListener mtOnTouchingLetterChangedListener) {
        this.mOnTouchingLetterChangedListener = mtOnTouchingLetterChangedListener;
    }

    /** 回调接口,手指的拖动,会导致英文字母的改变,并做出响应的处理 **/
    public interface OnTouchingLetterChangedListener {
        public void onTouchingLetterChanged(char c);
    }
}

2.顶部的搜索框
搜索框的代码其实很好写,也就是一个EditText,但是需要监听输入状态,每次输入框的内容改变,我们都要进行一次数据的检索,提高用户体验,调用EditText的addTextChangedListener()方法就可以了,业务逻辑自己在里面写

3.显示好友列表的ListView
首先,我们从数据库取出来的好友列表并不一定是我们想要的顺序,所以我们需要先对好友列表进行排序,排序规则:按照首字母进行A~Z排序,如果首字母不是英文字母,是特殊符号或者数字活着其他乱七八糟的什么,那就归类到#,排序很简单,我的代码是这样的:

Collections.sort(list, new Comparator<Friend>() {

            @Override
            public int compare(Friend o1, Friend o2) {
                String c1 = o1.getFistChar() + "";
                String c2 = o2.getFistChar() + "";
                if (c1.equals("#")) {
                    return 1;
                }
                if (c2.equals("#")) {
                    return -1;
                }

                return c1.compareTo(c2);
            }
        });

我已经提前用pinyin4j这个第三方库将每个好友的首字母提取出来了,这类文章网上很多,想知道如何使用的,自己去百度吧,我这里就不多讲了

排序排好了,我们就开始配置adapter了,adapter是继承了BaseAdapter,我的每个item布局是这样的:

再展示一下adapter里面的getView方法

class ViewHolder {
        TextView key;
        TextView friend_name;
        ImageView friend_img;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Friend friend = getItem(position);
        ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.friend_list_item, null);
            holder = new ViewHolder();
            holder.key = (TextView) convertView.findViewById(R.id.key);
            holder.friend_img = (ImageView) convertView.findViewById(R.id.friend_img);
            holder.friend_name = (TextView) convertView.findViewById(R.id.friend_name);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        if (getPositionForSection(friend.getFistChar()) == position) {
            holder.key.setText(friend.getFistChar() + "");
            holder.key.setVisibility(View.VISIBLE);
        } else {
            holder.key.setVisibility(View.GONE);
        }
        holder.friend_name.setText(friend.getName());
        return convertView;
    }

    private int getPositionForSection(char c) {
        for (int i = 0; i < list.size(); i++) {
            if (getItem(i).getFistChar() == c) {
                return i;
            }
        }
        return -1;
    }

listview中的每个item都对应着一个联系人,判断该联系人的首字母是否是排在该类的第一个,如果是第一个,就显示首字母,如果不是第一个,就不显示首字母。举个例子,如果我有一个list,里面存放着一大堆联系人,并且已经排好顺序了,如{”阿猫”,”阿狗”,”壁虎”,”Big”,”白天黑夜”,”单身狗”,”淡淡的”,”的”,”冯”,”种子”},如果item要显示壁虎的信息,就需要首字母这个控件,如果item要显示Big的信息,就不需要显示首字母这个空间,因为壁虎和Big都属于B类,而且壁虎排在第一个,所以只要第一个显示首字母空间就可以了

好了,这个项目差不多也完了,还有一个挤压的功能没有写出来,因为本人能力有限,等以后技术成熟了再来完善这篇博客吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值