參考文章
- Android使用RecycleView實現魅族手機通訊錄界面
- Android微信通訊錄滑動快速定位實現
- 更快實現Android多級樹形選擇列表
- 其中recyclerview部分參考第一篇文章,側邊欄參考第二篇文章
關鍵點:
-
判斷是否分組的開始
-
ItemDecoration
- getItemOffsets爲繪製分組頭部字母和分割線預留空間
- onDraw繪製分組頭部字母
- onDrawOver繪製懸停字母
-
側邊欄的實現
- 側邊欄的事件
效果如下
關鍵代碼
-
關鍵點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代碼
@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代碼
@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); } }