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之中的
android GridLayoutManager StaggeredGridLayoutManager设置间距、占满一行及使用StaggeredGridLayoutManager时遇到的一些问题_第1张图片
像常见的九宫格的话,我最开始想到的实现方式是这样的
android GridLayoutManager StaggeredGridLayoutManager设置间距、占满一行及使用StaggeredGridLayoutManager时遇到的一些问题_第2张图片
这种方式是有问题的,原因还是注意:间距是计算在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);

你可能感兴趣的:(android知识点)