参考文章
  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
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐