托管UI fragment
为托管UI fragment,activity必须做到:
- 在布局中为fragment的视图安排位置;
- 管理fragment实例的生命周期。
fragment的生命周期
托管的两种方式
- 在activity布局中添加fragment
- 在activity代码中添加fragment
我们选择在activity代码中添加UI fragment,但还是要在activity视图层级结构中为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">
</FrameLayout>
创建UI fragment
定义CrimeFragment的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/crime_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/crime_title_hint" />
</LinearLayout>
创建CrimeFragment类
public class CrimeFragment extends Fragment {
}
实现fragment生命周期方法
覆盖Fragment.onCreate(Bundle)方法:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrime = new Crime();
}
需要注意的有:
- Fragment.onCreate(Bundle)是public方法,而Activity.onCreate(Bundle)是protected方法,因为托管fragment的activity要调用它。
- 和activity一样,fragment也可以通过覆盖Fragment.onSaveInstanceState(Bundle)方法保存bundle(如果需要)。
- fragment的视图并没有在Fragment.onCreate(Bundle)方法中生成。我们在Fragment.onCreate(Bundle)方法中配置了fragment实例,但创建和配置fragment视图是以下方法完成的:
/**
* 实例化fragment视图的布局
* @param inflater LayoutInflater
* @param container ViewGroup
* @param savedInstanceState Bundle
* @return
*/
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
/**
* 直接调用LayoutInflater.inflate(int, ViewGroup, boolean)方法生成fragment视图
* @param resId int 布局资源id
* @param root ViewGroup 视图的父视图
* @param attachToRoot boolean 告知布局生成器是否将生成的视图添加给父视图
*/
View view = inflater.inflate(R.layout.fragment_crime, container, false);
return view;
}
在onCreateView(LayoutInflater, ViewGroup, Bundle)方法中,fragment的视图是直接调用LayoutInflater.inflate(int, ViewGroup, boolean)方法并传入布局资源ID生成的,第2个参数是视图的父视图,第3个参数告知布局生成器是否将生成的视图添加给父视图。
关联EditText组件
onCreateView(LayoutInflater, ViewGroup, Bundle)方法也是生成EditText组件并响应用户输入的地方。视图生成后,引用EditText组件并添加监听器:
mTitleField = view.findViewById(R.id.crime_title);
mTitleField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d(TAG, "输入的文本内容:" + s.toString());
mCrime.setTitle(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle)方法几乎等同于Activity.onCreate(Bundle)方法,唯一的区别是fragment需要自己调用View.findViewById(int)方法,而Activity.findViewById(int)方法能够自动调用View.findViewById(int)方法。
添加UI fragment到FragmentManager
FragmentManager类具体管理的是:
- fragment队列
- fragment事务回退栈
在MainActivity类的onCreate(Bundle)方法中获取FragmentManager:
FragmentManager fm = getSupportFragmentManager();
fragment事务
获取FragmentManager之后,获取一个fragment并交由FragmentManager管理:
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = new CrimeFragment();
/**
* 创建一个新的fragment事务,加入一个添加操作,然后提交该事务
*/
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}