创业水务公司网站,济宁市环保局建设项目审批网站,临沂seo网站推广,企业网络营销策划与分析效果图效果图分析先来分析一下#xff0c;可以看到这是一个按月份分组的2行图片列表#xff0c;列表顶部一个悬浮栏#xff0c;会随着列表滑动而刷新#xff0c;点击顶部栏#xff0c;弹出了一个筛选框。思路1.列表部分可以用RecyclerViewGridLayoutManager#xff0c;月… 效果图效果图分析先来分析一下可以看到这是一个按月份分组的2行图片列表列表顶部一个悬浮栏会随着列表滑动而刷新点击顶部栏弹出了一个筛选框。思路1.列表部分可以用RecyclerViewGridLayoutManager月份的标题栏可以使用多布局首先是主体item的布局?xml version1.0 encodingutf-8?android.support.v7.widget.CardView xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:backgroundcolor/cffffffapp:cardCornerRadius4dp android.support.constraint.ConstraintLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_content ImageView android:idid/iv_pictrue android:layout_widthmatch_parent android:layout_height0dp app:layout_constraintDimensionRatio1.78:1 / TextView android:idid/tv_pictrue_title android:layout_widthwrap_content android:layout_heightwrap_content android:layout_marginTop10dp android:textColorcolor/c151619 android:textSize16sp app:layout_constraintLeft_toLeftOfparent app:layout_constraintRight_toRightOfparent app:layout_constraintTop_toBottomOfid/iv_pictrue tools:text长沙会议图集(210) / TextView android:idid/tv_pictrue_time android:layout_widthwrap_content android:layout_heightwrap_content android:layout_marginTop2dp android:layout_marginBottom10dp tools:text2018-11-10 android:textColorcolor/c969696 android:textSize16sp app:layout_constraintBottom_toBottomOfparent app:layout_constraintLeft_toLeftOfparent app:layout_constraintRight_toRightOfparent app:layout_constraintTop_toBottomOfid/tv_pictrue_title / android.support.constraint.ConstraintLayoutandroid.support.v7.widget.CardViewPictureAdapter 这里使用了 BaseRecyclerViewAdapterHelper需要继承BaseMultiItemQuickAdapter关于adapter多布局的使用篇幅所限这里不再细述。public class PictureAdapter extends BaseMultiItemQuickAdapterPictureModel, BaseViewHolder { public PictureAdapter(Nullable List data) { super(data); addItemType(PictureModel.PICTURE_CONTENT, R.layout.item_pictures); addItemType(PictureModel.PICTURE_TITLE, R.layout.item_picture_month); } Override protected void convert(BaseViewHolder helper, PictureModel item) { if (helper.getItemViewType() PictureModel.PICTURE_CONTENT) { //标题/数量 helper.setText(R.id.tv_pictrue_title, item.getTitle() ( item.getPicture_count() )); //时间 helper.setText(R.id.tv_pictrue_time, item.getDate()); //封面图 GlideUtils.loadImg(mContext, item.getCover_image(), (ImageView) helper.getView(R.id.iv_pictrue)); } else if (helper.getItemViewType() PictureModel.PICTURE_TITLE) { helper.setText(R.id.tv_picture_month, item.getDate()); } } Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, PictureModel.PICTURE_TITLE); } Override public void onViewDetachedFromWindow(NonNull BaseViewHolder holder) { super.onViewDetachedFromWindow(holder); FullSpanUtil.onViewAttachedToWindow(holder, this, PictureModel.PICTURE_TITLE); }}其中由于月份的标题需要占满一行需要重写onAttachedToRecyclerView和onViewDetachedFromWindow方法。public class FullSpanUtil { public static void onAttachedToRecyclerView(RecyclerView recyclerView, final RecyclerView.Adapter adapter, final int pinnedHeaderType) { // 如果是网格布局这里处理标签的布局占满一行 final RecyclerView.LayoutManager layoutManager recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager (GridLayoutManager) layoutManager; final GridLayoutManager.SpanSizeLookup oldSizeLookup gridLayoutManager.getSpanSizeLookup(); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { Override public int getSpanSize(int position) { if (adapter.getItemViewType(position) pinnedHeaderType) { return gridLayoutManager.getSpanCount(); } if (oldSizeLookup ! null) { return oldSizeLookup.getSpanSize(position); } return 1; } }); } } public static void onViewAttachedToWindow(RecyclerView.ViewHolder holder, RecyclerView.Adapter adapter, int pinnedHeaderType) { // 如果是瀑布流布局这里处理标签的布局占满一行 final ViewGroup.LayoutParams lp holder.itemView.getLayoutParams(); if (lp instanceof StaggeredGridLayoutManager.LayoutParams) { final StaggeredGridLayoutManager.LayoutParams slp (StaggeredGridLayoutManager.LayoutParams) lp; slp.setFullSpan(adapter.getItemViewType(holder.getLayoutPosition()) pinnedHeaderType); } }}PictureModel需要继承MultiItemEntity然后重写getItemType方法adapter即可通过model的type来判断该使用哪个布局。注get和set方法这里就不贴了public class PictureModel implements MultiItemEntity { public static final int PICTURE_TITLE 1; public static final int PICTURE_CONTENT 0; private int type; private String id; private String title; private String date_time; private String create_time; private String picture_count; private String status; private String cover_image; private String date; public PictureModel(int type) { this.type type; } public int getType() { return type; } public void setType(int type) { this.type type; } Override public int getItemType() { return type; }}最后是在Activity使用 pictureAdapter new PictureAdapter(null); rvPictrues.setLayoutManager(new GridLayoutManager(context, 2)); SpaceDecoration spaceDecoration new SpaceDecoration(dp2px(context, 10)); spaceDecoration.setPaddingStart(false); rvPictrues.addItemDecoration(spaceDecoration); rvPictrues.setAdapter(pictureAdapter); pictureAdapter.bindToRecyclerView(rvPictrues); /** * dp转px * param context * param dpVal * return */ public static int dp2px(Context context, float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics()); }SpaceDecorationpublic class SpaceDecoration extends RecyclerView.ItemDecoration { private int space; private int headerCount -1; private int footerCount Integer.MAX_VALUE; private boolean mPaddingEdgeSide true; private boolean mPaddingStart true; private boolean mPaddingHeaderFooter false; private ColorDrawable mColorDrawable; private boolean mDrawLastItem true; private boolean mDrawHeaderFooter false; public SpaceDecoration(int space) { this.mColorDrawable new ColorDrawable(Color.parseColor(#e7e7e7)); this.space space; } public SpaceDecoration(int space, int color) { this.mColorDrawable new ColorDrawable(color); this.space space; } public void setPaddingEdgeSide(boolean mPaddingEdgeSide) { this.mPaddingEdgeSide mPaddingEdgeSide; } public void setPaddingStart(boolean mPaddingStart) { this.mPaddingStart mPaddingStart; } public void setPaddingHeaderFooter(boolean mPaddingHeaderFooter) { this.mPaddingHeaderFooter mPaddingHeaderFooter; }Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position parent.getChildAdapterPosition(view); int spanCount 0; int orientation 0; int spanIndex 0; int headerCount 0, footerCount 0; if (parent.getAdapter() instanceof BaseQuickAdapter) { headerCount ((BaseQuickAdapter) parent.getAdapter()).getHeaderLayoutCount(); footerCount ((BaseQuickAdapter) parent.getAdapter()).getFooterLayoutCount(); } RecyclerView.LayoutManager layoutManager parent.getLayoutManager(); if (layoutManager instanceof StaggeredGridLayoutManager) { orientation ((StaggeredGridLayoutManager) layoutManager).getOrientation(); spanCount ((StaggeredGridLayoutManager) layoutManager).getSpanCount(); spanIndex ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } else if (layoutManager instanceof GridLayoutManager) { orientation ((GridLayoutManager) layoutManager).getOrientation(); spanCount ((GridLayoutManager) layoutManager).getSpanCount(); spanIndex ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex(); } else if (layoutManager instanceof LinearLayoutManager) { orientation ((LinearLayoutManager) layoutManager).getOrientation(); spanCount 1; spanIndex 0; } /** * 普通Item的尺寸 */ if ((position headerCount position if (orientation VERTICAL) { float expectedWidth (float) (parent.getWidth() - space * (spanCount (mPaddingEdgeSide ? 1 : -1))) / spanCount; float originWidth (float) parent.getWidth() / spanCount; float expectedX (mPaddingEdgeSide ? space : 0) (expectedWidth space) * spanIndex; float originX originWidth * spanIndex; outRect.left (int) (expectedX - originX); outRect.right (int) (originWidth - outRect.left - expectedWidth); if (position - headerCount outRect.top space; } outRect.bottom space; return;} else { float expectedHeight (float) (parent.getHeight() - space * (spanCount (mPaddingEdgeSide ? 1 : -1))) / spanCount; float originHeight (float) parent.getHeight() / spanCount; float expectedY (mPaddingEdgeSide ? space : 0) (expectedHeight space) * spanIndex; float originY originHeight * spanIndex; outRect.bottom (int) (expectedY - originY); outRect.top (int) (originHeight - outRect.bottom - expectedHeight); if (position - headerCount outRect.left space; } outRect.right space; return;} } else if (mPaddingHeaderFooter) {if (orientation VERTICAL) { outRect.right outRect.left mPaddingEdgeSide ? space : 0; outRect.top mPaddingStart ? space : 0;} else { outRect.top outRect.bottom mPaddingEdgeSide ? space : 0; outRect.left mPaddingStart ? space : 0;} } } Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { if (parent.getAdapter() null) { return; } int orientation 0; int headerCount 0, footerCount 0, dataCount; if (parent.getAdapter() instanceof BaseQuickAdapter) {headerCount ((BaseQuickAdapter) parent.getAdapter()).getHeaderLayoutCount();footerCount ((BaseQuickAdapter) parent.getAdapter()).getFooterLayoutCount();dataCount parent.getAdapter().getItemCount(); } else {dataCount parent.getAdapter().getItemCount(); } int dataStartPosition headerCount; int dataEndPosition headerCount dataCount; RecyclerView.LayoutManager layoutManager parent.getLayoutManager(); if (layoutManager instanceof StaggeredGridLayoutManager) {orientation ((StaggeredGridLayoutManager) layoutManager).getOrientation(); } else if (layoutManager instanceof GridLayoutManager) {orientation ((GridLayoutManager) layoutManager).getOrientation(); } else if (layoutManager instanceof LinearLayoutManager) {orientation ((LinearLayoutManager) layoutManager).getOrientation(); } int start, end; if (orientation OrientationHelper.VERTICAL) {start parent.getPaddingLeft();end parent.getWidth() - parent.getPaddingRight(); } else {start parent.getPaddingTop();end parent.getHeight() - parent.getPaddingBottom(); } int childCount parent.getChildCount(); for (int i 0; i View child parent.getChildAt(i);int position parent.getChildAdapterPosition(child);if (position dataStartPosition position 1//数据项除了最后一项 || (position dataEndPosition - 1 mDrawLastItem)//数据项最后一项 || (!(position dataStartPosition position //headerfooter且可绘制 ) { if (orientation OrientationHelper.VERTICAL) { RecyclerView.LayoutParams params (RecyclerView.LayoutParams) child.getLayoutParams(); int top child.getBottom() params.bottomMargin; int bottom top; mColorDrawable.setBounds(start, top, end, bottom); mColorDrawable.draw(c); } else { RecyclerView.LayoutParams params (RecyclerView.LayoutParams) child.getLayoutParams(); int left child.getRight() params.rightMargin; int right left; mColorDrawable.setBounds(left, start, right, end); mColorDrawable.draw(c); }} } }}2.顶部栏部分这里可以使用ItemDecoration难点在于如何设置点击点击事件。感谢作者提供了一种新的思路 StickyItemDecoration这里只说如何使用原理阅读作者源码即可。按照这个思路我们可以将头部布局单独出来这样的话处理点击事件就很简单。activity布局RelativeLayoutandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid.support.v7.widget.RecyclerViewandroid:idid/rv_pictruesandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:backgroundcolor/cf7f8faandroid:nestedScrollingEnabledfalse /com.leda.yunke.widget.sticky.StickyHeadContainerandroid:idid/shc_pictruesandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:backgroundcolor/cffffff LinearLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:gravitycenter_horizontalandroid:orientationvertical TextViewandroid:idid/tv_picture_timeandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginTop8dpandroid:layout_marginBottom8dpandroid:drawableRightmipmap/unfoldandroid:drawablePadding10dpandroid:gravitycenterandroid:text2018年11月android:textColorcolor/c969696android:textSize16sp / TextView stylestyle/line_f3f3f3 / LinearLayoutcom.leda.yunke.widget.sticky.StickyHeadContainerRelativeLayoutStickyHeadContainerpublic class StickyHeadContainer extends ViewGroup { private int mOffset; private int mLastOffset Integer.MIN_VALUE; private int mLastStickyHeadPosition Integer.MIN_VALUE; private int mLeft; private int mRight; private int mTop; private int mBottom; private DataCallback mDataCallback; public StickyHeadContainer(Context context) { this(context, null); } public StickyHeadContainer(Context context, AttributeSet attrs) { this(context, attrs, 0); } public StickyHeadContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOnClickListener(new OnClickListener() {Overridepublic void onClick(View v) { // TODO: 2017/1/9 屏蔽点击事件} }); } Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int desireHeight; int desireWidth; int count getChildCount(); if (count ! 1) {throw new IllegalArgumentException(只允许容器添加1个子View); } final View child getChildAt(0); // 测量子元素并考虑外边距 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); // 获取子元素的布局参数 final MarginLayoutParams lp (MarginLayoutParams) child.getLayoutParams(); // 计算子元素宽度取子控件最大宽度 desireWidth child.getMeasuredWidth() lp.leftMargin lp.rightMargin; // 计算子元素高度 desireHeight child.getMeasuredHeight() lp.topMargin lp.bottomMargin; // 考虑父容器内边距 desireWidth getPaddingLeft() getPaddingRight(); desireHeight getPaddingTop() getPaddingBottom(); // 尝试比较建议最小值和期望值的大小并取大值 desireWidth Math.max(desireWidth, getSuggestedMinimumWidth()); desireHeight Math.max(desireHeight, getSuggestedMinimumHeight()); // 设置最终测量值 setMeasuredDimension(resolveSize(desireWidth, widthMeasureSpec), resolveSize(desireHeight, heightMeasureSpec)); } Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final View child getChildAt(0); MarginLayoutParams lp (MarginLayoutParams) child.getLayoutParams(); final int paddingLeft getPaddingLeft(); final int paddingTop getPaddingTop(); mLeft paddingLeft lp.leftMargin; mRight child.getMeasuredWidth() mLeft; mTop paddingTop lp.topMargin mOffset; mBottom child.getMeasuredHeight() mTop; child.layout(mLeft, mTop, mRight, mBottom); } // 生成默认的布局参数 Override protected LayoutParams generateDefaultLayoutParams() { return super.generateDefaultLayoutParams(); } // 生成布局参数,将布局参数包装成我们的 Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } // 生成布局参数,从属性配置中生成我们的布局参数 Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } // 查当前布局参数是否是我们定义的类型这在code声明布局参数时常常用到 Override protected boolean checkLayoutParams(LayoutParams p) { return p instanceof MarginLayoutParams; } public void scrollChild(int offset) { if (mLastOffset ! offset) {mOffset offset;ViewCompat.offsetTopAndBottom(getChildAt(0), mOffset - mLastOffset); } mLastOffset mOffset; } protected int getChildHeight() { return getChildAt(0).getHeight(); } protected void onDataChange(int stickyHeadPosition) { if (mDataCallback ! null mLastStickyHeadPosition ! stickyHeadPosition) {mDataCallback.onDataChange(stickyHeadPosition); } mLastStickyHeadPosition stickyHeadPosition; } public void reset() { mLastStickyHeadPosition Integer.MIN_VALUE; } public interface DataCallback { void onDataChange(int pos); } public void setDataCallback(DataCallback dataCallback) { mDataCallback dataCallback; }}在activity中完整使用StickyItemDecoration stickyItemDecoration new StickyItemDecoration(shcPictrues, PictureModel.PICTURE_TITLE);stickyItemDecoration.setOnStickyChangeListener(new OnStickyChangeListener() {Overridepublic void onScrollable(int offset) { //可见时 shcPictrues.scrollChild(offset); shcPictrues.setVisibility(View.VISIBLE);}Overridepublic void onInVisible() { //不可见时 shcPictrues.reset(); shcPictrues.setVisibility(View.INVISIBLE);} }); shcPictrues.setDataCallback(new StickyHeadContainer.DataCallback() {Overridepublic void onDataChange(int pos) { //数据更新 List listModels pictureAdapter.getData();if (listModels.size() pos) { tvPictureTime.setText(listModels.get(pos).getDate()); }} });//添加至rv rvPictrues.addItemDecoration(stickyItemDecoration); pictureAdapter new PictureAdapter(null); rvPictrues.setLayoutManager(new GridLayoutManager(context, 2)); rvPictrues.addItemDecoration(stickyItemDecoration); SpaceDecoration spaceDecoration new SpaceDecoration(DensityUtils.dp2px(context, 10)); spaceDecoration.setPaddingStart(false); rvPictrues.addItemDecoration(spaceDecoration); rvPictrues.setAdapter(pictureAdapter); pictureAdapter.bindToRecyclerView(rvPictrues);StickyItemDecorationpublic class StickyItemDecoration extends RecyclerView.ItemDecoration { private int mStickyHeadType; private int mFirstVisiblePosition; //private int mFirstCompletelyVisiblePosition; private int mStickyHeadPosition; private int[] mInto; private RecyclerView.Adapter mAdapter; private StickyHeadContainer mStickyHeadContainer; private boolean mEnableStickyHead true; private OnStickyChangeListener mOnStickyChangeListener; public void setOnStickyChangeListener(OnStickyChangeListener onStickyChangeListener){ this.mOnStickyChangeListener onStickyChangeListener; } public StickyItemDecoration(StickyHeadContainer stickyHeadContainer, int stickyHeadType) { mStickyHeadContainer stickyHeadContainer; mStickyHeadType stickyHeadType; } // 当我们调用mRecyclerView.addItemDecoration()方法添加decoration的时候RecyclerView在绘制的时候去会绘制decorator即调用该类的onDraw和onDrawOver方法 // 1.onDraw方法先于drawChildren // 2.onDrawOver在drawChildren之后一般我们选择复写其中一个即可。 // 3.getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量主要用于绘制Decorator。 Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); checkCache(parent); if (mAdapter null) {// checkCache的话RecyclerView未设置之前mAdapter为空return; } calculateStickyHeadPosition(parent); if (mEnableStickyHead /* mFirstCompletelyVisiblePosition mStickyHeadPosition*/ mFirstVisiblePosition mStickyHeadPosition mStickyHeadPosition ! -1) {View belowView parent.findChildViewUnder(c.getWidth() / 2, mStickyHeadContainer.getChildHeight() 0.01f);mStickyHeadContainer.onDataChange(mStickyHeadPosition);int offset;if (isStickyHead(parent, belowView) belowView.getTop() 0) { offset belowView.getTop() - mStickyHeadContainer.getChildHeight();} else { offset 0;}if (mOnStickyChangeListener!null){ mOnStickyChangeListener.onScrollable(offset);} } else {if (mOnStickyChangeListener!null){ mOnStickyChangeListener.onInVisible();} } } public void enableStickyHead(boolean enableStickyHead) { mEnableStickyHead enableStickyHead; if (!mEnableStickyHead) {mStickyHeadContainer.setVisibility(View.INVISIBLE); } } private void calculateStickyHeadPosition(RecyclerView parent) { final RecyclerView.LayoutManager layoutManager parent.getLayoutManager(); // mFirstCompletelyVisiblePosition findFirstCompletelyVisiblePosition(layoutManager); // 获取第一个可见的item位置 mFirstVisiblePosition findFirstVisiblePosition(layoutManager); // 获取标签的位置 int stickyHeadPosition findStickyHeadPosition(mFirstVisiblePosition); if (stickyHeadPosition 0 mStickyHeadPosition ! stickyHeadPosition) {// 标签位置有效并且和缓存的位置不同mStickyHeadPosition stickyHeadPosition; } } /** * 从传入位置递减找出标签的位置 * param formPosition * return */ private int findStickyHeadPosition(int formPosition) { for (int position formPosition; position 0; position--) { // 位置递减只要查到位置是标签立即返回此位置 final int type mAdapter.getItemViewType(position); if (isStickyHeadType(type)) { return position;} } return -1; } /** * 通过适配器告知类型是否为标签 * param type * return */ private boolean isStickyHeadType(int type) { return mStickyHeadType type; } /** * 找出第一个可见的Item的位置 * param layoutManager * return */ private int findFirstVisiblePosition(RecyclerView.LayoutManager layoutManager) { int firstVisiblePosition 0; if (layoutManager instanceof GridLayoutManager) {firstVisiblePosition ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition(); } else if (layoutManager instanceof LinearLayoutManager) {firstVisiblePosition ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition(); } else if (layoutManager instanceof StaggeredGridLayoutManager) {mInto new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(mInto);firstVisiblePosition Integer.MAX_VALUE;for (int pos : mInto) { firstVisiblePosition Math.min(pos, firstVisiblePosition);} } return firstVisiblePosition; } /** * 找出第一个完全可见的Item的位置 * param layoutManager * return */ private int findFirstCompletelyVisiblePosition(RecyclerView.LayoutManager layoutManager) { int firstVisiblePosition 0; if (layoutManager instanceof GridLayoutManager) {firstVisiblePosition ((GridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition(); } else if (layoutManager instanceof LinearLayoutManager) {firstVisiblePosition ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition(); } else if (layoutManager instanceof StaggeredGridLayoutManager) {mInto new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];((StaggeredGridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPositions(mInto);firstVisiblePosition Integer.MAX_VALUE;for (int pos : mInto) { firstVisiblePosition Math.min(pos, firstVisiblePosition);} } return firstVisiblePosition; } /** * 检查缓存 * * param parent */ private void checkCache(final RecyclerView parent) { final RecyclerView.Adapter adapter parent.getAdapter(); if (mAdapter ! adapter) {mAdapter adapter;// 适配器为null或者不同清空缓存mStickyHeadPosition -1;mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { Override public void onChanged() { reset(); } Override public void onItemRangeChanged(int positionStart, int itemCount) { reset(); } Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { reset(); } Override public void onItemRangeInserted(int positionStart, int itemCount) { reset(); } Override public void onItemRangeRemoved(int positionStart, int itemCount) { reset(); } Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { reset(); }}); } } private void reset() { mStickyHeadContainer.reset(); } /** * 查找到view对应的位置从而判断出是否标签类型 * param parent * param view * return */ private boolean isStickyHead(RecyclerView parent, View view) { final int position parent.getChildAdapterPosition(view); if (position RecyclerView.NO_POSITION) {return false; } final int type mAdapter.getItemViewType(position); return isStickyHeadType(type); }}3.点击顶部栏弹窗偷个懒不贴代码了。最后就是组装数据然后设置给pictureAdapter即可。完整源码https://github.com/18702953620/PicRvDemo大家都在看Android自定义频道选择器、频道定制Flutter 学习及实战分享你必须要掌握的Android冷启动优化Android自定义View快递时间轴实现欢迎前往安卓巴士博客区投稿技术成长于分享期待巴友留言共同探讨学习