android GridLayoutManager StaggeredGridLayoutManager設定間距、佔滿一行及使用StaggeredGridLayoutManager時遇到的一些問題
阿新 • • 發佈:2019-01-26
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);