[解決済み] RecyclerView GridLayoutManager: スパン数を自動検出する方法は?
質問
新しいGridLayoutManagerを使用する。 https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html
これは明示的なスパン数を取るので、問題は、1 行に収まる "スパン" の数をどのように知るか、ということになります。これは結局のところ、グリッドです。測定された幅に基づいて、RecyclerViewが適合できるのと同じ数のスパンがあるはずです。
古い
GridView
を使用すると、ちょうど "columnWidth" プロパティを設定し、それは自動的にフィットするいくつかの列を検出するでしょう。これは基本的に、私がRecyclerViewのために再現したいものです。
-
の上にOnLayoutChangeListenerを追加します。
RecyclerView
- このコールバックで、単一の 'グリッド アイテム' を生成し、それを測定します。
- spanCount = recyclerViewWidth / singleItemWidth;
これはかなり一般的な動作のようですが、私が見ていないもっと簡単な方法があるのでしょうか?
どのように解決するのですか?
個人的には、RecyclerViewのサブクラスを作成するのは好きではありません。そこで、RecyclerViewとGridLayoutManagerのためのいくつかのアンドロイドのソースコードを掘った後、私は仕事をするGridLayoutManagerを拡張した独自のクラスを書きました。
public class GridAutofitLayoutManager extends GridLayoutManager
{
private int columnWidth;
private boolean isColumnWidthChanged = true;
private int lastWidth;
private int lastHeight;
public GridAutofitLayoutManager(@NonNull final Context context, final int columnWidth) {
/* Initially set spanCount to 1, will be changed automatically later. */
super(context, 1);
setColumnWidth(checkedColumnWidth(context, columnWidth));
}
public GridAutofitLayoutManager(
@NonNull final Context context,
final int columnWidth,
final int orientation,
final boolean reverseLayout) {
/* Initially set spanCount to 1, will be changed automatically later. */
super(context, 1, orientation, reverseLayout);
setColumnWidth(checkedColumnWidth(context, columnWidth));
}
private int checkedColumnWidth(@NonNull final Context context, final int columnWidth) {
if (columnWidth <= 0) {
/* Set default columnWidth value (48dp here). It is better to move this constant
to static constant on top, but we need context to convert it to dp, so can't really
do so. */
columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
context.getResources().getDisplayMetrics());
}
return columnWidth;
}
public void setColumnWidth(final int newColumnWidth) {
if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
columnWidth = newColumnWidth;
isColumnWidthChanged = true;
}
}
@Override
public void onLayoutChildren(@NonNull final RecyclerView.Recycler recycler, @NonNull final RecyclerView.State state) {
final int width = getWidth();
final int height = getHeight();
if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
final int totalSpace;
if (getOrientation() == VERTICAL) {
totalSpace = width - getPaddingRight() - getPaddingLeft();
} else {
totalSpace = height - getPaddingTop() - getPaddingBottom();
}
final int spanCount = Math.max(1, totalSpace / columnWidth);
setSpanCount(spanCount);
isColumnWidthChanged = false;
}
lastWidth = width;
lastHeight = height;
super.onLayoutChildren(recycler, state);
}
}
なぜonLayoutChildrenでスパン数を設定することにしたのか、このクラスを書いたのは少し前なので、実は覚えていないのです。しかし、重要なのは、ビューが計測された後、高さと幅を取得するために、そうする必要があるということです。
EDIT 1: スパン数の設定ミスによるコードの誤りを修正しました。ありがとうございました。 Elyees Abouda の報告および提案に感謝します。 解決策 .
EDIT 2: いくつかの小さなリファクタリングと、手動方向変更処理に関するエッジケースを修正しました。ありがとうございました。 を追加しました。 の報告および提案に感謝します。 解決策 .
関連
-
[解決済み】Android Recyclerview GridLayoutManagerの列間隔について
-
[解決済み】RecyclerViewとGridLayoutManagerを使ったAndroidの簡単なグリッド例(昔のGridViewのようなもの)。
-
[解決済み] RecyclerView.Stateを使って、RecyclerViewのスクロール位置を保存するには?
-
[解決済み] ViewPagerのアイテムを強制的に再インスタンス化する方法 [重複].
-
[解決済み] Android Studio - あいまいなメソッド呼び出し getClass()
-
[解決済み] 文字サイズとアンドロイドの画面サイズの違い
-
[解決済み] 複数のフィルタを持つBroadcastReceiverか、複数のBroadcastReceiverか?
-
[解決済み] キャンバスに複数行のテキストを描画する
-
[解決済み] 実行に失敗しました app:processDebugResources Android Studio
-
[解決済み] ブルートゥースアプリケーションのテストにアンドロイドエミュレータを使用するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 深くネストされたスタックから離れるとき、Fragmentのバックスタックをクリーンアップする方法はこれで良いのでしょうか?
-
[解決済み] 「KotlinとAndroidで「パラメータTを推測するのに十分な情報がありません。
-
[解決済み] アプリ内課金テスト:android.test.purchased already owned
-
[解決済み] DialogFragmentを正しく終了させるには?
-
[解決済み] Androidのadb logcatでTAG名で特定のメッセージを除外する方法は?
-
[解決済み] Androidアプリケーションのヒープサイズを大きくするには?
-
[解決済み] グリッドビューの高さが削減される
-
[解決済み] edittextのテキストがメールアドレスかどうかを確認するには?
-
[解決済み] proguard hell - 参照されているクラスが見つかりません。
-
[解決済み] <string> XMLで改行やタブを作るには(eclipse/android)?