Android快速索引:实现微信通讯录效果

来源:互联网 发布:台湾永宏plc编程软件 编辑:程序博客网 时间:2024/05/19 00:11

最近在练习自定义view,找了一些资料,模仿了一下微信通讯录的实现效果,首先看一下效果图:
这里写图片描述

记录下来当做笔记以备后用。
第一步:是绘制26个字母的view:
在每个构造方法中调用下面的init()方法实现画笔的初始化

private void init() {        //去掉字母锯齿的参数        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setColor(Color.WHITE);        // mPaint.setTypeface(Typeface.DEFAULT_BOLD);        mPaint.setTextSize(40);//设置字母大小    }

然后是onDraw()方法进行绘制:

@Override    protected void onDraw(Canvas canvas) {        //这里用来绘制背景,当字母被触摸的时候会变成灰色        if (mTouched) {            canvas.drawColor(0x30000000);        }        for (int i = 0; i < letterLength; i++) {            String text = LETTERS[i];            // 计算坐标            int x = (int) (cellWidth / 2.0f - mPaint.measureText(text) / 2.0f);            // 获取文本的高度            Rect bounds = new Rect();// 矩形            mPaint.getTextBounds(text, 0, text.length(), bounds);            int textHeight = bounds.height();            int y = (int) (cellHeight / 2.0f + textHeight / 2.0f + i* cellHeight);            // 设置文本颜色            mPaint.setColor(Color.BLACK);            // 绘制文本A-Z            canvas.drawText(text, x, y, mPaint);        }    }

根据注释可以清楚的知道绘制的原理,就是计算26个字母的x和y坐标,x左边不变的,y坐标规律的增加。

接下来重写onTouchEvent()方法

boolean mTouched = false;int touchIndex = -1;    @Overridepublic boolean onTouchEvent(MotionEvent event) {        int index = -1;        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:        case MotionEvent.ACTION_MOVE:            // 获取当前触摸到的字母索引            index = (int) (event.getY() / cellHeight);            if (index >= 0 && index < LETTERS.length) {                // 判断是否跟上一次触摸到的一样            if (index != touchIndex) {                if (listener != null) {                                    listener.onLetterUpdate(LETTERS[index]);                    }                    touchIndex = index;                }            }            mTouched = true;            break;        case MotionEvent.ACTION_UP:            if (listener != null) {                listener.onFinished();            }            touchIndex = -1;            mTouched = false;            break;        default:            break;        }        invalidate();        return true;    }

原理就是根据两个索引值,即当前按下字母的索引是否和上次的一样,如果不一样才会调用接口把字母暴露给调用方,否则如果不进行判断的话,就会导致当手指在快速索引条上移动的时候总是会弹出相同的字母。还有就是记录了一个按下的mTouched值,如果按下或者移动设置为true,否则为false。这样就可以根据是否按下来绘制背景改变颜色了。再看一下ACTION_UP事件中暴露onFinished()方法给调用方,主要是为了将弹出的字母隐藏掉。这样当手指按下的时候会弹出当前的字母,当手指抬起就会立即消失。

当view的大小发生变化时获取单元格的宽和高

@Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        // 获取单元格的宽和高        cellWidth = getMeasuredWidth();        int mHeight = getMeasuredHeight();        cellHeight = mHeight * 1.0f / LETTERS.length;    }

接下来就是回调接口:

    /**     * 暴露一个字母的监听     */    public interface OnLetterUpdateListener {        void onLetterUpdate(String letter);        void onFinished();    }    private OnLetterUpdateListener listener;    /**     * 设置字母更新监听     *      * @param listener     */    public void setListener(OnLetterUpdateListener listener) {        this.listener = listener;    }

以上就是快速索引条的绘制过程。

接下来看一下MainActivity.java的主要代码:

// 设置监听bar.setListener(new OnLetterUpdateListener() {            @Override    public void onLetterUpdate(String letter) {        showLetter(letter);        // 根据字母定位ListView, 找到集合中第一个以letter为拼音首字母的对象,得到索引        for (int i = 0; i < persons.size(); i++) {            Person person = persons.get(i);            String l = person.getPinyin().charAt(0) + "";            if (TextUtils.equals(letter, l)) {                // 匹配成功                mMainList.setSelection(i);                break;            }        }    }    @Override    public void onFinished() {        tv_center.setVisibility(View.GONE);    }});

这就是实现回调方法,弹出显示字母框和隐藏字母的功能。
还有一个就是对ListView中联系人拼音的第一个字母和手指此刻按下的字母进行比较,如果相等的话,就会将ListView位置定位到这个字母,也就是把该字母显示在第一个位置。

这个是显示字母的代码:

/*** 显示字母*/protected void showLetter(String letter) {    tv_center.setVisibility(View.VISIBLE);    tv_center.setText(letter);}

这个是对通讯录进行排序的方法:

private void fillAndSortData(ArrayList<Person> persons) {    List<String> nameList = PhoneContactsUtils.getContactsName(this);    // 填充数据    for (int i = 0; i < nameList.size(); i++) {        String name = nameList.get(i);        persons.add(new Person(name));    }    // 进行排序    Collections.sort(persons);    }

以上就是主要的代码,还有工具类、实体类和适配器的代码没有贴出来,感觉太多了贴出来不方便阅读。实体类就是一个名字和拼音两个成员变量,并且要实现Comparable接口以便进行联系人根据字母排序。还有读取手机通讯录联系人等没什么好讲的,直接放到源码包中就好了。

源码下载地址:Android自定义view实现微信通讯录一模一样效果

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑版酷狗字体模糊怎么办 酷我切歌怎么办 快手暂不支持音乐格式怎么办 上传视频不清晰怎么办 MP4格式嫌大怎么办 课堂派怎么办改成考试 手机信息幕变黑怎么办 手机百度太耗电怎么办 电脑打不开主页面怎么办? 贴吧被永久封了怎么办 晒课视频太大怎么办 有道精品课过期怎么办 手机缓存变小了怎么办 优学院课程过期怎么办 上公开课紧张怎么办 光纤被老鼠咬断怎么办 石灰粉进入眼睛怎么办 幼儿误吃粉笔怎么办? 吃了粉笔应该怎么办 小孩吃了颜料怎么办 小宝宝吃了纸怎么办 孩子不认真听讲怎么办 监控手机软件离线状态怎么办 云课堂忘记密码怎么办 广州办培训机构怎么办 一师一优课账号忘了怎么办 云相册空间不足怎么办 三星云空间不足怎么办 三星储存空间不足怎么办 宁阳县教育局强制补课怎么办 沉迷网络该怎么办英语 29岁沉迷游戏怎么办 学乐云登录不上怎么办 魔方学院无法识别怎么办 路由器卫士忘记密码怎么办 邮箱号忘记密码怎么办 水卡没钱了怎么办 旅行青蛙换手机怎么办 软件尚未受信任怎么办 百度搜不到的怎么办 百度中搜不到怎么办