android通訊錄(任意層級樹形列表和字母列表切換)

參考文章

  1. Android使用RecycleView實現魅族手機通訊錄界面
  2. Android微信通訊錄滑動快速定位實現
  3. 更快實現Android多級樹形選擇列表
  4. 其中recyclerview部分參考第一篇文章,側邊欄參考第二篇文章

關鍵點:

  1. 判斷是否分組的開始

  2. ItemDecoration

    1. getItemOffsets爲繪製分組頭部字母和分割線預留空間
    2. onDraw繪製分組頭部字母
    3. onDrawOver繪製懸停字母
  3. 側邊欄的實現

    1. 側邊欄的事件

效果如下

在這裏插入圖片描述


關鍵代碼

  1. 關鍵點1代碼

    /**
     * 是否是分組頭部 當前位置和上一個位置的首字母不一樣,則是分組的頭部
     * @param position 位置
     * @return
     */
    private boolean isSectionHeader(int position){
        if (position == 0){
            return true;
        }else{
            if (!modelList.get(position).getIndexTag().equals(modelList.get(position - 1).getIndexTag())){
                return true;
            }else {
                return false;
            }
        }
    }
    
  2. 關鍵點2代碼

     @Override
     public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
         //parent.getChildLayoutPosition(view); 區別
         int position = parent.getChildAdapterPosition(view);
         if (modelList == null || modelList.size() == 0 || modelList.size() <= position || position < 0) {
             super.getItemOffsets(outRect, view, parent, state);
             return;
         }
         if (isSectionHeader(position)){
             outRect.top = dividerHeight;
         }else {
             outRect.top = 1;
         }
     }
    
        @Override
        public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            int count = parent.getChildCount();
            for (int i = 0; i < count; i++) {
                View view = parent.getChildAt(i);
                int position = parent.getChildAdapterPosition(view);
                //考慮到recyclerview的內邊距
                int left = parent.getPaddingLeft();
                int right = parent.getWidth() - parent.getPaddingRight();//?parent.getRight - parent.getPaddingRight()
                if (isSectionHeader(position)){//分組頭部
                    //1.先畫矩形
    //                c.drawRect(0,view.getTop() - dividerHeight,right,view.getTop(),mPaint);
                    //2.畫圓
                    //改變畫筆的顏色
    //                ColorUtil.setPaintColor(mPaint,tagsStr.indexOf(modelList.get(position).getIndexTag()));
    //                c.drawCircle(QMUIDisplayHelper.dp2px(mContext, 42), view.getTop() - dividerHeight / 2, 35, mPaint);
                    //3.畫字
                    mPaint.setTextSize(40);
                    mPaint.setColor(Color.parseColor("#909090"));
                    c.drawText(modelList.get(position).getFirstLetter(),QMUIDisplayHelper.dp2px(mContext,42),view.getTop()-dividerHeight/3,mPaint);
                }else {//普通item
    //                c.drawRect(0,view.getTop() - 1,right,view.getTop(),linePaint);
    //                c.drawLine(0,view.getTop() - 1,right,view.getTop(),linePaint);//畫分割線,寬度不會撐滿
                }
            }
        }
    
    
        @Override
        public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            //第一個可見的item的position
            int position = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
            if (modelList == null || modelList.size() == 0 || modelList.size() <= position || position < 0){
                return;
            }
            int bottom = parent.getPaddingTop() + dividerHeight;
            mPaint.setColor(Color.parseColor("#ffffff"));
            c.drawRect(parent.getLeft(), parent.getPaddingTop(), parent.getRight() - parent.getPaddingRight(), parent.getPaddingTop() + dividerHeight, mPaint);
    //        ColorUtil.setPaintColor(mPaint, tagsStr.indexOf(modelList.get(position).getIndexTag()));
    //        c.drawCircle(QMUIDisplayHelper.dp2px(mContext, 42), bottom - dividerHeight / 2, 35, mPaint);
            mPaint.setTextSize(40);
            mPaint.setColor(Color.parseColor("#007aff"));
            c.drawText(modelList.get(position).getFirstLetter(), QMUIDisplayHelper.dp2px(mContext, 42), bottom - dividerHeight / 3, mPaint);
        }
    
    
  3. 關鍵點3代碼

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setBackgroundColor(TOUCHED_BACKGROUND_COLOR);
                handle(event);
                return true;
            case MotionEvent.ACTION_MOVE:
                handle(event);
                return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                setBackgroundColor(Color.TRANSPARENT);
                handle(event);
                return true;
        }
        return super.onTouchEvent(event);
    }
    
        private void handle(MotionEvent event) {
    
            int color =  downTextColor;
            if (event.getAction() == MotionEvent.ACTION_UP){
                color = indexTextColor;
            }
            for (int i = 0; i < getChildCount(); i++) {
                View vi = getChildAt(i);
                if (vi instanceof TextView){
                    ((TextView) vi).setTextColor(color);
                }
            }
    
            int y = (int) event.getY();
            int height = getHeight();
            //觸摸點的距離除以每個字母的高度(控件高度除以字母的個數)
            int position =  y / (height/INDEXES.length);
            if (position < 0){
                position = 0;
            }else if (position >= INDEXES.length){
                position = INDEXES.length - 1;
            }
            String tag = INDEXES[position];
            boolean showInicator = event.getAction() != MotionEvent.ACTION_UP && event.getAction() != MotionEvent.ACTION_CANCEL;
            if (listener != null){
                listener.onIndexChanged(tag,position, showInicator);
            }
        }
    

完整代碼github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章