1、什么是Fragment
Fragment从字面意思来说就是片段的意思,是Avtivity的子模式,所以其行为会受Activity控制,它的出现是为了适应大屏幕的手机或者平板,这些屏幕可以容纳更多的ui组件,比如在平板上一半是列表,一半是列表的具体内容展示。用Fragment展示就会很方便。Fragment是andorid3.0引进的新api,如果要在3.0之前的设备上使用,则需要继承android.support.v4.app.Fragment包。它有如下的特点
- Fragment总是Activity的一部分,可调用getActivity()方法获取所在的Activity
- 一个Activity可以有很多的Fragment,反过来,一个Fragment也可以被多个Activty复用
- Fragment可以响应自己输入事件,拥有自己生命周期
- 在Activity运行过程中,可调用FragmentManager的add(),remove(),replace()等方法动态的添加,删除,替换Fragment.
2、如何创建和添加Fragement
一般创建Fragment会实现下面三个方法
- onCreate():系统创建Fragment对象后会回调该方法。
- onCreateView():当Fragment显示页面组件时,会回调该方法。返回一个该Fragment所显示的View.
- onPause():用户离开时会回调该方法
1、直接在布局文件里添加(静态加载)
- 继承Fragement,重写onCreateView方法,然后在布局文件直接声明。
TestFragment.java
public class TestFragment extends Fragment {
public static final String TAG = TestFragment.class.getSimpleName();
private String mName = "hahah";
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
//items是Fragment要显示的视图,一个简单的TextView,背景是白色
View view = inflater.inflate(R.layout.items, container);
TextView textView = (TextView) view.findViewById(R.id.text1);
textView.setText(mName);
return view;
}
@Override
public void onPause() {
Log.i(TAG, "onPause");
super.onPause();
}
布局文件
MainActivity
public class TestFragmentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_fragment);
}
}
运行之后显示的图像如下:
按返回键离开该Fragment,在后台可以看到依次打印的语句
2、用代码的形式添加(动态加载)
这种方法比较灵活,在Activity中添加代码如下:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
TestFragment testFragment = TestFragment.newInstance("ha"); transaction.add(R.id.fragment_view,testFragment).commit();
老师说的特别形象,Fragmentmanager是一个校长,而FragmentTransaction则是校长的秘书,校长一般不亲自出面,都是秘书来处理一些如add,remove,replace Fragment的操作。commit(),提交一个事务,只能执行一次。其中fragment_view是一个线性布局,是在Fragment下加的。
布局文件
TestFragment.java
public class TestFragment extends Fragment {
public static final String TAG = TestFragment.class.getSimpleName();
public static final String AGRGUMENT_NAME = "Agrgument_name";
private String mName = "hahah";
public static TestFragment newInstance(String name){
TestFragment testFragment = new TestFragment();
//传递数据
Bundle bundle = new Bundle();
bundle.putString(AGRGUMENT_NAME, name);
testFragment.setArguments(bundle);
return testFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
//接收数据
Bundle bundle = getArguments();
if (bundle != null){
mName = bundle.getString(AGRGUMENT_NAME);
}
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
//container:父控件,false:不和父控件绑定
View view = inflater.inflate(R.layout.items, container, false);
TextView textView = (TextView) view.findViewById(R.id.text1);
textView.setText(mName);
return view;
}
@Override
public void onPause() {
Log.i(TAG, "onPause");
super.onPause();
}
}
在静态加载的时候,View view = inflater.inflate(R.layout.items, container)
,这样写没有问题,但是在动态加载时这样写会有问题;首先看inflate的参数inflate(int resource, ViewGroup root, boolean attachToRoot)
ViewGroup是父控件,后面是是否和父控件绑定。然后看add的操作transaction.add(R.id.fragment_view,testFragment)
,而add(int containerViewId, Fragment fragment)
第一个参数是container的id。所以现在的情况是items是和container绑定在一起,items是container的子控件,而container实际上是fragment_view。要把含有items的Fragment添加到fragment_view中,fragment_view似乎没有同意~~。所以不要这层关系,使attachToRoot为false,这样就行了。
3、Fragment的一些操作
张鸿洋:回退栈的操作,Fragment与Activity的交互,最佳实践
3、Fragment的生命周期
- onAttach():Fragment被添加到Activity中回调。
- onDetach():将该Fragment从Activity中删除替换完成时回调该方法
- onActivityCreate():当Fragment所在的Activity被启动后回调。
三个状态:运行状态,暂停状态,停止状态。
书上的一个小例子,比较有代表性:显示列表内容