Skip to content

Commit

Permalink
1.0.18 fix setSpanSizeLookup会发生错乱 #13
Browse files Browse the repository at this point in the history
  • Loading branch information
youlookwhat committed Mar 28, 2020
1 parent 8fe3ad7 commit a6bcb69
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

Expand All @@ -44,7 +45,6 @@ public class GridSpaceItemDecoration extends RecyclerView.ItemDecoration {
* 距屏幕周围是否也有间距
*/
private boolean mIncludeEdge;

/**
* 头部 不显示间距的item个数
*/
Expand All @@ -53,37 +53,82 @@ public class GridSpaceItemDecoration extends RecyclerView.ItemDecoration {
* 尾部 不显示间距的item个数 默认不处理最后一个item的间距
*/
private int mEndFromSize = 1;
/**
* 瀑布流 头部第一个整行的position
*/
private int fullPosition = -1;

public GridSpaceItemDecoration(int spanCount, int spacing) {
this(spanCount, spacing, true);
public GridSpaceItemDecoration(int spacing) {
this(spacing, true);
}

/**
* @param spanCount item 每行个数
* @param spacing item 间距
* @param includeEdge item 距屏幕周围是否也有间距
*/
public GridSpaceItemDecoration(int spacing, boolean includeEdge) {
this.mSpacing = spacing;
this.mIncludeEdge = includeEdge;
}

/**
* 已不需要手动设置spanCount
*/
@Deprecated
public GridSpaceItemDecoration(int spanCount, int spacing) {
this(spanCount, spacing, true);
}

/**
* 已不需要手动设置spanCount
*/
@Deprecated
public GridSpaceItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.mSpanCount = spanCount;
this.mSpacing = spacing;
this.mIncludeEdge = includeEdge;
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int lastPosition = state.getItemCount() - 1;
int position = parent.getChildAdapterPosition(view);
if (mStartFromSize <= position && position <= lastPosition - mEndFromSize) {

// 减掉不设置间距的position
position = position - mStartFromSize;
int column = position % mSpanCount;

// 瀑布流获取列方式不一样
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
column = ((StaggeredGridLayoutManager.LayoutParams) layoutParams).getSpanIndex();
// 行
int spanGroupIndex = -1;
// 列
int column = 0;
// 瀑布流是否占满一行
boolean fullSpan = false;

RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
int spanCount = gridLayoutManager.getSpanCount();
// 当前position的spanSize
int spanSize = spanSizeLookup.getSpanSize(position);
// 一行几个
mSpanCount = spanCount / spanSize;
// =0 表示是最左边 0 2 4
int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
// 列
column = spanIndex / spanSize;
// 行 减去mStartFromSize,得到从0开始的行
spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount) - mStartFromSize;

} else if (layoutManager instanceof StaggeredGridLayoutManager) {
// 瀑布流获取列方式不一样
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
// 列
column = params.getSpanIndex();
// 是否是全一行
fullSpan = params.isFullSpan();
mSpanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
// 减掉不设置间距的position,得到从0开始的position
position = position - mStartFromSize;

if (mIncludeEdge) {
/*
Expand All @@ -95,12 +140,33 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
* 10 3+7 6+4 10
* ---------10--------
*/
outRect.left = mSpacing - column * mSpacing / mSpanCount;
outRect.right = (column + 1) * mSpacing / mSpanCount;
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
outRect.left = mSpacing - column * mSpacing / mSpanCount;
outRect.right = (column + 1) * mSpacing / mSpanCount;
}

if (position < mSpanCount) {
outRect.top = mSpacing;
if (spanGroupIndex > -1) {
// grid 显示规则
if (spanGroupIndex < 1 && position < mSpanCount) {
// 第一行才有上间距
outRect.top = mSpacing;
}
} else {
if (fullPosition == -1 && position < mSpanCount && fullSpan) {
// 找到头部第一个整行的position,后面的上间距都不显示
fullPosition = position;
}
// Stagger显示规则 头部没有整行或者头部体验整行但是在之前的position显示上间距
boolean isFirstLineStagger = (fullPosition == -1 || position < fullPosition) && (position < mSpanCount);
if (isFirstLineStagger) {
// 第一行才有上间距
outRect.top = mSpacing;
}
}

outRect.bottom = mSpacing;

} else {
Expand All @@ -113,10 +179,31 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle
* 0 3+7 6+4 0
* --------0--------
*/
outRect.left = column * mSpacing / mSpanCount;
outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount;
if (position >= mSpanCount) {
outRect.top = mSpacing;
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
outRect.left = column * mSpacing / mSpanCount;
outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount;
}

if (spanGroupIndex > -1) {
if (spanGroupIndex >= 1) {
// 超过第0行都显示上间距
outRect.top = mSpacing;
}
} else {
if (fullPosition == -1 && position < mSpanCount && fullSpan) {
// 找到头部第一个整行的position
fullPosition = position;
}
// Stagger上间距显示规则
boolean isStaggerShowTop = position >= mSpanCount || (fullSpan && position != 0) || (fullPosition != -1 && position != 0);

if (isStaggerShowTop) {
// 超过第0行都显示上间距
outRect.top = mSpacing;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected void bindView(BaseByViewHolder<DataItemBean> holder, DataItemBean bean
layoutManager.setOrientation(RecyclerView.VERTICAL);
binding.recyclerView.setLayoutManager(layoutManager);
binding.recyclerView.setRefreshEnabled(true);
binding.recyclerView.addItemDecoration(new GridSpaceItemDecoration(2, 2, false).setStartFrom(1));
binding.recyclerView.addItemDecoration(new GridSpaceItemDecoration(2, false).setStartFrom(1));
// binding.recyclerView.setAdapter(mAdapter);
binding.recyclerView.setOnLoadMoreListener(new ByRecyclerView.OnLoadMoreListener() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
package me.jingbin.byrecyclerview.adapter;

import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import java.util.List;

import me.jingbin.byrecyclerview.R;
import me.jingbin.byrecyclerview.bean.DataItemBean;
import me.jingbin.byrecyclerview.binding.BaseBindingAdapter;
import me.jingbin.byrecyclerview.binding.BaseBindingHolder;
import me.jingbin.byrecyclerview.databinding.ItemGridBinding;
import me.jingbin.byrecyclerview.utils.DensityUtil;
import me.jingbin.byrecyclerview.utils.ViewUtil;
import me.jingbin.library.ByRecyclerView;
import me.jingbin.library.adapter.BaseByViewHolder;
import me.jingbin.library.adapter.BaseRecyclerAdapter;
import me.jingbin.library.stickyview.StickyHeaderHandler;

/**
* @author jingbin
*/
public class GridAdapter extends BaseBindingAdapter<DataItemBean, ItemGridBinding> {
public class GridAdapter extends BaseRecyclerAdapter<DataItemBean> {

private boolean isStaggered = false;

Expand All @@ -26,14 +36,87 @@ public GridAdapter(List<DataItemBean> data) {
}

@Override
protected void bindView(BaseBindingHolder holder, DataItemBean bean, ItemGridBinding binding, int position) {
protected void bindView(BaseByViewHolder<DataItemBean> holder, DataItemBean bean, int position) {
if (isStaggered) {
View clGrid = holder.getView(R.id.cl_grid);
TextView tvTitle = holder.getView(R.id.tv_title);
if (position % 2 == 0) {
ViewUtil.setHeight(binding.clGrid, DensityUtil.dip2px(binding.clGrid.getContext(), 100));
ViewUtil.setHeight(clGrid, DensityUtil.dip2px(clGrid.getContext(), 100));
} else {
ViewUtil.setHeight(binding.clGrid, DensityUtil.dip2px(binding.clGrid.getContext(), 200));
ViewUtil.setHeight(clGrid, DensityUtil.dip2px(clGrid.getContext(), 200));
}
binding.tvTitle.setText("" + position);
tvTitle.setText("" + position);
}
}

/**
* 设置Grid多类型
*/
@Override
public void onAttachedToRecyclerView(@NonNull final RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
final ByRecyclerView byRecyclerView = (ByRecyclerView) recyclerView;

gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (byRecyclerView.isLoadMoreView(position)
|| byRecyclerView.isFootView(position)
|| byRecyclerView.isStateView(position)
|| byRecyclerView.isRefreshHeader(position)
|| byRecyclerView.isHeaderView(position)) {
return gridManager.getSpanCount();
}
int adapterPosition = position - byRecyclerView.getCustomTopItemViewCount();
switch (adapterPosition) {
case 0:
// title栏显示一列
return gridManager.getSpanCount();
case 4:
return 3;
case 5:
return 3;
case 6:
return gridManager.getSpanCount();
default:
//默认显示2列
return 2;
}
}
});
}
}

/**
* 设置StaggeredGrid多类型
*/
@Override
public int getItemViewType(int position) {
if (position == 0 || position == 2 || position == 8) {
return StickyHeaderHandler.TYPE_STICKY_VIEW;
}
return 2;
}

@Override
public void onViewAttachedToWindow(@NonNull BaseByViewHolder<DataItemBean> holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
ByRecyclerView byRecyclerView = holder.getByRecyclerView();
if (lp != null
&& byRecyclerView != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& (byRecyclerView.isHeaderView(holder.getLayoutPosition())
|| byRecyclerView.isFootView(holder.getLayoutPosition())
|| byRecyclerView.isRefreshHeader(holder.getLayoutPosition())
|| byRecyclerView.isLoadMoreView(holder.getLayoutPosition())
|| byRecyclerView.isStateView(holder.getLayoutPosition())
|| holder.getItemViewType() == StickyHeaderHandler.TYPE_STICKY_VIEW)) {
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,25 @@ private void initAdapter() {

if ("grid".equals(mType)) {
// 宫格
GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 3);
GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 6);
recyclerView.setLayoutManager(gridLayoutManager);
// 四周也有间距
GridSpaceItemDecoration itemDecoration = new GridSpaceItemDecoration(3,
DensityUtil.dip2px(activity, 10));
GridSpaceItemDecoration itemDecoration = new GridSpaceItemDecoration(
DensityUtil.dip2px(activity, 10), true);
// 去掉首尾的分割线 (刷新头部和加载更多尾部)
recyclerView.addItemDecoration(itemDecoration.setNoShowSpace(1, 1));
recyclerView.addItemDecoration(itemDecoration.setNoShowSpace(2, 1));

} else {
// 瀑布流
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
// 四周没有间距
GridSpaceItemDecoration itemDecoration = new GridSpaceItemDecoration(3,
DensityUtil.dip2px(activity, 10), false);
recyclerView.addItemDecoration(itemDecoration.setNoShowSpace(1, 1));
GridSpaceItemDecoration itemDecoration = new GridSpaceItemDecoration(
DensityUtil.dip2px(activity, 10), true);
recyclerView.addItemDecoration(itemDecoration.setNoShowSpace(2, 1));
mAdapter.setStaggered(true);
}
recyclerView.addHeaderView(R.layout.layout_header_view);
recyclerView.setAdapter(mAdapter);
recyclerView.setOnLoadMoreListener(new ByRecyclerView.OnLoadMoreListener() {
@Override
Expand Down

0 comments on commit a6bcb69

Please sign in to comment.