Fragment 碎片学习

Fragments是什么?


  碎片(Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分
地利用大屏幕的空间,因而在平板上应用的非常广泛。

 

  创建一个动态的、多窗格在Android用户界面,您需要将UI组件和Activity行为封装到模块,而这些模块你可以用来交换的活动。

您可以创建这些模块与Fragment类,这行为有点像一个嵌套的Activity,可以定义自己的布局和管理自己的生命周期。

Fragment 的生命周期


 

碎片的生命周期类似于活动的生命周期,可能的状态如下:

1. 运行状态
  当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行
状态。

2.暂停状态

  当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与
它相关联的可见碎片就会进入到暂停状态。

3. 停止状态
  当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态。或者通过调
用 FragmentTransaction 的 remove()、replace()方法将碎片从活动中移除,但有在事务提
交之前调用 addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入
停止状态的碎片对用户来说是完全不可见的,有可能会被系统回收。

4. 销毁状态
  碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入
到销毁状态。或者通过调用 FragmentTransaction 的 remove()、replace()方法将碎片从活
动中移除,但在事务提交之前并没有调用 addToBackStack()方法,这时的碎片也会进入
到销毁状态。

 

Fragment 类中也提供了一系列的回调方法,以覆盖碎片生命周期的每个环节。其中,活动中有的回调方法,碎片

中几乎都有,不过碎片还提供了一些附加的回调方法,主要的如下:

1. onAttach()
  当碎片和活动建立关联的时候调用。
2. onCreateView()
  为碎片创建视图(加载布局)时调用。
3. onActivityCreated()
  确保与碎片相关联的活动一定已经创建完毕的时候调用。
4. onDestroyView()
  当与碎片关联的视图被移除的时候调用。
5. onDetach()
  当碎片和活动解除关联的时候调用。

 

生命周期如图所示

创建一个 Fragment 类


为了创建一个Fragement,需要继承 Fragment 类,然后重写有关生命周期的方法并在其中插入你需要的逻辑,类似创建一个活动

唯一不同的一点就是你需要实现 onCreateView() 来返回定义的布局

需要自己定义一个XML布局

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);
    }
}

 

就像一个活动,fragment也拥有生命周期函数,用来从活动中添加或删除和与活动的生命周期状态之间的对应。

例如当活动的onPause()被调用时,活动中的fragment也会收到调用onPause()

利用XML文件添加Fragment到活动中


 

添加 <fragment> 元素,并将 <fragment>  的 name 属性设置为创建的fragment类

<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 添加 Fragment


 

你可以在 Activity 运行时向其添加 Fragment, 而不用使用 <fragment> 元素在布局文件中为 Activity 定义 Fragment。

如果你打算在 Activity 运行周期内更改 Fragment,就必须这样做。

 

要执行添加或移除 Fragment 等事务,你必须使用 FragmentManager 创建一个 FragmentTransaction,后者可提供用于执行添加、移除、替换以及其他 Fragment 事务的 API。

在处理 Fragment(特别是在运行时添加的 Fragment )时,请谨记以下重要规则:

  必须在布局中为 Fragment 提供 View 容器(比如FrameLayout),以便保存 Fragment 的布局。

 

步骤:  

  1. 创建待添加的碎片实例。
  2. 获取到 FragmentManager,在活动中可以直接调用 getFragmentManager()方法得到。
  3. 开启一个事务,通过调用 beginTransaction()方法开启。
  4. 向容器内加入碎片,一般使用 replace()方法实现,需要传入容器的 id 和待添加的碎
  片实例。
  5. 提交事务,调用 commit()方法来完成。

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);

            // 确认 Activity 使用的布局版本包含
            // fragment_container FrameLayout
            if (findViewById(R.id.fragment_container) != null) {

                // 不过,如果我们要从先前的状态还原,
                // 则无需执行任何操作而应返回
                // 否则就会得到重叠的 Fragment 。
                if (savedInstanceState != null) {
                    return;
                }

               // 创建 Fragment 并为其添加一个参数,用来指定应显示的文章
           ArticleFragment newFragment = new ArticleFragment();
           Bundle args = new Bundle();
           args.putInt(ArticleFragment.ARG_POSITION, position);
           newFragment.setArguments(args);

           FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

           // 将 fragment_container View 中的内容替换为此 Fragment ,
           // 然后将该事务添加到返回堆栈,以便用户可以向后导航
           transaction.replace(R.id.fragment_container, newFragment);
           transaction.addToBackStack(null);

           // 执行事务
           transaction.commit();
            }
        }
    }

 

请注意,当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 addToBackStack(),然后再执行 FragmentTransaction。 

 

Fragment 通信


 

 Fragment 向 Activity 传递数据

方法一:

  1、在 Fragment 类中声明一个接口,并定义一个接口

  2、在 onAttach 中将定义的接口与传进来的 activity 进行绑定

  3、在 Activity 中实现 Fragment 中定义的接口

  在 Fragement 中需要传给 activity 时调用定义的接口函数,实现将 Fragment 数据传给Activity

 

  定义接口

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(Context context) {
        super.onAttach(context);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }

    ...
}

 

  传递数据给activity

@Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Send the event to the host activity
        mCallback.onArticleSelected(position);
    }

 

  实现接口

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
    }
}

 

 

方法二:

  可以在 Fragment 中调用 getActivity() 获取 Activity 实例,从而调动 Activity 方法

MainActivity activity = (MainActivity) getActivity();

 

向 Fragment 传递数据

为了方便碎片和活动之间进行通信, FragmentManager 提供了一个类似于 findViewById() 的方法,专门用于从布局文件中获取碎片的实例

可以通过 FragmentManager 的 findFragmentById() 获取 Fragment 的实例

 

例如上个例子中当选择了一个 Fragment 中的 item 时,需要向另一个 Fragment 更新数据时,获取另一个 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();
        }
    }
} 
posted @ 2016-10-25 18:47  时光小孩  阅读(286)  评论(0编辑  收藏  举报