【Android応用開発技術:応用コンポーネント】Fragment使用方法


作者:郭孝星微博:郭孝星の新浪微博メールアドレス:[email protected]ブログ:http://blog.csdn.net/allenwells Github:https://github.com/AllenWells
【Androidアプリケーション開発技術:アプリケーションコンポーネント】章一覧
Fragment管理と事務
Activityは、FragmentManagerによってFragmentを管理します.FragmentManagerは、次の機能を実行できます.
  • findFragmentById()またはfindFragmentByTag()メソッドを呼び出して、指定されたFragmentを取得します.XMLファイルでFragmentを定義する場合はandroid:idまたはandroid:tagでFragmentを識別できます.
  • popBackStack()メソッドを呼び出して、バックグラウンドスタックからFragmentをポップアップし、ユーザーのbackキーをシミュレートします.
  • addOnBackStackChangeListener()を呼び出して、バックグラウンドスタックの変更をリスニングするリスナーを登録します.

  • Fragmentの作成方法を学ぶ前に、次の図に示すように、Fragmentの継承システムを見てみましょう.
    Fragment継承アーキテクチャクラス図Visioソースファイルダウンロード
    【Android应用开发技术:应用组件】Fragment使用方法_第1张图片
    Fragmentを作成するには、Fragmentクラスを継承し、対応するライフサイクルメソッドにビジネスロジックを書き込む必要があります.Fragmentを定義する際に最も頻繁に書き換える方法は、次のようにonCreateView()です.
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.view.LayoutInflater;
    import android.view.ViewGroup;
    public class ArticleFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.article_view, container, false);
        }
    }

    1.1 Fragmentの追加
    1.1.1静的追加
    静的追加とは、レイアウトファイルで要素を常に使用し、要素のandroid:name属性はFragmentを実装するクラスを指定します.XMLレイアウトファイルを使用してActivityにFragmentを静的に追加する方法では、Fragmentは動的に削除できません.Fragmentのダイナミックな切り込みと切り抜きを実現するには、Activityが起動した後、ActivityにFragmentを追加する必要があります.
    例を挙げる
    res/layout-large/newsを定義します.articles.xmlファイル
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <fragment android:name="com.example.android.fragments.HeadlinesFragment"
                  android:id="@+id/headlines_fragment"
                  android:layout_weight="1"
                  android:layout_width="0dp"
                  android:layout_height="match_parent" />
        <fragment android:name="com.example.android.fragments.ArticleFragment"
                  android:id="@+id/article_fragment"
                  android:layout_weight="2"
                  android:layout_width="0dp"
                  android:layout_height="match_parent" />
    LinearLayout>

    Activityへのレイアウトファイルの追加
    import android.os.Bundle;
    import android.support.v4.app.FragmentActivity;
    public class MainActivity extends FragmentActivity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.news_articles);
        }
    }

    1.1.2動的追加
    JavaコードにFragmentTransactionオブジェクトのadd()メソッドでFragmentを追加します.ActivityのgetFragmentManager()メソッドはFragmentManagerオブジェクトを返し、FragmentManagerオブジェクトのbeginTransaction()メソッドはFragmentTransactionオブジェクトを開いて返します.
    例を挙げる
    res/layout_を定義するarticles.xmlファイル
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    1.2 Fragmentの置換
    Fragmentを置き換えるプロセスは追加するプロセスと非常に似ており,add()メソッドをreplace()メソッドに置き換える必要がある.
    注意:Fragmentトランザクションを実行する場合、たとえば、ユーザーがこの操作を後方にナビゲートして取り消すことができるように適切にする必要があります.FragmentTransactionのコミット前にaddToBackStack()メソッドを呼び出す必要があります.addToBackStack()メソッドは、トランザクションに一意の名前を指定するオプションのStringパラメータを提供します.FragmentManagerを使うつもりでない限り、この名前は必須ではありません.BackStackEntry APIsは、いくつかの高度なFragment操作を行います.
    Fragmentを除去または置換して戻りスタックに入れると、除去されたfragmentのライフサイクルはdestoryedではなくstoppedになります.ユーザがこのFragmentを再開すると、そのライフサイクルはrestartsになります.Fragmentを戻りスタックに入れなかった場合、削除または置き換えられたときのライフサイクルはdestoryedです.
    例を挙げる
    // Create fragment and give it an argument specifying the article it should show
    ArticleFragment newFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putInt(ArticleFragment.ARG_POSITION, position);
    newFragment.setArguments(args);
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    // Replace whatever is in the fragment_container view with this fragment,
    // and add the transaction to the back stack so the user can navigate back
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);
    // Commit the transaction
    transaction.commit();

    二FragmentとActivity通信
    まず2つのFragment間のインタラクションの問題についてお話しします.
    Fragment UIコンポーネントを再利用するには、各Fragmentを完全に自己包含的でモジュール化されたコンポーネントに構築し、独自のレイアウトと動作を定義する必要があります.これらのモジュール化されたFragmentを定義すると、Activityを関連付け、Appの論理と結合させ、グローバルな複合UIを実現することができます.
    通常、ユーザイベントに基づいてFragmentの内容を変更するなど、Fragment間で相互作用したいと考えています.すべてのFragment間のインタラクションは、それらに関連付けられたactivityによって必要であり、2つのFragment間で直接インタラクションすべきではない.
    2.1 ActivityからFragmentへのデータ転送
    ActivityでBundleパケットを作成し、FragmentのsetArguments(Bundle bundle)メソッドを呼び出すと、BundleパケットをFragmentに渡すことができます.
    例を挙げる
    public static class MainActivity extends Activity
            implements HeadlinesFragment.OnHeadlineSelectedListener{
        ...
        public void onArticleSelected(int position) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article
            ArticleFragment articleFrag = (ArticleFragment)
                    getSupportFragmentManager().findFragmentById(R.id.article_fragment);
            if (articleFrag != null) {
                // If article frag is available, we're in two-pane layout...
                // Call a method in the ArticleFragment to update its content
                articleFrag.updateArticleView(position);
            } else {
                // Otherwise, we're in the one-pane layout and must swap frags...
                // Create fragment and give it an argument for the selected article
                ArticleFragment newFragment = new ArticleFragment();
                Bundle args = new Bundle();
                args.putInt(ArticleFragment.ARG_POSITION, position);
                newFragment.setArguments(args);
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragment_container, newFragment);
                transaction.addToBackStack(null);
                // Commit the transaction
                transaction.commit();
            }
        }
    }

    2.2 FragmentからActivityへのデータ転送
    Fragmentで内部コールバックインタフェースを定義し、このコールバックインタフェースをFragmentを含むActivityに実装させることで、Fragmentはコールバックメソッドを呼び出してActivityにデータを渡すことができます.
    例を挙げる
    Fragmentでインタフェースを定義しました
    public class HeadlinesFragment extends ListFragment {
        OnHeadlineSelectedListener mCallback;
        // Container Activity must implement this interface
        public interface OnHeadlineSelectedListener {
            public void onArticleSelected(int position);
        }
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            // This makes sure that the container activity has implemented
            // the callback interface. If not, it throws an exception
            try {
                mCallback = (OnHeadlineSelectedListener) activity;
            } catch (ClassCastException e) {
                throw new ClassCastException(activity.toString()
                        + " must implement OnHeadlineSelectedListener");
            }
        }
    
     //Fragment         Activity    
     @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            // Send the event to the host activity
            mCallback.onArticleSelected(position);
        }
    }

    Fragmentが属するActivityはこのインタフェースを実現する
    public static class MainActivity extends Activity
            implements HeadlinesFragment.OnHeadlineSelectedListener{
        ...
        public void onArticleSelected(int position) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article
        }
    }