接上文
***步:首先我们来写一个类,它起标记的作用,来放每一个item的对应的悬浮栏的字符串
- public class NameBean {
- String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
第二步:自定义一个SectionDecoration 类 继承 RecyclerView的ItemDecoration
- public class SectionDecoration extends RecyclerView.ItemDecoration {
- private static final String TAG = "SectionDecoration";
- private List<NameBean> dataList;
- private DecorationCallback callback;
- private TextPaint textPaint;
- private Paint paint;
- private int topGap;
- private int alignBottom;
- private Paint.FontMetrics fontMetrics;
- public SectionDecoration(List<NameBean> dataList, Context context, DecorationCallback decorationCallback) {
- Resources res = context.getResources();
- this.dataList = dataList;
- this.callback = decorationCallback;
- //设置悬浮栏的画笔---paint
- paint = new Paint();
- paint.setColor(res.getColor(R.color.colorGray));
- //设置悬浮栏中文本的画笔
- textPaint = new TextPaint();
- textPaint.setAntiAlias(true);
- textPaint.setTextSize(DensityUtil.dip2px(context, 14));
- textPaint.setColor(Color.DKGRAY);
- textPaint.setTextAlign(Paint.Align.LEFT);
- fontMetrics = new Paint.FontMetrics();
- //决定悬浮栏的高度等
- topGap = res.getDimensionPixelSize(R.dimen.sectioned_top);
- //决定文本的显示位置等
- alignBottom = res.getDimensionPixelSize(R.dimen.sectioned_alignBottom);
- }
- @Override
- public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
- super.getItemOffsets(outRect, view, parent, state);
- int pos = parent.getChildAdapterPosition(view);
- Log.i(TAG, "getItemOffsets:" + pos);
- String groupId = callback.getGroupId(pos);
- if (groupId.equals("-1")) return;
- //只有是同一组的***个才显示悬浮栏
- if (pos == 0 || isFirstInGroup(pos)) {
- outRect.top = topGap;
- if (dataList.get(pos).getName() == "") {
- outRect.top = 0;
- }
- } else {
- outRect.top = 0;
- }
- }
- @Override
- public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
- super.onDraw(c, parent, state);
- int left = parent.getPaddingLeft();
- int right = parent.getWidth() - parent.getPaddingRight();
- int childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View view = parent.getChildAt(i);
- int position = parent.getChildAdapterPosition(view);
- String groupId = callback.getGroupId(position);
- if (groupId.equals("-1")) return;
- String textLine = callback.getGroupFirstLine(position).toUpperCase();
- if (textLine == "") {
- float top = view.getTop();
- float bottom = view.getTop();
- c.drawRect(left, top, right, bottom, paint);
- return;
- } else {
- if (position == 0 || isFirstInGroup(position)) {
- float top = view.getTop() - topGap;
- float bottom = view.getTop();
- //绘制悬浮栏
- c.drawRect(left, top - topGap, right, bottom, paint);
- //绘制文本
- c.drawText(textLine, left, bottom, textPaint);
- }
- }
- }
- }
- @Override
- public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
- super.onDrawOver(c, parent, state);
- int itemCount = state.getItemCount();
- int childCount = parent.getChildCount();
- int left = parent.getPaddingLeft();
- int right = parent.getWidth() - parent.getPaddingRight();
- float lineHeight = textPaint.getTextSize() + fontMetrics.descent;
- String preGroupId = "";
- String groupId = "-1";
- for (int i = 0; i < childCount; i++) {
- View view = parent.getChildAt(i);
- int position = parent.getChildAdapterPosition(view);
- preGroupId = groupId;
- groupId = callback.getGroupId(position);
- if (groupId.equals("-1") || groupId.equals(preGroupId)) continue;
- String textLine = callback.getGroupFirstLine(position).toUpperCase();
- if (TextUtils.isEmpty(textLine)) continue;
- int viewBottom = view.getBottom();
- float textY = Math.max(topGap, view.getTop());
- //下一个和当前不一样移动当前
- if (position + 1 < itemCount) {
- String nextGroupId = callback.getGroupId(position + 1);
- //组内***一个view进入了header
- if (nextGroupId != groupId && viewBottom < textY) {
- textY = viewBottom;
- }
- }
- //textY - topGap决定了悬浮栏绘制的高度和位置
- c.drawRect(left, textY - topGap, right, textY, paint);
- //left+2*alignBottom 决定了文本往左偏移的多少(加-->向左移)
- //textY-alignBottom 决定了文本往右偏移的多少 (减-->向上移)
- c.drawText(textLine, left + 2 * alignBottom, textY - alignBottom, textPaint);
- }
- }
- /**
- * 判断是不是组中的***个位置
- *
- * @param pos
- * @return
- */
- private boolean isFirstInGroup(int pos) {
- if (pos == 0) {
- return true;
- } else {
- // 因为是根据 字符串内容的相同与否 来判断是不是同意组的,所以此处的标记id 要是String类型
- // 如果你只是做联系人列表,悬浮框里显示的只是一个字母,则标记id直接用 int 类型就行了
- String prevGroupId = callback.getGroupId(pos - 1);
- String groupId = callback.getGroupId(pos);
- //判断前一个字符串 与 当前字符串 是否相同
- if (prevGroupId.equals(groupId)) {
- return false;
- } else {
- return true;
- }
- }
- }
- //定义一个借口方便外界的调用
- interface DecorationCallback {
- String getGroupId(int position);
- String getGroupFirstLine(int position);
- }
- }
第三步:在向list集合中先把每一个item的 起“标记”作用的字符串都加进去
- setPullAction(comingslist);
- private void setPullAction(List<WaitMVBean.DataBean.ComingBean> comingslist) {
- dataList = new ArrayList<>();
- for (int i = 0; i < comingslist.size(); i++) {
- NameBean nameBean = new NameBean();
- String name0 = comingslist.get(i).getComingTitle();
- nameBean.setName(name0);
- dataList.add(nameBean);
- }
- }
第四步:在setAdapter() 前,为RecyclerView添加ItemDecoration:
- recyclerView.addItemDecoration(new SectionDecoration(dataList,mContext, new SectionDecoration.DecorationCallback() {
- //返回标记id (即每一项对应的标志性的字符串)
- @Override
- public String getGroupId(int position) {
- if(dataList.get(position).getName()!=null) {
- return dataList.get(position).getName();
- }
- return "-1";
- }
- //获取同组中的***个内容
- @Override
- public String getGroupFirstLine(int position) {
- if(dataList.get(position).getName()!=null) {
- return dataList.get(position).getName();
- }
- return "";
- }
- }));
这样就完成了~
再看一眼最终效果感受一下: