Androidアプリ開発 モーダル BottomSheetBehaviorでモーダル画面を表示する

Androidアプリ開発でも、メニューやダイアログでなく、WEBのようなモーダル画面を利用したい場合があります。Androidアプリでは、BottomSheetBehaviorを使ってモーダル画面を作成できます。
この記事は、AndroidアプリでBottomSheetBehaviorを使ってモーダル画面を作る方法を記載した記事です。
環境はAndroid 7.1 (API level 25) です。
環境
- OS X El Capitan
- android sdk 25
- Oracle jdk version 1.8.0_72
- Android Studio 2.3
難易度
初心者向け
サンプルコード
BottomSheetBehavior
BottomSheetBehaviorは、モーダル画面(Modal bottom sheets)を作成するクラスです。
一般的には、メニューや簡単なダイアログの代わりとして、リストやグリッドにアクションを表示するのに使います。メニューやダイアログより多くの情報を表示できます。
BottomSheetBehaviorはcom.android.support:designのversion23から導入されました。
アプリ設計
この記事のサンプルでは、画面で日付をタップすると、画面下から出現する詳細な日付を表示するモーダル画面をBottomSheetBehaviorで作成します。
動画
記事の内容を実装したBottomSheetBehavior Modalアプリの動画です。
アプリ実装
日付を表示するカレンダー画面をFragmentで作成し、BottomSheetBehaviorは、Fragmentを管理するActivityクラスで実装します。クラス名はBottomSheetBehaviorActivityにします。
/** * Screen for BottomSheetBehavior */ public class BottomSheetBehaviorActivity extends AppCompatActivity implements CalendarFragment.OnFragmentInteractionListener { private RelativeLayout bottomSheet; private BottomSheetBehavior behavior; private TextView text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bottom_sheet_behavior); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); bottomSheet = (RelativeLayout) findViewById(R.id.bottomSheet); behavior = BottomSheetBehavior.from(bottomSheet); behavior.setState(BottomSheetBehavior.STATE_HIDDEN); text = (TextView) findViewById(R.id.text); } @Override public void onClickDay(Day day) { if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) { behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); text.setText(day.getDay()); } else { behavior.setState(BottomSheetBehavior.STATE_HIDDEN); } } }
layoutを記述したactivity_bottom_sheet_behavior.xmlは以下のように記載します。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
tools:context="java_lang_programming.com.android_layout_demo.article81.BottomSheetBehaviorActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_bottom_sheet_behavior" />
<RelativeLayout
android:id="@+id/bottomSheet"
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="#000000"
app:behavior_hideable="true"
app:behavior_peekHeight="300dp"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
■ 実装の解説
1. BottomSheetBehavior
BottomSheetBehaviorは画面の下からViewを出現させるクラスです。
private RelativeLayout bottomSheet; bottomSheet = (RelativeLayout) findViewById(R.id.bottomSheet); behavior = BottomSheetBehavior.from(bottomSheet);
BottomSheetBehavior.fromメソッドは、引数にviewを受け取ります。引数に渡すViewはCoordinatorLayoutのサブクラスである必要あります。
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout> <RelativeLayout> <TextView /> </RelativeLayout> </android.support.design.widget.CoordinatorLayout>
CoordinatorLayoutのサブクラスでない場合は、IllegalArgumentExceptionが発生します。なぜなら、引数のviewはgetLayoutParamsメソッドを呼び出して、CoordinatorLayout.LayoutParamsのオブジェクトであることを確認します。
ViewGroup.LayoutParams params = view.getLayoutParams(); if (!(params instanceof CoordinatorLayout.LayoutParams)) { throw new IllegalArgumentException("The view is not a child of CoordinatorLayout"); }
2. BottomSheetBehaviorの状態を取得
BottomSheetBehavior#getState()メソッドで現在のBottomSheetBehaviorの状態を取得することができます。
if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) { } else { }
3. BottomSheetBehaviorの状態を設定
BottomSheetBehavior#setState()メソッドでBottomSheetBehaviorの状態を設定することができます。
if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) { behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); text.setText(day.getDay()); } else { behavior.setState(BottomSheetBehavior.STATE_HIDDEN); }
BottomSheetBehaviorには、5つのState定数が宣言されています。
/** * The bottom sheet is dragging. */ public static final int STATE_DRAGGING = 1; /** * The bottom sheet is settling. */ public static final int STATE_SETTLING = 2; /** * The bottom sheet is expanded. */ public static final int STATE_EXPANDED = 3; /** * The bottom sheet is collapsed. */ public static final int STATE_COLLAPSED = 4; /** * The bottom sheet is hidden. */ public static final int STATE_HIDDEN = 5;
よく使用するのは、STATE_EXPANDED, STATE_COLLAPSED, STATE_HIDDENです。STATE_HIDDENはBottomSheetBehaviorに設定したviewを非表示にします。

STATE_HIDDENを有効にするには、app:behavior_hideable="true"で指定します。
app:behavior_hideable="true"
STATE_COLLAPSEDはBottomSheetBehaviorに設定したviewを表示します。

Viewの位置はapp:behavior_peekHeightで指定した高さです。
app:behavior_peekHeight="300dp"
STATE_EXPANDEDはBottomSheetBehaviorに設定したviewを全て表示します。

googleの公式では、STATE_COLLAPSEDでViewを表示して、ユーザーがviewをスワイプさせることを推奨しています。
ビルド
上記のコードビルドして動作を確認します。

BottomSheetBehaviorでviewが表示できました。
結論
Androidでも、BottomSheetBehaviorを使ってWEBのようなモーダル画面を作れるようになりました。便利な機能なので、利用してみてください。