Androidアプリ開発 FrameLayoutのFragment 子のFragmentを重ねた親のFragmentのタッチイベントを無効にする

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

AndroidアプリでFragmentを利用する場合は、Fragmentの上に別のFragmentを重ねることはよくあります。
この記事は、親のFragmentに子のFragmentの重ねたとき、親のFragmentのタッチイベントを無効にする方法を記載した記事です。

環境はAndroid 7.1 (API level 25) です。

環境

  • macOS Sierra
  • android sdk 25
  • Oracle jdk version 1.8.0_72
  • Android Studio 2.3.1

難易度

初心者向け

サンプルコード

Android-Basic-Technique-Demo

動画

記事の内容を実装したアプリケーションの動画です。

重ねたFragmentの挙動

親のFragementの上に、FrameLayoutやRelativeLayoutで作成した子のFragmentを重ねると、親のFragmentで設定したclickイベントが重ねた子のフラグメントからも実行されます。

fig1. 子のFragmentから親のFragmentのクリックイベントが発火

上記のサンプルは、子のFragmentをモーダル画面として表示しています。この時、モーダル画面は、下の親Fragmentのイベントも実行してしまいます。

この子のFragmentレイアウトxmlファイルは以下です。

{project_folder}/main/res/layout/fragment_child.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ADD62044"
    tools:context="java_lang_programming.com.android_basic_technique_demo.article83.ChildFragment">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:gravity="center"
        android:text="@string/fragment_child_text" />

    <Button
        android:id="@+id/btn_click_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/text"
        android:text="@string/fragment_child_btn_1" />

</RelativeLayout>
        

Don't.

FrameLayoutやRelativeLayout等のレイアウトを重ねたViewは、イベントが下のViewまで伝わります。

これはAndroidの仕様です。Viewを重ねてもイベントを取得する必要があるからです。

修正方法

親のFragmentにタッチイベントが伝わらないようにします。

{project_folder}/main/res/layout/fragment_child.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   +android:clickable="true"    
    android:background="#ADD62044"
    tools:context="java_lang_programming.com.android_basic_technique_demo.article83.ChildFragment">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:gravity="center"
        android:text="@string/fragment_child_text" />

    <Button
        android:id="@+id/btn_click_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/text"
        android:text="@string/fragment_child_btn_1" />

</RelativeLayout>
        

Do.

子のFragmentのLayoutにandroid:clickable="true"を追加します。これで親のFragmentのイベントを遮断できます。

ビルド

上記のコードの動作を確認してみましょう。

fig2. 子のFragmentから親のFragmentのクリックイベントが発火しない

親のFragmentのイベントが無効になりました。

結論

Androidの開発では、Viewの仕組みを知っておくと便利です。開発に慣れてきたらAndroidのソースコードも読んでみましょう。

関連記事

タグ検索で調べてみよう

Android7.1 UI