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

2017年04月09日(編集2017年04月09日)
このエントリーをはてなブックマークに追加

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

難易度

初心者向け

サンプルコード

Android-Layout-Demo

BottomSheetBehavior

BottomSheetBehaviorは、モーダル画面(Modal bottom sheets)を作成するクラスです。

一般的には、メニューや簡単なダイアログの代わりとして、リストやグリッドにアクションを表示するのに使います。メニューやダイアログより多くの情報を表示できます。

BottomSheetBehaviorはcom.android.support:designのversion23から導入されました。

アプリ設計

この記事のサンプルでは、画面で日付をタップすると、画面下から出現する詳細な日付を表示するモーダル画面をBottomSheetBehaviorで作成します。

動画

記事の内容を実装したBottomSheetBehavior Modalアプリの動画です。

アプリ実装

日付を表示するカレンダー画面をFragmentで作成し、BottomSheetBehaviorは、Fragmentを管理するActivityクラスで実装します。クラス名はBottomSheetBehaviorActivityにします。

{project_folder}/BottomSheetBehaviorActivity.java
/**
 * 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は以下のように記載します。

{project_folder}/lactivity_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を非表示にします。

fig1. STATE_HIDDEN BottomSheetBehavior

STATE_HIDDENを有効にするには、app:behavior_hideable="true"で指定します。

app:behavior_hideable="true"
        

STATE_COLLAPSEDはBottomSheetBehaviorに設定したviewを表示します。

fig2. STATE_COLLAPSED BottomSheetBehavior

Viewの位置はapp:behavior_peekHeightで指定した高さです。

app:behavior_peekHeight="300dp"
        

STATE_EXPANDEDはBottomSheetBehaviorに設定したviewを全て表示します。

fig3. STATE_EXPANDED BottomSheetBehavior

googleの公式では、STATE_COLLAPSEDでViewを表示して、ユーザーがviewをスワイプさせることを推奨しています。

ビルド

上記のコードビルドして動作を確認します。

fig1. BottomSheetBehavior

BottomSheetBehaviorでviewが表示できました。

結論

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

タグ検索で調べてみよう

Android7.1 UI