Fragment是3.0引入的新组件,在3.0之前需要引入v4包的Fragment进行向下兼容,在项目中会频繁用到。
先说下3.0的Fragment用法。
其中,Fragment的生命周期就不多说了,首先构建Fragment 的View对象。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment02, null);
return v;
}
然后在Activity中显示目标Fragment。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fg3 = new Fragment03();
//获取fragment管理器
FragmentManager fm = getFragmentManager();
//打开事务
FragmentTransaction ft = fm.beginTransaction();
//把内容显示至帧布局
ft.replace(R.id.fl, fg3);
//提交
ft.commit();
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="horizontal"
>
<FrameLayout
android:id="@+id/fl"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
></FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fragment01"
android:onClick="click1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fragment02"
android:onClick="click2"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fragment03"
android:onClick="click3"
/>
</LinearLayout>
</LinearLayout>
首先,我们要先导入系统自带的V4包。
package com.itheima.supportfragment;
import android.os.Bundle;
import android.app.Activity;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.view.View;
public class MainActivity extends FragmentActivity {
private Fragment03 fg3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fg3 = new Fragment03();
//获取fragment管理器
FragmentManager fm = getSupportFragmentManager();
//打开事务
FragmentTransaction ft = fm.beginTransaction();
//把内容显示至帧布局
ft.replace(R.id.fl, fg3);
//提交
ft.commit();
}
}
与上者使用方法大体相同,都是替换Activity中的FrameLayout布局。
最后说下Activity与Fragment之间数据的传递。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment01, null);
final EditText et = (EditText) v.findViewById(R.id.et);
Button bt = (Button) v.findViewById(R.id.bt);
bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String text = et.getText().toString();
//把数据传递给activity
((MainActivity)getActivity()).setText(text);
}
});
return v;
}
Fragment向Activity传递数据时,直接调用getActivity()获取Activity的对象。
public void click4(View v){
String text = et_main.getText().toString();
//传递数据
fg3.setText(text);
}
Activity向Fragment传递数据时,先new一个Fragment即可。
但是一般Fragment与Activity之间最好利用回调接口的方式进行数据传递。这样做的好处是利于Fragment的重用性。
public static class FragmentA extends ListFragment{
...
//Container Activity must implement this interface
public interface OnArticleSelectedListener{
public void onArticleSelected(Uri articleUri);
}
...
}
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");
}
}
...
}
如果 activity 没有实现那个接口, fragment 抛出 ClassCastException 异常。如果成功了, mListener 成员变量保存 OnArticleSelectedListener 的实例。于是 fragmentA 就可以调用 mListener 的方法来与 activity 共享事件。例如,如果 fragmentA 是一个 ListFragment ,每次选中列表的一项时,就会调用 fragmentA 的 onListItemClick() 方法,在这个方法中调用 onArticleSelected() 来与 activity 共享事件,如下:
public static class FragmentA extends ListFragment{
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l,View v,int position,long id){
//Append the clicked item's row ID with the content provider Uri
Uri noteUri =ContentUris.withAppendedId(ArticleColumns.CONTENT_URI,id);
//Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}
FragmentManager可以做如下一些事情:
1、使用findFragmentById() (用于在activity layout中提供一个UI的fragment)或findFragmentByTag()(适用于有或没有UI的fragment)获取activity中存在的fragment
2、将fragment从后台堆栈中弹出, 使用 popBackStack()
3、使用addOnBackStackChangeList
FragmentTransaction是对Fragment进行添加,替换,移除等操作的。
在使用add(),replace(),remove()时可以动态的给每一个Fragment添加一个标签,下次方便FragmentManager通过tag标签进行查找。最后记得ft.commit();
当执行一个移除fragment的事务时, 如果没有调用 addToBackStack(), 那么当事务提交后, 那个fragment会被销毁,并且用户不能导航回到它. 有鉴于此, 当移除一个fragment时,如果调用了 addToBackStack(), 那么fragment会被停止, 如果用户导航回来,它将会被恢复.我认为是重要的,以上的话,可以理解,remove后,加到堆栈后。按返回还是可以返回到之前的fragment。fragment的显示和隐藏可以用FragmentTransaction的show 或是hide来实现,ft.show(fragment); ft.hide(fragment);