Android之Fragments


定义:A Fragment represents a behavior or a portion of user interface in an Activity.
一个Activity可包括多个Fragments,用来创建一个多pane的UI,并可在多个Activity中重用这些Fragment。此外,可将其看做是一个Activity的模块化部分,它有本身的生命周期,可接受用户输入,可在Activity运行时进行添加或者修改。
一个Fragment必须嵌入到一个Activity中,且受宿主Activity的影响。如Activity pause了,那么全部的Fragment都将进入pause,当全部Activity destory了,全部的Fragment也都destory了。当Activity在运行时,可添加或者删除fragment,还能够将其加入back stack,这样可经过back button 进行回退。
当添加一个Fragment时,它将做为ViewGroup的一个部分,而且可定义本身的View。可经过在Activity的代码中插入< fragment>标签,或者在运行时将其添加到一个已经存在ViewGroup。
然而Fragment并不一必定要做为Activity Layout的一部分,它也能够是无UI的,做为Activity不可见的Worker。android

Design Philosophy

 An example of how two UI modules defined by fragments can be combined into one activity for a tablet design, but separated for a handset design.

Creating a Fragment

1. OverView

  1. 须要继承fragment class。
  2. 生命周期
    Framgent生命周期
    一般必须实现如下三个回调。

- OnCreate(), 初始化必须的组建,即须要在fragement的onPause, onStop, onResume等状态时retain这些。
- onCreateView(), 为Fragemnt建立UI,而且须要返回布局的根View。若是该fragment不须要界面,也能够返回Null。
- onPause(), 这是指示用户须要离开该fragment,所以须要提交须要持久化的数据。app

还有3个Fragment能够继承的:less

  • dialogFragment, 显示一个悬浮的对话框。是对Activity的dialog helper method一个很好的替换,由于你能够将一个Fragment合并到由Activity管理的fragment 的backstack,这样就容许用户返回到以前消失的fragment。
  • ListFragment, 显示一个由Adapter管理的列表式的item,相似与ListActivity。
  • PreferenceFragment, 用list显示一个层级结构的Preference对象。相似与PreferenceActivity,对于建立settings比较有用。

2. Adding A user Interface

提供用户接口,必须实现onCreateView(),返回布局的根View。如果ListFragment,则返回ListView。
To return a layout from onCreateView(), 可inflate an xml layout resource。 onCreateView的默认参数包含了一个LayoutInflater的对象。
代码以下:ide

public static class ExampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}

其中 container 是Activity布局里的ViewGroup对象,而后inflate出来的布局会被出入到该container。Bundler则是用于传递参数或者其余恢复布局的状态。然而,inflate方法的3个参数,第一个为布局的resource id, 第二个为container, 第3个指示是否须要attach 到 viewgroup,因为指定了container,于是此处应设为false,不然Android System将会create a redundant view group in the final layout.模块化

3. Adding a fragment to an activity

two ways to add。
1. 在activity的xml layout文件中,声明fragment xml 布局文件。布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>

其中android:name 属性为指定Fragment类来初始化layout。在系统初始话该布局时,它会初始化每一个fragment类,而后调用onCreateView()方法,获取到每一个fragment的布局。
为了重用the fragment,须要为每一个fragment分配一个unique id:使用android:id; 使用adndroid:tag; 不设置,系统使用container的id。
2. 代码中添加到一个现存的ViewGroup动画

// 获取fragmentTransaction,就可实现诸如add, remove, or replace a fragment等行为。
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//  添加一个fragment到R.id.fragment_container,并提交。
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

4. Adding a fragment without a UI

可将该fragment做为一个后台worker。
方法:ui

使用add(Fragment, String), 其中String是一个字符串tag,因为不提供layout给activity,所以该fragment也无需建立onCreateView()。tag将做为该fragment的标识,并使用findFragmentByTag()方法来寻找。this

Managing Fragments

  1. 使用FragmentManager,可经过getFragmentManager()得到。
  2. 可作的事情包括:

- getFragmentById(), or getFragmentByTag();
- pop fragments off the back stack with popBackStack()
- addOnBackStackChangedListener(), register a listener for changes。
- open a FragmentTransaction, 处理add, remove fragment等事务。spa

Performing Fragment Transactions

Steps:
1. acquire an instance of FragmentTransaction

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
  1. using methods such as add(), remove(), and replace(), and then call commit() to apply the transaction.
  2. before calling commit(), you might want to call addToBackStack(), 以便于将该fragment当前的状态保存,即将其加入backstack,这样用户可以使用按钮回退到该界面。
    示例:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

上述代码替换掉container中的当前fragment。
若调用了多个操做,add,replace等且调用了addToBackStack,在commit以前的全部操做都会被保存,并可被一块儿恢复。
commit必须被最后执行,添加多个fragment到同一个container,添加顺序将绝定每一个fragment在view hierarchy的顺序。

Tip:, 调用setTransition(),可为fragment之间的切换添加动画。另,若不调用addToBackStack,则调用remove,该fragment就会被destory。如果调用了addToBackStack,则该fragment将进入stopped,而且可被resumed when the user navigate it。

此外,commit()不是马上执行transation,而是会根据主线程调度状况执行。除非必需要马上执行,可调用executePendingTransaction()。
最后须要注意的是,commit()必须先于activity的saving its state(即pause或stop),不然将致使异常。解决这个问题,可调用cimmitAllowingStateless()。

Communicating with the Activity

1. Overview

  • the fragment can access the Activity instance.
    View listView = getActivity.findViewById(R.id.list)
  • the activity can also can methods in fragment by acquiring a refrence to the Fragment from FragmentManager
    ExampleFragment fragment = getFragmentManager.findFragmentById(R.id.example_fragment);

2. Creating event callbacks to the activity

  • 在fragment的子类中,申明一个内部的回调接口,这样activity实现该接口,便可实现回调。
public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}
  • 保证容器Activity实现该回调,在fragment的onAttach时,实例化该接口。
public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...
}
  • 在fragment中,如有事件发生须要传递给Activity,则调用
    mListener.onArticleSelected(uri)
    便可通知到宿主activity。

Adding items to the Action Bar

  1. 实现onCreateOptionsMenu(), 而后在onCreate必须调用setHasOptionsMenu() 以便于接受options的调用。
  2. 也接受onOptionsItemSelected()方法回调,
  3. 可以使用ContextMenu:registerForContextMenu(),并可在onCreateContextMenu()中接受到调用通知,也可在onContextItemSelected()中收到选中item的调用通知。

事件处理流程是Activity先处理,发现无人处理后才会向下传递到fragment中。

Handling the Fragment Lifecycle

The effect of the activity lifecycle on the fragment lifecycle.

管理一个生命周期,仍然包括三个态:
- Resumed,运行时,可见。
- Paused, 被另外一个Activity挡住了,但本Activity仍然可见(未被彻底遮住,如dialog)。
- Stopped, 彻底不可见,但all state and member information is retained by the system。

可用onSaveInstanceState()保存数据,并在onCreate(), onCreateView(), or onActivityCreated()中重装。

其中Activity会自动进入BackStack,而fragment须要明确调用addToBackStack()。

1. Coordinating with the activity lifecycle

相关文章
相关标签/搜索