天天看點

安卓仿手機聯系人右側快速搜尋菜單自定義View

今天練習了一下手機聯系人快速索引的自定義View,依例看下效果圖:

先來張極具爆發力的大月亮珠聯璧合組合:

安卓仿手機聯系人右側快速搜尋菜單自定義View

效果圖:

安卓仿手機聯系人右側快速搜尋菜單自定義View

觀今夜星,額不,觀效果很多同學一下子可能感覺很複雜,沒錯,确實蠻複雜的。不過分析一下就很簡單了,整個布局分為三塊:

  1. 鋪滿螢幕的清單控件(這裡用的是Recycleview)
  2. 中間顯示字幕的正方形
  3. 右側可滑動、點選的不知啥玩意

完成布局除了右側的東西其他都很簡單,那麼重點就是在右側的滑動控件了,沒錯,這玩意就是這個效果的最主要成員,暫且命名其為IndexWord(字幕索引),下面我們一步步來實作效果:

1.IndexWord自定義的初始化以及字幕的呈現

public class IndexWord extends View {

    private String[] words = {"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 TextPaint textPaint;//文本畫筆
    private int everywidth;//每一個字母單元格的寬度
    private int length;//words長度,
    private int everyheght;//每一個字母單元格的高度
    private Rect rect;//矩形
    private int index = -;//用于touchevent中記錄點選的是哪個字幕

    public IndexWord(Context context) {
        this(context, null);
    }

    public IndexWord(Context context, AttributeSet attrs) {
        this(context, attrs, );
    }

    public IndexWord(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initpaint();


    }
           

當然這裡的words可以通過各種途徑獲得到,看屬性就知道不怎麼複雜,主要是怎麼把字幕(漢子也可以)平均的畫出來,那麼問題轉化為如何獲得每個字母的坐标x,y了。自古文字留不住,唯有圖檔得人心,看一下下圖應該就了解了:

安卓仿手機聯系人右側快速搜尋菜單自定義View

drawtext中 x,y的坐标是可以更改的,需要注意的是預設情況下y的坐标是底線上的坐标值,

下面是onDraw中的代碼:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        initheight();
        for (int i = ; i < length; i++) {
            String word = words[i];
            textPaint.getTextBounds(word, , , rect);
            int width = rect.width();
            int height = rect.height();
            if (index == i) {
                textPaint.setColor(Color.RED);
            } else {
                textPaint.setColor(Color.BLACK);
            }
            canvas.drawText(word, everywidth /  - width / , everyheght * i+(everyheght/+        height/), textPaint);
        }

    }
           

這樣就把各個字幕畫在 了控件上,裡面的之是以有if判斷,待會會講到。

2.點選滑動事件的添加

仔細看的同學應該注意到了,當點選或者滑動到某個字母的時候,改字幕是要變色的,自然而然的就要處理觸屏事件了,重寫onTouchEvent方法如下:

@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN|MotionEvent.ACTION_MOVE:
                index = (int) (event.getY() / everyheght);
                if (indexPressWord != null && index >= ) {
                    indexPressWord.setIndexPressWord(words[index]);
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                index = -;
                invalidate();
                break;
            default:
        }
        return true;
    }
           

當某個子母被點選或者滑到的時候,通過index = (int) (event.getY() / everyheght)得到他是哪個字幕,也就是下标,然後調用invalidate()方法重走onDraw方法,在通過if判斷,如果點選的是這個字幕 改變 畫筆的顔色,這樣就實作了效果。

3.中間正方形字幕的實作

其實,上一步重寫onTouchEvent的時候我們已經得到了點選的字幕,這個時候我們隻是要把他在正方形中呈現出來而已,那麼就很容易實作了,直接通過接口會調就實作了,上一步驟中已經給出了回調:indexPressWord.setIndexPressWord(words[index]),直接在主線程中就可以set出來,讓正方形出現三秒再消失,這裡的方法有很多很多,我用的是handler,下面是主要代碼:

private void setTvWord() {
        iwMain.setIndexPressWord(new IndexWord.IndexPressWord() {
            @Override
            public void setIndexPressWord(String word) {
                tvMain.setVisibility(View.VISIBLE);
                tvMain.setText(word);
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        tvMain.setVisibility(View.GONE);
                    }
                }, );
            }
        });
    }
           

一看應該就會很明白了

4.Recycleview呈現資料源,以及跳到制定字幕的實作

這裡就不貼代碼了,說一下實作思路,還是看張圖檔:

安卓仿手機聯系人右側快速搜尋菜單自定義View

全是套路,哈哈,隻是把那些不該看到的東西隐藏掉了而已,當然如果覺得自己很牛叉,可以試試recycleview的多布局,保證會寫吐。

這裡的阿虎阿貓以及A、B是Perdon類的屬性;Person類如下:

public class Person {

    private String name;

    private String pinyin;

    public Person(String name){
        this.name = name;
        this.pinyin = PinYinUtils.getPinYin(name);
    }
           

代碼中的PersonUtils是專門把漢子轉換為拼音的工具類,我們截取拼音的第一位就得到了A、B,很容易。

具體如何判斷某個字母是不是第一次出現,待會兒可以看下源碼,很容易了解,這裡就不貼代碼了。

5.實作點選右側字母,聯系人自動移到對應聯系人

其實和中間的正方形顯示字幕一個意思,同樣是在回調裡面實作,回掉裡面拿到字幕Word,然後周遊persons,如果person拼音的首位與word相同,那麼記錄下位置i,然後移動就可以了,主要代碼如下:

private void getWord(String word) {

        for (int i = ; i < persons.size(); i++) {
            String substring = persons.get(i).getPinyin().substring(, );
            if (substring.equals(word) && persons.size() >= i) {
                //如果person拼音的首位與word相同,則實作效果,并退出循環
                View childAt = rvMain.getChildAt(i);
                MoveToPosition(linearmanger, rvMain, i);
                break;
            }
        }
    }

    /**
     * 此方法是讓recycleview滑動到指定位置,并且是讓其到頂部
     *
     * @param manager
     * @param mRecyclerView
     * @param n
     */
    public void MoveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
        int firstItem = manager.findFirstVisibleItemPosition();
        int lastItem = manager.findLastVisibleItemPosition();
        if (n <= firstItem) {
            mRecyclerView.scrollToPosition(n);
        } else if (n <= lastItem) {
            int top = mRecyclerView.getChildAt(n - firstItem).getTop();
            mRecyclerView.scrollBy(, top);
        } else {
            mRecyclerView.scrollToPosi
tion(n);
        }
    }
           

這樣就簡單實作了聯系人快速定位的功能,有問題請加QQ群661614986,點選檢視源碼。