Android
 Computer >> コンピューター >  >> プログラミング >> Android

【Android】FragmentでfindViewByIdを使う方法を実例付きで解説


FragmentでfindViewByIdを使う方法

この記事では、Androidアプリ開発においてFragment内からfindViewById()を使ってViewを取得する方法を、実際に動作するサンプルコードとともにわかりやすく解説します。画面を上下に分割して2つのFragmentを配置したシンプルなアプリを題材にします。

最重要ポイント:inflateしたViewに対して呼び出す

FragmentでfindViewById()を使う際に最も重要なのは、「onCreateView()でインフレートしたルートViewに対して呼び出す」という点です。Fragmentの中で何も付けずにfindViewById(R.id.text)と書いてしまうと、それはActivity側のビュー階層を検索するため、Fragment自身のレイアウト内のViewは見つかりません。必ずインフレート結果のViewオブジェクト経由で呼び出しましょう。

ステップ1:新規プロジェクトを作成する

Android Studioを起動し、メニューからFile → New Projectを選択します。必要な項目をすべて入力して、新しいプロジェクトを作成してください。この記事では言語にJavaを使用します。

ステップ2:activity_main.xmlにレイアウトを記述する

res/layout/activity_main.xml に以下のコードを追加します。

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    android:orientation = "vertical"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent">
    <LinearLayout
        android:id = "@+id/linearlayout01"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:background = "#ccc"
        android:layout_weight = "1"
        android:orientation = "vertical">
        <fragment android:name = "com.example.myapplication.FirstFragment"
            android:id = "@+id/frag_1"
            android:layout_width = "match_parent"
            android:layout_height = "match_parent" />
    </LinearLayout>
    <LinearLayout
        android:id = "@+id/linearlayout02"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:layout_weight = "1"
        android:background = "#eee"
        android:orientation = "vertical">
        <fragment android:name = "com.example.myapplication.SecondFragment"
            android:id = "@+id/frag_2"
            android:layout_width = "match_parent"
            android:layout_height = "match_parent" />
    </LinearLayout>
</LinearLayout>

このレイアウトでは、縦方向のLinearLayoutの中に2つのLinearLayoutを配置し、それぞれ<fragment>タグで「FirstFragment」「SecondFragment」を埋め込んでいます。layout_weight="1" を指定しているため、画面が上下に均等に分割されます。

ステップ3:MainActivity.javaを記述する

src/MainActivity.java に以下のコードを追加します。

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

※古いサンプルでは android.support.v4.app.FragmentActivity が使われることもありますが、現在はAndroidX(androidx.appcompat.app.AppCompatActivity や androidx.fragment.app.Fragment)の利用が推奨されています。

ステップ4:FirstFragment.javaを記述する

src/FirstFragment.java に以下のコードを追加します。ここが本題となる部分です。

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class FirstFragment extends Fragment {
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment, container, false);
        TextView text = (TextView) root.findViewById(R.id.text);
        return root;
    }
}

ポイントは次の行です。

TextView text = (TextView) root.findViewById(R.id.text);

onCreateView()でインフレートしたルートView(root)に対してfindViewById()を呼び出すことで、Fragment自身のレイアウト内にあるTextViewを正しく取得できます。また、inflate()の第2引数にはcontainerを渡し、第3引数にはfalseを指定するのが推奨される書き方です(nullを渡すとレイアウトパラメータが失われる場合があります)。

ステップ5:SecondFragment.javaを記述する

src/SecondFragment.java に以下のコードを追加します。こちらは「onViewCreated()の中でfindViewById()を呼ぶ」という、もうひとつの定番パターンを示した例です。

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class SecondFragment extends Fragment {
    private TextView textView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        textView = view.findViewById(R.id.text);
    }
}

onCreateView()で生成したViewは、onViewCreated()の引数としても受け取れます。そのため、onViewCreated()内でview.findViewById(...)と書けば安全にViewを取得でき、取得した参照をフィールドに保持しておけばFragmentのライフサイクル全体で使い回せます。

アプリを実行して確認する

それでは、実際にアプリを起動してみましょう。Android端末をPCに接続した状態で、Android StudioのツールバーにあるRun(▶)アイコンをクリックし、デバイスとして自分のスマートフォンを選択します。ビルドが完了すると、端末に次のような画面が表示されます。

【Android】FragmentでfindViewByIdを使う方法を実例付きで解説

まとめ

  • FragmentでfindViewById()を使うときは、onCreateView()でインフレートしたルートViewに対して呼び出すのが基本
  • onCreateView()以降の処理では、onViewCreated()の引数viewやgetView()経由で呼び出せる
  • 無指定のfindViewById()はActivityのビュー階層が検索対象になるため、Fragmentのレイアウト内のViewは取得できない点に注意
  1. 【Android】スナックバー(Snackbar)の使い方をステップごとに解説

    このチュートリアルでは、Androidアプリでスナックバー(Snackbar)を使用する方法を、サンプルコードとともに段階的に解説します。スナックバーは画面下部に短いメッセージを一時的に表示できるUIコンポーネントで、Toastとは異なり「再試行(RETRY)」などのアクションボタンを組み込めるのが大きな特徴です。 手順1:新規プロジェクトを作成する Android Studioを起動し、メニューから「File」→「New Project」を選択します。必要な項目をすべて入力して、新しいプロジェクトを作成しましょう。 手順2:レイアウトファイル(activity_main.xml)を編集する

  2. 【Android】NavigationViewの実装方法をステップごとに解説

    この記事では、AndroidアプリでNavigationView(ナビゲーションビュー)を使用してドロワーメニューを実装する方法を、ステップごとに詳しく解説します。ハンバーガーアイコンから開閉できるサイドメニューは、多くのアプリで採用されている定番のUIです。ステップ1:新しいプロジェクトを作成するAndroid Studioを開き、File → New Project を選択して、必要な情報を入力し新しいプロジェクトを作成します。テンプレートには「Navigation Drawer Activity」を選ぶと、後の作業がスムーズになります。ステップ2:activity_main.xml にコ