创建动态多界面UI,需要把UI元素和动作封装到可以调用和隐藏的模块中。在此可以用Fragment把这些模块封装起来,就像Activity一样管理自己的布局元素和生命周期。
Fragment指定自己的布局元素后,会根据不同的屏幕适应不同的布局组合。eg:小屏幕可能显示一个Fragment,大屏幕就会显示多个。
Fragment能够创建一个动态的用户体验并且会根据不同屏幕尺寸的设备优化用户体验,这些在Android 1.6 (API level 4) 以上都可以支持(这里需要引用Support Library package),如果是Android 3.0 (API level 11)或更高就不需要啦。
创建一个Fragment Class
public class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.article_view, container, false);
}
}
就像Activity,一个Fragment可以实现系统回调生命周期方法来管理它的状态,例如从Activity中添加或是移除时切换它的生命周期状态。eg:当Activity的onPause()方法被调用时在Activity中的所有Fragment也会调用自己的onPause()方法; 这个时候需要去了解一下Fragment的生命周期(.......)。
用XML文件形式添加一个Fragment到FragmentActivity
Fragment组件重用时,需要有一个父容器FragmentActivity。可以从Activity布局XML文件中获取到被定义好的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="MyFragment"
android:id="@+id/fragment_1"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="MyFragment"
android:id="@+id/fragment_2"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
添加到布局文件中的Fragment在运行时是不能被移除掉滴。如果打算在用户交互时切入切出Fragment,必须在Activity启动时把Fragment添加进去。
创建一个灵活的UI
当设计App时支持高大上屏幕时,可以基于可用的屏幕空间在不同布局内配置优化用户体验,达到重用Fragment。eg:一个设备一次仅能够适合一个用户界面被显示。相反地,在平板电脑上可能就会设计Fragment并排多个显示,给用户更多的信息。
FragmentManager 在运行时提供 添加、移除、替换Fragments到Activity中,这样可以创建一个动态的体验。这是需要用FragmentManager 创建一个FragmentTransaction,支持添加,删除,替换和展示其他Fragment事务。
如果Activity允许这些操作,那就需要在Activity onCreate()方法中初始化Fragment(s)。
当我们处理Fragment时,在Fragment布局文件中必须有一个View容器。为了能够用其他的替换当前Fragment,Activity布局必须包含一个空的FragmentLayout作为Fragment的容器。
<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" />
在Activity中调用getSupportFragmentManager()获取FragmentManager然后调用beginTransaction()创建FragmentTransaction并且调用add()方法添加一个Fragment。当执行了改变操作后,必须调用commit()方法。eg:
MyFragment mMyFragment = new MyFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container,mMyFragment)commit();
Fragment的替换操作FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container,mMyFragment);
transaction.addToBackStack(StringName);//这里添加参数为Fragment名字,用于FragmentManager.BackStackEntry.getName()获取这个实体的名字。这样的Fragment存在的持续时间和Activity容器一样持久。
transaction.commit();
Fragment互相之间的通讯
Fragment为了能够重用,需要自己将布局或行为封装模块化,为自身使用。通常情况下,基于用户操作行为事件改变内容,想让一个Fragment与另外一个Fragment通讯,此时需要都通过Activity来完成,而不是互相之间直接通讯交互。
定义一个接口
在Fragment中定义并在Activity中实现一个接口,以使Fragment和Activity进行通讯。Fragment在它的生命周期方法onAttach()中捕获接口的实现,并且通过调用接口方法实现和Activity通信。eg:
public class MyFragment extends ListFragment {
OnMyListener mCallback;
// Activity容器必须实现这个接口
public interface OnMyListener {
public void OnMyListenerMethod(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnMyListener) activity;//Activity如果没有实现这个接口的话,就会抛出异常
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnMyListener");
}
}
。。。。。。mCallback 下面就可以拿着它“胡作非为”了
}
实现这个接口
为能够在Fragment中回调这些事件,Activity需要实现Fragment中定义的这些接口。
public class MainActivity extends Activity implements MyFragment.OnMyListener {
public void OnMyListenerMethod(int position) {
// Do something
}
}
给Fragment传递一条消息
Activity可以通过findFragmentById()获取到一个Fragment的实例,然后调用Fragment的公共方法来传递消息。
public class MainActivity extends Activity implements MyFragment.OnMyListener {
public void OnMyListenerMethod(int position) {
// Do something
OtherFragment mOtherFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_2);
if(mOtherFragment != null){
mOtherFragment.update(position);
}else{
OtherFragment mOtherFragment = new OtherFragment();
Bundle args = new Bundle();
args.putInt(MyFragment.POSITION,position);
mOtherFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
}