android qq分组效果,【Android视图效果】分组列表实现吸顶效果

原标题:【Android视图效果】分组列表实现吸顶效果

效果图

2bc7be8a042db759f5cdd85adf99df8d.gif

效果图 分析

先来分析一下,可以看到这是一个按月份分组的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返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值