转载

安卓当下最流行的吸顶效果的实现(下)

安卓当下最流行的吸顶效果的实现(下)

接上文

第一步:首先我们来写一个类,它起标记的作用,来放每一个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 "";   
                }   
            })); 

这样就完成了~

再看一眼最终效果感受一下:

安卓当下最流行的吸顶效果的实现(下)

原文  http://mobile.51cto.com/android-527792.htm
正文到此结束
Loading...