Quantcast
Channel: Google Developers Japan
Viewing all articles
Browse latest Browse all 2207

FlexboxLayout で柔軟なレイアウトを構築

$
0
0
この記事は Takeshi Hagikura, Developer Programs Engineer による Android Developers Blog の記事 "Build flexible layouts with FlexboxLayout" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
昨年の Google I/O では、フラットなビュー階層を維持しつつ複雑なレイアウトを構築でき、Android Studio の Visual Layout Editorでも完全にサポートされている ConstraintLayout を発表しました。

同じタイミングで FlexboxLayout をオープンソース化し、Android で CSS Flexible Layout モジュールと同じ機能が使えるようになりました。この記事では、FlexboxLayoutが特に有用ないくつかのケースを紹介します。

FlexboxLayoutは、高度な LinearLayout と考えることができます。どちらのレイアウトも、子ビューを順番に配置する機能を持っているためです。LinearLayout と FlexboxLayoutのもっとも顕著な違いは、FlexboxLayoutには折り返し機能があることです。

FlexboxLayoutflexWrap="wrap"属性を追加すると、次の図のように現在の行に十分なスペースがない場合に、ビューが新しい行に配置されるようになります。


1 つのレイアウトでさまざまな画面サイズに対応

この特徴を考慮して、ビューを順番に配置しつつ、(端末のファクターの違い、画面の向きの変更、マルチウィンドウ モードでのウィンドウのサイズ変更などにより)利用できるスペースが変化した場合に次の行にビューを移動させるケースについて考えてみましょう。


Nexus 5 縦向き


Nexus 5 横向き

Pixel C でマルチウィンドウ モードが有効になっていて、分割線が左側にある場合


Pixel C でマルチウィンドウ モードが有効になっていて、分割線が中央にある場合


Pixel C でマルチウィンドウ モードが有効になっていて、分割線が右側にある場合

LinearLayoutRelativeLayoutなどの従来のレイアウトでさまざまな画面サイズに対応するには、DP を指定した複数のレイアウト(layout-600dp、layout-720dp、layout-1020dp など)を定義する必要がありました。一方、上のダイアログは FlexboxLayout を使用した一つのレイアウトだけでできています。

この例では、先ほど説明した flexWrap="wrap"を設定するというテクニックを利用しています。

<com .google.android.flexbox.flexboxlayout 
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexwrap="wrap">
これによって、子ビューが親からはみ出るのではなく、新しい行に配置されるようになり、次のようなレイアウトが得られます。




もう 1 つ紹介しておきたいのは、個々の子ビューに layout_flexGrow属性を設定するテクニックです。これによって、スペースが余った場合の最終的なレイアウトの見栄えを改善できます。layout_flexGrow属性は LinearLayoutlayout_weight属性に相当します。つまり、FlexboxLayoutは、設定された layout_flexGrowの値に応じて、余ったスペースを同じ行に配置された子ビューに割り当てます。

下に示すのは、各子ビューの layout_flexGrow属性を 1に設定している例です。そのため、余ったスペースがそれぞれの子ビューに均等に割り当てられています。
<android .support.design.widget.TextInputLayout
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_flexgrow="1">



このケースで使われている layout xmlファイルは、GitHub レポジトリで確認できます。

RecyclerView との統合 

FlexboxLayoutが提供するもう 1 つのメリットは、RecyclerViewと統合できるという点です。最新リリースであるアルファ版の新しい FlexboxLayoutManagerは、RecyclerView.LayoutManagerを拡張しています。そのため、スクロール可能な Flexbox コンテナではるかにメモリ効率がよい Flexbox の機能を使うことができます。

なお、スクロール可能な Flexbox コンテナは、ScrollViewの中に FlexboxLayoutを配置することでも実現できますが、レイアウトに含めるアイテムの数が増えると、スムーズに動かなくなったり OutOfMemoryError が発生する可能性が高くなります。これは、FlexboxLayoutではユーザーがスクロールして画面外に移動したビューの再利用が考慮されていないためです。

(RecyclerView の詳細を知りたい方は、12などの Android UI ツールキット チームの動画をご覧ください)

RecyclerViewの統合が役に立つ実例としてあげられるのは、Google Photos やニュースアプリのようなアプリです。これらはどちらも、さまざまな幅のアイテムを大量に処理する必要があります。

FlexboxLayoutのレポジトリには、例としてデモアプリが公開されています。レポジトリを見ればわかるように、RecyclerView内のイメージの幅はまちまちです。しかし、flexWrap で折り返すように設定してあり、

FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
さらに各子ビューの flexGrow属性(下記のコード例のように、FlexboxLayoutManager では xml ではなく、 FlexboxLayoutManager.LayoutParamsを使用して RecyclerView の各要素の属性を設定できます)も正の値に設定してあるため、
void bindTo(Drawable drawable) {
mImageView.setImageDrawable(drawable);
ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp =
(FlexboxLayoutManager.LayoutParams) mImageView.getLayoutParams();
flexboxLp.setFlexGrow(1.0f);
}
}
画面の向きによらず、すべてのイメージをきれいにレイアウト内に収めることができます。



さらに複雑な FlexboxLayout の例を確認したい方は、以下をご覧ください。


次のステップ

ニーズに合った柔軟なレイアウトの構築に役立つその他の属性については、完全版のドキュメントをご覧ください。皆さんのフィードバックをお待ちしています。問題や機能リクエストがある場合は、GitHub レポジトリの問題にご報告ください。




Posted by Takeshi Hagikura - Developer Relations Team

Viewing all articles
Browse latest Browse all 2207

Trending Articles