1. 程式人生 > >android GridLayoutManager StaggeredGridLayoutManager設定間距、佔滿一行及使用StaggeredGridLayoutManager時遇到的一些問題

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);