Android项目实战-获取手机本地联系人,并带字母导航栏

因项目需要,有重新写了一个获取手机联系人模块,再此记录一下,看效果图:
这里写图片描述
如图中所示,我们本篇文章要实现的有:
1、自定义view——–字母索引列表view
2、listview数据的展示
3、查询本地联系人的相关信息,如姓名、电话号
4、6.0权限适配

由上面的效果图,我们来分析实现步骤:
1、自定义一个字母索引view
2、写一个listview,还有适配器adapter
3、通过Cursor获取本地的联系人数据,添加进listview中
4、实现字母左侧滑动,listview也跟着滑动,同事listview滑动,字母列表也实现滑动

一、自定义索引列表
1、就是一个自定义view,效果是当我们滑动到某个字母时当前字母变为白色,当前字母背景为蓝色,所以需要两个画笔,一个画字母,一个画背景:

public class SpellsSortView extends View{
    /*绘制的列表导航字母*/
    private String   spells[]= {"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 spellPaint;
    //字母背景画笔
    private Paint spellbgPaint;
    /*每一个字母的宽度*/
    private int itemWidth;
    /*每一个字母的高度*/
    private int itemHeight;
    /*手指按下的字母索引*/
    private int touchIndex = 0;
    /*手指按下的字母改变接口*/
    private onWordsChangeListener listener;

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

    public SpellsSortView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public SpellsSortView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

2、初始化字母画笔,背景画笔及设置字母大小

//进行一些初始化操作
    private void init() {
        //初始化字母画笔
        spellPaint = new Paint();
        spellPaint.setColor(Color.parseColor("#F7F7F7"));
        spellPaint.setAntiAlias(true);
        spellPaint.setTextSize(40);
        spellPaint.setTypeface(Typeface.DEFAULT_BOLD);

        //初始化字母背景画笔
        spellbgPaint = new Paint();
        spellbgPaint.setAntiAlias(true);
        spellbgPaint.setColor(Color.parseColor("#1dcdef"));

    }

3、我们知道要字母,我们首先要知道字母的宽高,所以需要重写Onmeasue();如下:

//测量每个字母的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        itemWidth = getMeasuredWidth();
        //使得边距好看一些
        int height = getMeasuredHeight() - 10;
        itemHeight = height / 27;//spells.length  总27个字母,均匀分布
    }

4、接下来就是绘制字母及其背景了:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i <spells.length ; i++) {
            //判断是不是我们按下的当前字母,让字母显示为白色,其他的为灰色
            if (touchIndex==i){
                //绘制文字圆形背景
                canvas.drawCircle(itemWidth / 2, itemHeight / 2 + i * itemHeight, 23, spellbgPaint);
                spellPaint.setColor(Color.WHITE);
            }else {
                spellPaint.setColor(Color.GRAY);
            }
            //获取文字的宽高
            Rect rect = new Rect();
            spellPaint.getTextBounds(spells[i], 0, 1, rect);
            int wordWidth = rect.width();
            //绘制字母
            float wordX = itemWidth / 2 - wordWidth / 2;
            float wordY = itemWidth / 2 + i * itemHeight;
            canvas.drawText(spells[i], wordX, wordY, spellPaint);
        }
    }

5、就是当滑动到某个字母时让其变色,而这个字母我们给的是touchIndex来指定,所以我们需要在ontouch事件里对touchIndex进行赋值,然后重新绘制。

/**
     * 当手指触摸按下的时候改变字母背景颜色
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float y = event.getY();
                //获得我们按下的是那个索引(字母)
                int index = (int) (y / itemHeight);
                if (index != touchIndex)
                    touchIndex = index;
                //重新绘制
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //手指抬起,不做任何操作
                break;
        }
        return true;
    }

这样,我们就完成了其基本功能,然后再xml里把布局写上即可
二、写一个listview,还有适配器adapter 这个就比较简单,在布局中加入listview,并且写一个adapter就好了,比较简单就不在这里写了,可以去看我的demo
三、通过Cursor获取本地的联系人数据,添加进listview中前提,需要在manifest中添加读取联系人的权限

String[] cols = {ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
        Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                cols, null, null, null);
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToPosition(i);
            // 取得联系人名字
            int nameFieldColumnIndex = cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);
            int numberFieldColumnIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
            String name = cursor.getString(nameFieldColumnIndex);
            String number = cursor.getString(numberFieldColumnIndex);
            Person person=new Person();
            person.setName(name);
            person.setUserphone(number);
            list.add(person);
        }

四、实现字母左侧滑动,listview也跟着滑动,同事listview滑动,字母列表也实现滑动
要实现listview滑动,同时字母列表也滑动,我们常用的方式就是写一个接口,然后这面实现接口,就能实现两个类之间的联动了,如下:首先在SpellsSortView里定义接口:

/*手指按下了哪个字母的回调接口*/
    public interface onWordsChangeListener {
        void wordsChange(String words);
    }

    /*设置手指按下字母改变监听*/
    public void setOnWordsChangeListener(onWordsChangeListener listener) {
        this.listener = listener;
    }

然后在onTouch时调用方法:

/**
     * 当手指触摸按下的时候改变字母背景颜色
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float y = event.getY();
                //获得我们按下的是那个索引(字母)
                int index = (int) (y / itemHeight);
                if (index != touchIndex)
                    touchIndex = index;
                //防止数组越界
                if (listener != null && 0 <= touchIndex && touchIndex <= spells.length - 1) {
                    //回调按下的字母
                    listener.wordsChange(spells[touchIndex]);
                }
                //重新绘制
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //手指抬起,不做任何操作
                break;
        }
        return true;
    }

然后让列表随着字母所以滑动就比较简单了,

/**
     * @param words 首字母
     */
    private void updateListView(String words) {
        for (int i = 0; i < list.size(); i++) {
            String headerWord = list.get(i).getHeaderWord();
            //将手指按下的字母与列表中相同字母开头的项找出来
            if (words.equals(headerWord)) {
                //将列表选中哪一个
                lv_list.setSelection(i);
                //找到开头的一个即可
                return;
            }
        }
    }

大致思路就是这样的,具体的可以看我的demo,本篇也参考网上的一些资料,本着分享的精神,希望大家能学到自己想要的知识。
可以去这里下载demo,没有cb的可以加我qq2145228494
http://download.csdn.net/download/ali18510953445/10213819

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值