android GridLayoutManager StaggeredGridLayoutManager设置间距、占满一行及使用StaggeredGridLayoutManager时遇到的一些问题

LineaLayoutManager 设置间距比较简单就不再说了

GridLayoutManager 网格布局设置间距:

final int divider = AndroidUtil.dpToPx(10, mContext);
gridItemDecoration = new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
                final GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) view.getLayoutParams();
                final int spanCount = layoutManager.getSpanCount();
                int layoutPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
                if (lp.getSpanSize() != spanCount) {
                    //左边间距
                    if (layoutPosition % 2 == 1) {
                        outRect.left = divider / 2;
                        outRect.right = divider;
                    } else {
                        outRect.left = divider;
                        outRect.right = divider / 2;
                    }
                }
                outRect.top = divider;
            }
        };
recyclerview.addItemDecoration(gridItemDecoration);

以上的代码对应下图
注意:间距是计算在itemview之中的
在这里插入图片描述
像常见的九宫格的话,我最开始想到的实现方式是这样的
在这里插入图片描述
这种方式是有问题的,原因还是注意:间距是计算在itemview之中的,因为每个条目的大小是相等的,左右两个条目减去边距就会缩小图片的尺寸了,那就必须要一行三个,横向间距+图片大小都相等 一共4个间距,那么每个条目的横向间距总值应为4/3*间距即(1,1/3) (2/3,2/3) (1/3,1)

//每个条目的偏移距离
int eachWidth = (spanCount + 1) * divider / spanCount;
outRect.left = (spanCount-layoutPosition%spanCount)/spanCount*divider;
outRect.right = eachWidth-outRect.left;

注意:以上计算的偏移距离为左右有间距的,若左右无间距,只有中间有间距

int eachWidth = (spanCount - 1) * divider / spanCount;

计算左右间距就是数学问题了

GridLayoutManager 中条目占满一行

mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                //判断若为banner类型,占满一行
                if (bbsHomeAdapter.getItemViewType(position) == 0) {
                    return 2;
                }else{
                	return 1;
            	}
          }
});

StaggeredGridLayoutManager布局设置间距:

StaggeredGridLayoutManager通过layoutposition设置会错乱,改成StaggeredGridLayoutManager.layoutParams.getSpanIndex()就好了

RecyclerView.ItemDecoration gridItemDecoration = new RecyclerView.ItemDecoration() {
                @Override
                public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                    //不为banner类型
                    if (bbsHomeAdapter.getItemViewType(parent.getChildAdapterPosition(view)) != 0) {
                        StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
                        int spanIndex = layoutParams.getSpanIndex();
                        outRect.top = divider;
                        if (spanIndex == 0) {
                            // left
                            outRect.left = divider;
                            outRect.right = divider / 2;
                        } else{
                            outRect.right = divider;
                            outRect.left = divider / 2;
                        }
                    }
                }
            };
recyclerview.addItemDecoration(gridItemDecoration);

StaggeredGridLayoutManager占满一行

@Override
    public void onViewAttachedToWindow(BaseHolder holder) {
        super.onViewAttachedToWindow(holder);
        int index = holder.getLayoutPosition();
        //判断若为banner类型,占满一行
        if (getItemViewType(index) == 0) {
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) {
                StaggeredGridLayoutManager.LayoutParams p =
                        (StaggeredGridLayoutManager.LayoutParams) lp;
                p.setFullSpan(true);
            }
        }
    }

StaggeredGridLayoutManager使用时遇到的问题:

1.条目闪动

staggeredGridLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);

2.下拉一段距离第一行条目距顶部有间距(此解决方法未必有效)

rvContent.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    // 滑动停止,刷新布局与分割线
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        if (recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {
                            ((StaggeredGridLayoutManager) recyclerView.getLayoutManager()).invalidateSpanAssignments();
                            recyclerView.invalidateItemDecorations();
                        }
                    }
                }
            });

3.滑动卡顿
卡顿的原因是由于要加载图片完成后,根据bitmap的宽高比设置给imageview对应的高度
没有太好的办法,让后台返回图片尺寸,直接设置给imageview,这种方法效果是最好的,可还要考虑后台不一定返回的情况,就需要自己按原样请求了,只是请求成功计算出imageview高度保存一下,以后的滑动就不会每次请求了,只是第一次卡顿了
4.瀑布流中imageview设置了scaletype为centerCrop,刷新后,同一张图可能会被多次裁剪放大中心部分
百度了半天没解决,google检索结果第一个就搜到了
参考:https://github.com/bumptech/glide/issues/1497

加上.dontTransform() 取消图片变化效果
Glide.with(mContext).load(url).dontTransform().into(ivImage);
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用 `StaggeredGridLayoutManager` ,可以通过设置 `ItemDecoration` 来设置间距。具体步骤如下: 1. 首先创建一个继承自 `RecyclerView.ItemDecoration` 的类,重写 `getItemOffsets` 方法,在该方法中设置每个 item 的上下左右间距。例如: ``` public class MyItemDecoration extends RecyclerView.ItemDecoration { private int space; public MyItemDecoration(int space) { this.space = space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = space; outRect.right = space; outRect.bottom = space; // Add top margin only for the first item to avoid double space between items if (parent.getChildAdapterPosition(view) == 0) { outRect.top = space; } else { outRect.top = 0; } } } ``` 2. 在 `RecyclerView` 的代码中,创建 `StaggeredGridLayoutManager` 对象,同创建 `MyItemDecoration` 对象,并将其设置给 `RecyclerView`。例如: ``` RecyclerView recyclerView = findViewById(R.id.recyclerView); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); MyItemDecoration itemDecoration = new MyItemDecoration(16); recyclerView.addItemDecoration(itemDecoration); ``` 其中,`StaggeredGridLayoutManager` 的第一个参数是列数,第二个参数是排列方向。`MyItemDecoration` 的构造函数中的参数是间距大小,单位为像素。 这样就可以使用 `ItemDecoration` 设置 `StaggeredGridLayoutManager` 的间距了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值