StaggeredGridLayoutManager
では、セル幅をカスタマイズしたり、垂直方向の複数列(フルスパンを除く)をスパンしたりすることはできません。
上記のようにセルを整理するのに好ましいLayoutManager
は何ですか?
P.S。StaggeredGridLayoutManager
で高さではなくセル幅をカスタマイズする方法を知りたいだけです。この sample で実装されているように、高さをカスタマイズできることを知っています。
_public class VerticalStaggeredGridFragment extends RecyclerFragment {
public static VerticalStaggeredGridFragment newInstance() {
VerticalStaggeredGridFragment fragment = new VerticalStaggeredGridFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
protected RecyclerView.LayoutManager getLayoutManager() {
return new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
}
@Override
protected RecyclerView.ItemDecoration getItemDecoration() {
return new InsetDecoration(getActivity());
}
@Override
protected int getDefaultItemCount() {
return 100;
}
@Override
protected SimpleAdapter getAdapter() {
return new SimpleStaggeredAdapter();
}
}
_
アダプター
_public class SimpleStaggeredAdapter extends SimpleAdapter {
@Override
public void onBindViewHolder(VerticalItemHolder itemHolder, int position) {
super.onBindViewHolder(itemHolder, position);
final View itemView = itemHolder.itemView;
if (position % 4 == 0) {
int height = itemView.getContext().getResources()
.getDimensionPixelSize(R.dimen.card_staggered_height);
itemView.setMinimumHeight(height);
} else {
itemView.setMinimumHeight(0);
}
}
}
_
itemView.setMinimumWidth(customWidth)
はセル幅に影響しません。
簡単にするために、グリッドレイアウトを
StaggeredGridLayoutManager
または他のレイアウトマネージャーのセル1と比較してセル0の幅を増やす方法は?
StaggeredGridLayoutManager.LayoutParams
を使用してセルの幅と高さを変更できます。設計するものは単純なパターンに従います。すべてのセルにインデックスを割り当てると(デフォルトでStaggeredGridLayoutManager
配置される順序で)これを持っています:
index % 4 == 3 ---> full span cell
index % 8 == 0, 5 ---> half span cell
index % 8 == 1, 2, 4, 6 ---> quarter span cell
最初にアダプターでいくつかの定数を宣言して、スパンタイプを定義します。
private static final int TYPE_FULL = 0;
private static final int TYPE_HALF = 1;
private static final int TYPE_QUARTER = 2;
次に、アダプターのgetItemViewType
メソッドを次のようにオーバーライドします。
@Override
public int getItemViewType(int position) {
final int modeEight = position % 8;
switch (modeEight) {
case 0:
case 5:
return TYPE_HALF;
case 1:
case 2:
case 4:
case 6:
return TYPE_QUARTER;
}
return TYPE_FULL;
}
必要なことは、viewType
のholder
を考慮してlayoutparamsを変更することだけです。
@Override
public MyHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final View itemView =
LayoutInflater.from(mContext).inflate(R.layout.items, parent, false);
itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
final int type = viewType;
final ViewGroup.LayoutParams lp = itemView.getLayoutParams();
if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {
StaggeredGridLayoutManager.LayoutParams sglp =
(StaggeredGridLayoutManager.LayoutParams) lp;
switch (type) {
case TYPE_FULL:
sglp.setFullSpan(true);
break;
case TYPE_HALF:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
break;
case TYPE_QUARTER:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
sglp.height = itemView.getHeight() / 2;
break;
}
itemView.setLayoutParams(sglp);
final StaggeredGridLayoutManager lm =
(StaggeredGridLayoutManager) ((RecyclerView) parent).getLayoutManager();
lm.invalidateSpanAssignments();
}
itemView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
MyHolder holder = new MyHolder(itemView);
return holder;
}
私のアダプターは、アイテム数(テストのみ)に対して常に50を返し、アイテムの単純なレイアウトファイルを使用しました。これには、LinearLayout
およびTextView
が含まれ、ホルダーの位置を示します。 spanCount
(StaggeredGridLayoutManager
コンストラクター)の設計のため。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
StaggeredGridLayoutManager lm =
new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(lm);
rv.setAdapter(new MyAdapter(this));
}
[〜#〜] ps [〜#〜]:私のような怠け者にとっては、カスタムLayoutManager
を拡張するよりも簡単な方法かもしれません、しかし、これを達成するより良い方法があると確信しています。
Update:質問の更新された部分がよりシンプルになり、GridLayoutManager
を使用できます:
GridLayoutManager glm = new GridLayoutManager(this, 3);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position % 3 == 2) {
return 3;
}
switch (position % 4) {
case 1:
case 3:
return 1;
case 0:
case 2:
return 2;
default:
//never gonna happen
return -1 ;
}
}
});
rv.setLayoutManager(glm);
このようにして、デフォルトのスパンサイズに3を設定し、スパンの位置を考慮して、各アイテムが1、2、または3スパンを占有します。次のようなものです。
Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1.width
レイアウトを単純化せずにソリューションを探している他のすべての人は、 私の答えはこちら を参照するか、詳細を読むことができます。
Nick Butcher !に感謝します! SpannableGridLayoutManager
と呼ばれる彼のレイアウトマネージャーはこれを行うことができます。
ダウンロードSpannableGridLayoutManager ここから
何らかの理由で、この行を変更する必要がありました。
while (availableSpace > 0 && lastVisiblePosition < lastItemPosition) {
に
while (lastVisiblePosition < lastItemPosition) {
マネージャーを機能させるために。
SpannableGridLayoutMangerをご使用のRecyclerViewに設定します
あなたの場合:
SpannedGridLayoutManager manager = new SpannedGridLayoutManager(
new SpannedGridLayoutManager.GridSpanLookup() {
@Override
public SpannedGridLayoutManager.SpanInfo getSpanInfo(int position) {
switch (position % 8) {
case 0:
case 5:
return new SpannedGridLayoutManager.SpanInfo(2, 2);
case 3:
case 7:
return new SpannedGridLayoutManager.SpanInfo(3, 2);
default:
return new SpannedGridLayoutManager.SpanInfo(1, 1);
}
}
},
3, // number of columns
1f // default size of item
);
これにより、質問の最初の写真にある内容が正確にわかります。