LoginSignup
2
0

More than 3 years have passed since last update.

Master/Detail Flow + RecyclerView + GridLayoutManagerでタブレット対応でレイアウトが崩れにくいグリッド表示

Last updated at Posted at 2020-12-19

はじめに

既存のアプリをタブレット対応して下さいと言われた時にListを単純に横に伸ばしただけだと空白が広くなりすぎて見づらいとか、リスト上に文字が多く表示されてゴチャゴチャしたりとかあるかと思います。
スマホ用とタブレット用で別のlayoutを作成すれば良いのですが、どうにかして同じレイアウトで良い感じにならないかと考えた結果...

Grid表示とMaster/Detail Flowレイアウトを組み合わせたら結構いい感じになるんじゃないかと思ったので簡単なものを作ってみました:slight_smile:

つくったもの

Gridレイアウトの横に並ぶセルの数を画面の横幅に合わせて変えただけ。

スマホ表示
sp_ver (1).jpg

タブレット
sp_ver (2).jpg

つくりかた

簡単に作る為に、Master/Detail Flowテンプレートでプロジェクトを作成
スクリーンショット 2020-12-18 10.48.07.png

グリッド表示するのにCardViewを使用すると見た目が楽なので追加

build.gradle
dependencies {
    //省略
    implementation 'androidx.cardview:cardview:1.0.0'
}

リスト表示をCardViewに変更

item_list_content.xml
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="6dp"
    app:cardElevation="6dp"
    app:cardUseCompatPadding="true"
    app:contentPadding="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/id_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:textAppearance="?attr/textAppearanceListItem"
            tools:text="no" />

        <TextView
            android:id="@+id/content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/text_margin"
            android:textAppearance="?attr/textAppearanceListItem"
            tools:text="explain" />
    </LinearLayout>
</androidx.cardview.widget.CardView>

/res/layout-w900dpにあるやつをlayout-w600dpにコピペしてRecyclerViewとFrameLayoutの横幅の表示をlayout_weightで1:3になるように変更
(layout-w900dpの方は1:2にになるように変更)

layout-w600dp/item_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:baselineAligned="false"
    android:divider="?android:attr/dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle"
    tools:context=".ItemListActivity"
    android:weightSum="4">

    <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/item_list"
        android:name="com.example.masterdetailsample.ItemListFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        app:layoutManager="LinearLayoutManager"
        tools:context="com.example.masterdetailsample.ItemListActivity"
        tools:listitem="@layout/item_list_content" />

    <FrameLayout
        android:id="@+id/item_detail_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

</LinearLayout>

ItemListActivity.ktのsetupRecyclerViewのところにGridLayoutManagerでGrid表示するように設定し、spanCountを画面サイズによって変更するように追記

ItemListActivity.kt

private fun setupRecyclerView(recyclerView: RecyclerView) {
        recyclerView.adapter = SimpleItemRecyclerViewAdapter(this, DummyContent.ITEMS, twoPane)
        val spanCount = getSpanCount()
        recyclerView.layoutManager =
            GridLayoutManager(this, spanCount, RecyclerView.VERTICAL, false)
    }

    private fun getSpanCount(): Int {
        val dMetrics = DisplayMetrics()
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
            val display = this.display;
            display?.getRealMetrics(dMetrics)
        } else {
            @Suppress("DEPRECATION")
            window.windowManager.defaultDisplay.getRealMetrics(dMetrics)
        }
        var realWidth = dMetrics.widthPixels / dMetrics.density
        return if ( realWidth >= 600 && realWidth < 900) 1 else 2
    }

完成:grin:

gitHub:https://github.com/iKimishima/MasterDetailGridList.git

まとめ

これでどんな画面サイズが来ても大丈夫!

と思ったけど今回はTempleteを使用したのでMaster/Detail Flowの設定が必要なかったが、既存アプリにMaster/Detail Flowを導入するときは大変だろうなと思った冬の夜。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0