老豬帶你玩轉android自定義控件二——自定義索引欄listview


  帶索引欄的listview,在android開發非常普遍,方便用戶進行字母索引,就像微信通訊錄這樣:

 

  今天,我們就從零到一實現這個具有索引欄的listview.

  怎么實現這個控件了,我們應當梳理出一個思路。

  ①首先應當將字母的索引欄繼承與一個控件,通過ondraw方法將字母畫出來。

  ②然后我們應該監聽這個字母控件的ontouch事件,來判斷用戶到底是按了那個字母。

  ③就是實現這個索引欄與listview的聯動,就是將listview滑動到按下字母的位置。

  大體流程圖如下:

 

  有了前面鋪墊,我們引出本文重頭戲——代碼。

  首先,索引欄這個控件如何將字母繪制在控件上的代碼:

    /**
     * 側邊欄顯示字母
     */
    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", "#" };
    /**
     * 繪制列表控件的方法
     * 將要繪制的字母以從上到下的順序繪制在一個指定區域
     * 如果是進行選中的字母就進行高亮顯示
     */
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        int height = getHeight();// 獲取對應高度
        int width = getWidth(); // 獲取對應寬度
        int singleHeight = height / words.length;// 獲取每一個字母的高度

        for (int i = 0; i < words.length; i++) {
            paint.setColor(Color.rgb(33, 65, 98));
            // paint.setColor(Color.WHITE);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);
            paint.setTextSize(20f);
            // 選中的狀態
            if (isdown) {
                paint.setColor(Color.parseColor("#ffffff"));
                //paint.setFakeBoldText(true);
            }
            // x坐標等於中間-字符串寬度的一半.
            float xPos = width / 2 - paint.measureText(words[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(words[i], xPos, yPos, paint);
            paint.reset();// 重置畫筆
        }
    }

  通過上述的代碼,我們可以得出以下的結論:將要繪制的字母以從上到下的順序繪制在一個指定區域,每個字母的x坐標是一樣的,x坐標即為控件寬度一半。如果當前字母選中的話,就高亮顯示。思路如圖所示:

  緊接着,就來到第二步,確定用戶到底點擊是那個字母,代碼如下:

/**
     * 處理觸摸事件的方法
     * 用戶按下時候,整個控件背景變化
     * 根據按下y坐標 判斷究竟用戶按下那個字母
     * 當前字母高亮顯示 將其字母顯示listview中央
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int action = event.getAction();
        final float y = event.getY();// 點擊y坐標
        final int oldChoose = choose;
        final ITouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * words.length);// 點擊y坐標所占總高度的比例*b數組的長度就等於點擊b中的個數.
        switch (action) {
        case MotionEvent.ACTION_UP:
            isdown=false;
            setBackgroundResource(android.R.color.transparent);
            choose = -1;//
            invalidate();
            if (textViewDialog != null) {
                textViewDialog.setVisibility(View.INVISIBLE);
            }
            break;

        default:
            isdown=true;
            setBackgroundResource(R.color.sidebar_bg_color);
            if (oldChoose != c) {
                if (c >= 0 && c < words.length) {
                    if (listener != null) {
                        listener.OnTouchingLetterChanged(words[c]);
                    }
                    if (textViewDialog != null) {
                        textViewDialog.setText(words[c]);
                        textViewDialog.setVisibility(View.VISIBLE);
                    }

                    choose = c;
                    invalidate();
                }
            }
            break;
        }
        return true;
    }

  通過上述的代碼,我們可以這樣總結:當用戶按下的時候,整個控件背景發生變化,根據用戶按下的y坐標來確定用戶究竟是按下那個字母,並且將按下字母顯示屏幕的中央,效果圖如下:

  最終,將listview 移動到按下字母相應位置,代碼如下:

/**
         * 根據用戶點擊那個字母將listview移動到相應位置
         */
        sidebar.setOnTouchingLetterChangedListener(new ITouchingLetterChangedListener() {

            @Override
            public void OnTouchingLetterChanged(String cString) {
                int position = -1;
                if (cString.length() > 0) {
                    position = myAdapter.getPositionForSection(cString
                            .charAt(0));
                }
                if (position != -1) {
                    listview.setSelection(position);
                } else if (cString.contains("#")) {
                    listview.setSelection(0);
                }
            }
        });

  連篇累牘說了這么多,控件大功告成的效果為:

  源代碼地址為:

  http://pan.baidu.com/s/1dDMDjhR


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM