原标题:【Android视图效果】分组列表实现吸顶效果
效果图
效果图 分析
先来分析一下,可以看到这是一个按月份分组的2行图片列表,列表顶部一个悬浮栏,会随着列表滑动而刷新,点击顶部栏,弹出了一个筛选框。
思路1.列表部分
可以用RecyclerView+GridLayoutManager,月份的标题栏可以使用多布局
首先是主体item的布局
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cffffff"
app:cardCornerRadius="4dp">
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:id="@+id/iv_pictrue"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1.78:1"/>
android:id="@+id/tv_pictrue_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColor="@color/c151619"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_pictrue"
tools:text="长沙会议图集(210)"/>
android:id="@+id/tv_pictrue_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="10dp"
tools:text="2018-11-10"
android:textColor="@color/c969696"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_pictrue_title"/>
PictureAdapter 这里使用了 BaseRecyclerViewAdapterHelper,需要继承BaseMultiItemQuickAdapter,关于adapter多布局的使用,篇幅所限,这里不再细述。
publicclassPictureAdapterextendsBaseMultiItemQuickAdapter{
publicPictureAdapter(@Nullable List data){
super(data);
addItemType(PictureModel.PICTURE_CONTENT, R.layout.item_pictures);
addItemType(PictureModel.PICTURE_TITLE, R.layout.item_picture_month);
}
@Override
protectedvoidconvert(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));
} elseif(helper.getItemViewType == PictureModel.PICTURE_TITLE) {
helper.setText(R.id.tv_picture_month, item.getDate);
}
}
@Override
publicvoidonAttachedToRecyclerView(RecyclerView recyclerView){
super.onAttachedToRecyclerView(recyclerView);
FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, PictureModel.PICTURE_TITLE);
}
@Override
publicvoidonViewDetachedFromWindow(@NonNull BaseViewHolder holder){
super.onViewDetachedFromWindow(holder);
FullSpanUtil.onViewAttachedToWindow(holder, this, PictureModel.PICTURE_TITLE);
}
}
其中,由于月份的标题需要占满一行,需要重写onAttachedToRecyclerView和onViewDetachedFromWindow方法。
publicclassFullSpanUtil{
publicstaticvoidonAttachedToRecyclerView(RecyclerView recyclerView, finalRecyclerView.Adapter adapter, finalintpinnedHeaderType){
// 如果是网格布局,这里处理标签的布局占满一行
finalRecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager;
if(layoutManager instanceofGridLayoutManager) {
finalGridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
finalGridLayoutManager.SpanSizeLookup oldSizeLookup = gridLayoutManager.getSpanSizeLookup;
gridLayoutManager.setSpanSizeLookup( newGridLayoutManager.SpanSizeLookup {
@Override
publicintgetSpanSize(intposition){
if(adapter.getItemViewType(position) == pinnedHeaderType) {
returngridLayoutManager.getSpanCount;
}
if(oldSizeLookup != null) {
returnoldSizeLookup.getSpanSize(position);
}
return1;
}
});
}
}
publicstaticvoidonViewAttachedToWindow(RecyclerView.ViewHolder holder, RecyclerView.Adapter adapter, intpinnedHeaderType){
// 如果是瀑布流布局,这里处理标签的布局占满一行
finalViewGroup.LayoutParams lp = holder.itemView.getLayoutParams;
if(lp instanceofStaggeredGridLayoutManager.LayoutParams) {
finalStaggeredGridLayoutManager.LayoutParams slp = (StaggeredGridLayoutManager.LayoutParams) lp;
slp.setFullSpan(adapter.getItemViewType(holder.getLayoutPosition) == pinnedHeaderType);
}
}
}
PictureModel需要继承MultiItemEntity,然后重写getItemType方法,adaptermodel的type
注:get和set方法这里就不贴了
publicclassPictureModelimplementsMultiItemEntity{
publicstaticfinalintPICTURE_TITLE = 1;
publicstaticfinalintPICTURE_CONTENT = 0;
privateinttype;
privateString id;
privateString title;
privateString date_time;
privateString create_time;
privateString picture_count;
privateString status;
privateString cover_image;
privateString date;
publicPictureModel(inttype){
this.type = type;
}
publicintgetType{
returntype;
}
publicvoidsetType(inttype){
this.type = type;
}
@Override
publicintgetItemType{
returntype;
}
}
最后,是在Activity使用
pictureAdapter = newPictureAdapter( null);
rvPictrues.setLayoutManager( newGridLayoutManager(context, 2));
SpaceDecoration spaceDecoration = newSpaceDecoration(dp2px(context, 10));
spaceDecoration.setPaddingStart( false);
rvPictrues.addItemDecoration(spaceDecoration);
rvPictrues.setAdapter(pictureAdapter);
pictureAdapter.bindToRecyclerView(rvPictrues);
/**
* dp转px
* @paramcontext
* @paramdpVal
* @return
*/
publicstaticintdp2px(Context context, floatdpVal){
return( int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
context.getResources.getDisplayMetrics);
}
SpaceDecoration
publicclassSpaceDecorationextendsRecyclerView.ItemDecoration{
privateintspace;
privateintheaderCount = - 1;
privateintfooterCount = Integer.MAX_VALUE;
privatebooleanmPaddingEdgeSide = true;
privatebooleanmPaddingStart = true;
privatebooleanmPaddingHeaderFooter = false;
privateColorDrawable mColorDrawable;
privatebooleanmDrawLastItem = true;
privatebooleanmDrawHeaderFooter = false;
publicSpaceDecoration(intspace){
this.mColorDrawable = newColorDrawable(Color.parseColor( "#e7e7e7"));
this.space = space;
}
publicSpaceDecoration(intspace, intcolor){
this.mColorDrawable = newColorDrawable(color);
this.space = space;
}
publicvoidsetPaddingEdgeSide(booleanmPaddingEdgeSide){
this.mPaddingEdgeSide = mPaddingEdgeSide;
}
publicvoidsetPaddingStart(booleanmPaddingStart){
this.mPaddingStart = mPaddingStart;
}
publicvoidsetPaddingHeaderFooter(booleanmPaddingHeaderFooter){
this.mPaddingHeaderFooter = mPaddingHeaderFooter;
}
@Override
publicvoidgetItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state){
intposition = parent.getChildAdapterPosition(view);
intspanCount = 0;
intorientation = 0;
intspanIndex = 0;
intheaderCount = 0, footerCount = 0;
if(parent.getAdapter instanceofBaseQuickAdapter) {
headerCount = ((BaseQuickAdapter) parent.getAdapter).getHeaderLayoutCount;
footerCount = ((BaseQuickAdapter) parent.getAdapter).getFooterLayoutCount;
}
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager;
if(layoutManager instanceofStaggeredGridLayoutManager) {
orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation;
spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount;
spanIndex = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams).getSpanIndex;
} elseif(layoutManager instanceofGridLayoutManager) {
orientation = ((GridLayoutManager) layoutManager).getOrientation;
spanCount = ((GridLayoutManager) layoutManager).getSpanCount;
spanIndex = ((GridLayoutManager.LayoutParams) view.getLayoutParams).getSpanIndex;
} elseif(layoutManager instanceofLinearLayoutManager) {
orientation = ((LinearLayoutManager) layoutManager).getOrientation;
spanCount = 1;
spanIndex = 0;
}
/**
* 普通Item的尺寸
*/
if((position >= headerCount && position < parent.getAdapter.getItemCount - footerCount)) {
if(orientation == VERTICAL) {
floatexpectedWidth = ( float) (parent.getWidth - space * (spanCount + (mPaddingEdgeSide ? 1: - 1))) / spanCount;
floatoriginWidth = ( float) parent.getWidth / spanCount;
floatexpectedX = (mPaddingEdgeSide ? space : 0) + (expectedWidth + space) * spanIndex;
floatoriginX = originWidth * spanIndex;
outRect.left = ( int) (expectedX - originX);
outRect.right = ( int) (originWidth - outRect.left - expectedWidth);
if(position - headerCount < spanCount && mPaddingStart) {
outRect.top = space;
}
outRect.bottom = space;
return;
} else{
floatexpectedHeight = ( float) (parent.getHeight - space * (spanCount + (mPaddingEdgeSide ? 1: - 1))) / spanCount;
floatoriginHeight = ( float) parent.getHeight / spanCount;
floatexpectedY = (mPaddingEdgeSide ? space : 0) + (expectedHeight + space) * spanIndex;
floatoriginY = originHeight * spanIndex;
outRect.bottom = ( int) (expectedY - originY);
outRect.top = ( int) (originHeight - outRect.bottom - expectedHeight);
if(position - headerCount < spanCount && mPaddingStart) {
outRect.left = space;
}
outRect.right = space;
return;
}
} elseif(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
publicvoidonDraw(Canvas c, RecyclerView parent, RecyclerView.State state){
if(parent.getAdapter == null) {
return;
}
intorientation = 0;
intheaderCount = 0, footerCount = 0, dataCount;
if(parent.getAdapter instanceofBaseQuickAdapter) {
headerCount = ((BaseQuickAdapter) parent.getAdapter).getHeaderLayoutCount;
footerCount = ((BaseQuickAdapter) parent.getAdapter).getFooterLayoutCount;
dataCount = parent.getAdapter.getItemCount;
} else{
dataCount = parent.getAdapter.getItemCount;
}
intdataStartPosition = headerCount;
intdataEndPosition = headerCount + dataCount;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager;
if(layoutManager instanceofStaggeredGridLayoutManager) {
orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation;
} elseif(layoutManager instanceofGridLayoutManager) {
orientation = ((GridLayoutManager) layoutManager).getOrientation;
} elseif(layoutManager instanceofLinearLayoutManager) {
orientation = ((LinearLayoutManager) layoutManager).getOrientation;
}
intstart, end;
if(orientation == OrientationHelper.VERTICAL) {
start = parent.getPaddingLeft;
end = parent.getWidth - parent.getPaddingRight;
} else{
start = parent.getPaddingTop;
end = parent.getHeight - parent.getPaddingBottom;
}
intchildCount = parent.getChildCount;
for( inti = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
intposition = parent.getChildAdapterPosition(child);
if(position >= dataStartPosition && position < dataEndPosition - 1//数据项除了最后一项
|| (position == dataEndPosition - 1&& mDrawLastItem) //数据项最后一项
|| (!(position >= dataStartPosition && position < dataEndPosition) && mDrawHeaderFooter) //header&footer且可绘制
) {
if(orientation == OrientationHelper.VERTICAL) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams;
inttop = child.getBottom + params.bottomMargin;
intbottom = top;
mColorDrawable.setBounds(start, top, end, bottom);
mColorDrawable.draw(c);
} else{
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams;
intleft = child.getRight + params.rightMargin;
intright = left;
mColorDrawable.setBounds(left, start, right, end);
mColorDrawable.draw(c);
}
}
}
}
}
2.顶部栏部分
ItemDecoration,难点在于如何设置点击点击事件。感谢作者,提供了一种新的思路 StickyItemDecoration,这里只说如何使用,原理阅读作者源码即可。按照这个思路,我们可以将头部布局单独出来,这样的话,处理点击事件就很简单。
activity布局
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/rv_pictrues"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cf7f8fa"
android:nestedScrollingEnabled="false"/>
android:id="@+id/shc_pictrues"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/cffffff">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
android:id="@+id/tv_picture_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:drawableRight="@mipmap/unfold"
android:drawablePadding="10dp"
android:gravity="center"
android:text="2018年11月"
android:textColor="@color/c969696"
android:textSize="16sp"/>
StickyHeadContainer
publicclassStickyHeadContainerextendsViewGroup{
privateintmOffset;
privateintmLastOffset = Integer.MIN_VALUE;
privateintmLastStickyHeadPosition = Integer.MIN_VALUE;
privateintmLeft;
privateintmRight;
privateintmTop;
privateintmBottom;
privateDataCallback mDataCallback;
publicStickyHeadContainer(Context context){
this(context, null);
}
publicStickyHeadContainer(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
publicStickyHeadContainer(Context context, AttributeSet attrs, intdefStyleAttr){
super(context, attrs, defStyleAttr);
setOnClickListener( newOnClickListener {
@Override
publicvoidonClick(View v){
// TODO:2017/1/9 屏蔽点击事件
}
});
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec, intheightMeasureSpec){
intdesireHeight;
intdesireWidth;
intcount = getChildCount;
if(count != 1) {
thrownewIllegalArgumentException( "只允许容器添加1个子View!");
}
finalView child = getChildAt( 0);
// 测量子元素并考虑外边距
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
// 获取子元素的布局参数
finalMarginLayoutParams 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
protectedvoidonLayout(booleanchanged, intl, intt, intr, intb){
finalView child = getChildAt( 0);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams;
finalintpaddingLeft = getPaddingLeft;
finalintpaddingTop = 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
protectedLayoutParams generateDefaultLayoutParams{
returnsuper.generateDefaultLayoutParams;
}
// 生成布局参数,将布局参数包装成我们的
@Override
protectedLayoutParams generateLayoutParams(LayoutParams p){
returnnewMarginLayoutParams(p);
}
// 生成布局参数,从属性配置中生成我们的布局参数
@Override
publicLayoutParams generateLayoutParams(AttributeSet attrs){
returnnewMarginLayoutParams(getContext, attrs);
}
// 查当前布局参数是否是我们定义的类型这在code声明布局参数时常常用到
@Override
protectedbooleancheckLayoutParams(LayoutParams p){
returnp instanceofMarginLayoutParams;
}
publicvoidscrollChild(intoffset){
if(mLastOffset != offset) {
mOffset = offset;
ViewCompat.offsetTopAndBottom(getChildAt( 0), mOffset - mLastOffset);
}
mLastOffset = mOffset;
}
protectedintgetChildHeight{
returngetChildAt( 0).getHeight;
}
protectedvoidonDataChange(intstickyHeadPosition){
if(mDataCallback != null&& mLastStickyHeadPosition != stickyHeadPosition) {
mDataCallback.onDataChange(stickyHeadPosition);
}
mLastStickyHeadPosition = stickyHeadPosition;
}
publicvoidreset{
mLastStickyHeadPosition = Integer.MIN_VALUE;
}
publicinterfaceDataCallback{
voidonDataChange(intpos);
}
publicvoidsetDataCallback(DataCallback dataCallback){
mDataCallback = dataCallback;
}
}
在activity中完整使用
StickyItemDecoration stickyItemDecoration = newStickyItemDecoration(shcPictrues, PictureModel.PICTURE_TITLE);
stickyItemDecoration.setOnStickyChangeListener( newOnStickyChangeListener {
@Override
publicvoidonScrollable(intoffset){
//可见时
shcPictrues.scrollChild(offset);
shcPictrues.setVisibility(View.VISIBLE);
}
@Override
publicvoidonInVisible{
//不可见时
shcPictrues.reset;
shcPictrues.setVisibility(View.INVISIBLE);
}
});
shcPictrues.setDataCallback( newStickyHeadContainer.DataCallback {
@Override
publicvoidonDataChange(intpos){
//数据更新
List listModels = pictureAdapter.getData;
if(listModels.size > pos) {
tvPictureTime.setText(listModels.get(pos).getDate);
}
}
});
//添加至rv
rvPictrues.addItemDecoration(stickyItemDecoration);
pictureAdapter = newPictureAdapter( null);
rvPictrues.setLayoutManager( newGridLayoutManager(context, 2));
rvPictrues.addItemDecoration(stickyItemDecoration);
SpaceDecoration spaceDecoration = newSpaceDecoration(DensityUtils.dp2px(context, 10));
spaceDecoration.setPaddingStart( false);
rvPictrues.addItemDecoration(spaceDecoration);
rvPictrues.setAdapter(pictureAdapter);
pictureAdapter.bindToRecyclerView(rvPictrues);
StickyItemDecoration
publicclassStickyItemDecorationextendsRecyclerView.ItemDecoration{
privateintmStickyHeadType;
privateintmFirstVisiblePosition;
//private int mFirstCompletelyVisiblePosition;
privateintmStickyHeadPosition;
privateint[] mInto;
privateRecyclerView.Adapter mAdapter;
privateStickyHeadContainer mStickyHeadContainer;
privatebooleanmEnableStickyHead = true;
privateOnStickyChangeListener mOnStickyChangeListener;
publicvoidsetOnStickyChangeListener(OnStickyChangeListener onStickyChangeListener){
this.mOnStickyChangeListener = onStickyChangeListener;
}
publicStickyItemDecoration(StickyHeadContainer stickyHeadContainer, intstickyHeadType){
mStickyHeadContainer = stickyHeadContainer;
mStickyHeadType = stickyHeadType;
}
// 当我们调用mRecyclerView.addItemDecoration方法添加decoration的时候,RecyclerView在绘制的时候,去会绘制decorator,即调用该类的onDraw和onDrawOver方法,
// 1.onDraw方法先于drawChildren
// 2.onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。
// 3.getItemOffsets 可以通过outRect.set为每个Item设置一定的偏移量,主要用于绘制Decorator。
@Override
publicvoidonDraw(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);
intoffset;
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;
}
}
}
publicvoidenableStickyHead(booleanenableStickyHead){
mEnableStickyHead = enableStickyHead;
if(!mEnableStickyHead) {
mStickyHeadContainer.setVisibility(View.INVISIBLE);
}
}
privatevoidcalculateStickyHeadPosition(RecyclerView parent){
finalRecyclerView.LayoutManager layoutManager = parent.getLayoutManager;
// mFirstCompletelyVisiblePosition = findFirstCompletelyVisiblePosition(layoutManager);
// 获取第一个可见的item位置
mFirstVisiblePosition = findFirstVisiblePosition(layoutManager);
// 获取标签的位置,
intstickyHeadPosition = findStickyHeadPosition(mFirstVisiblePosition);
if(stickyHeadPosition >= 0&& mStickyHeadPosition != stickyHeadPosition) {
// 标签位置有效并且和缓存的位置不同
mStickyHeadPosition = stickyHeadPosition;
}
}
/**
* 从传入位置递减找出标签的位置
* @paramformPosition
* @return
*/
privateintfindStickyHeadPosition(intformPosition){
for( intposition = formPosition; position >= 0; position--) {
// 位置递减,只要查到位置是标签,立即返回此位置
finalinttype = mAdapter.getItemViewType(position);
if(isStickyHeadType(type)) {
returnposition;
}
}
return- 1;
}
/**
* 通过适配器告知类型是否为标签
* @paramtype
* @return
*/
privatebooleanisStickyHeadType(inttype){
returnmStickyHeadType == type;
}
/**
* 找出第一个可见的Item的位置
* @paramlayoutManager
* @return
*/
privateintfindFirstVisiblePosition(RecyclerView.LayoutManager layoutManager){
intfirstVisiblePosition = 0;
if(layoutManager instanceofGridLayoutManager) {
firstVisiblePosition = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition;
} elseif(layoutManager instanceofLinearLayoutManager) {
firstVisiblePosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition;
} elseif(layoutManager instanceofStaggeredGridLayoutManager) {
mInto = newint[((StaggeredGridLayoutManager) layoutManager).getSpanCount];
((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(mInto);
firstVisiblePosition = Integer.MAX_VALUE;
for( intpos : mInto) {
firstVisiblePosition = Math.min(pos, firstVisiblePosition);
}
}
returnfirstVisiblePosition;
}
/**
* 找出第一个完全可见的Item的位置
* @paramlayoutManager
* @return
*/
privateintfindFirstCompletelyVisiblePosition(RecyclerView.LayoutManager layoutManager){
intfirstVisiblePosition = 0;
if(layoutManager instanceofGridLayoutManager) {
firstVisiblePosition = ((GridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition;
} elseif(layoutManager instanceofLinearLayoutManager) {
firstVisiblePosition = ((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition;
} elseif(layoutManager instanceofStaggeredGridLayoutManager) {
mInto = newint[((StaggeredGridLayoutManager) layoutManager).getSpanCount];
((StaggeredGridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPositions(mInto);
firstVisiblePosition = Integer.MAX_VALUE;
for( intpos : mInto) {
firstVisiblePosition = Math.min(pos, firstVisiblePosition);
}
}
returnfirstVisiblePosition;
}
/**
* 检查缓存
*
* @paramparent
*/
privatevoidcheckCache(finalRecyclerView parent){
finalRecyclerView.Adapter adapter = parent.getAdapter;
if(mAdapter != adapter) {
mAdapter = adapter;
// 适配器为null或者不同,清空缓存
mStickyHeadPosition = - 1;
mAdapter.registerAdapterDataObserver( newRecyclerView.AdapterDataObserver {
@Override
publicvoidonChanged{
reset;
}
@Override
publicvoidonItemRangeChanged(intpositionStart, intitemCount){
reset;
}
@Override
publicvoidonItemRangeChanged(intpositionStart, intitemCount, Object payload){
reset;
}
@Override
publicvoidonItemRangeInserted(intpositionStart, intitemCount){
reset;
}
@Override
publicvoidonItemRangeRemoved(intpositionStart, intitemCount){
reset;
}
@Override
publicvoidonItemRangeMoved(intfromPosition, inttoPosition, intitemCount){
reset;
}
});
}
}
privatevoidreset{
mStickyHeadContainer.reset;
}
/**
* 查找到view对应的位置从而判断出是否标签类型
* @paramparent
* @paramview
* @return
*/
privatebooleanisStickyHead(RecyclerView parent, View view){
finalintposition = parent.getChildAdapterPosition(view);
if(position == RecyclerView.NO_POSITION) {
returnfalse;
}
finalinttype = mAdapter.getItemViewType(position);
returnisStickyHeadType(type);
}
}
pictureAdapter
完整源码
https://github.com/18702953620/PicRvDemo返回搜狐,查看更多
责任编辑: