一、声明周期
通常情况下只需要重写 onCreateView() 提供自定义界面就行,重写其它生命周期方法第一行都要返回 super 实现。
| onAttach( ) | Fragment与Activity关联时回调,只会调用一次。 |
| onCreate( ) | 创建该Fragment实例时回调,只会回调一次。用于除视图外的初始化,以保障它们在pause或stop状态时仍可用。 |
| onCreateView( ) | 绘制视图时回调,会将显示的View返回,用于视图组件的初始化。不显示视图可返回null。 |
| onActivityCreated( ) | 已弃用。初始化用上面两个。 |
| onStart( ) | 可见时回调。 |
| onResume( ) | 可以交互时回调。 |
| onPause( ) | 失去焦点时回调。可能是可见但无法交互,例如被dialog遮挡。也可能是用户离开,可以做一些数据持久化。 |
| onStop( ) | 完全不可见时回调,可以用来关闭一些资源。 |
| onDestroyView( ) | 当视图被销毁时回调。 |
| onDestroy( ) | 被销毁时回调。 |
| onDetach( ) | 该Fragment从Activity上移除/替换时回调,只会调用一次。 |
二、将Fragment添加到Activity中
Fragment 1.2.0版本官方建议无论使用哪种方式添加,容器都建议使用 FragmentContainerView。
2.1 静态添加(xml)
把Fragment当作View一样使用。
-
编写Fragment布局,继承Fragment重写onCreatedView()设置布局。
-
Activity布局中,通过对 FragmentContainerView 设置 name 引用 Fragment的全类名路径,在Activity代码中 findViewById 去使用。
//Activity布局中
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentLeft"
android:name="com.example.LeftFragment" //指定Fragment的类名
/>
2.2 动态添加(代码)
-
编写Fragment布局,继承Fragment重写onCreatedView()设置布局。
-
Activity布局中,添加 FragmentContainerView 用来占位。在Activity代码中实例化Fragment,通过 FragmentManager 开启 FragmentTransaction 将 Fragment 对象替换到占位容器中。
//Activity布局中
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView" //只是个用来占位的容器
/>
//activity
三、FragmentManager
用来管理Fragment返回栈,每一组操作称为事务 FragmentTransaction,一个事务只能被提交一次,只能再开启后提交。
-
在 Activity 中通过 getSupportFragmentManager( ) 来获取。
-
若是存在 Fragment 中嵌套 Fragment 的场景:
-
在父片段中通过 getChildFragmentManager( ) 来获取子片段的管理器。
-
在子片段中通过 getParentFragmentManager( ) 来获取父片段的管理器。
| FragmentManager | beginTransaction( ) | 开启事务,返回一个FragmentTransaction。 |
| findFragmentById( ) findFragmentByTag( ) | 通过 id 或 tag 获取对应的Fragment。 | |
| popBackStack( ) | 栈顶出栈。 | |
| getBackStackEntryCount( ) | 获取栈内Fragment数目。 | |
| FragmentTransaction | add( ) | 往容器中添加一个Fragment。 |
| remove( ) | 从容器中移除一个Fragment并销毁。 | |
| replace( ) | 用指定的Fragment替换当前显示的(本质先remove再add)。 | |
| hide( ) | 隐藏当前Fragment(设为不可见,不会销毁)。 | |
| show( ) | 显示指定被隐藏的Fragment。 | |
| commit( ) | 提交事务,一个事物只能被提交一次,只能再开启后提交。 | |
| addToBackStack( ) | 将Fragment加入回退栈,按返回键的时候就会退到上一个。 | |
| attach( ) | 只销毁视图不销毁实例,Fragment状态仍旧由FragmentManager维护。 | |
| detach( ) | 重建视图并显示。 |
设置唯一标识
设置后,便可通过 FragmentManager 来获取对应的Fragment。
-
通过 android:id 属性设置唯一id。
-
通过 android:tag 属性设置唯一字符串标识。
-
都为设置,默认为父容器view的id。
四、数据通信
更推荐使用ViewModel。
4.1 Fragment → Fragment
Fragment2 f2 = getActivity().getFragmentManager().findFragmentByTag("f2");
TextView textView = (TextView) getActivity().findViewById(R.id.fragment1_text);
4.2 Fragment → Activity
接口回调,或getActivity()并调用Activity中的方法。
4.3 Activity → Fragment
通过Fragment.setArguments方法向Fragment传递参数值,并且通过Fragment.getArguments方法获取传递的参数值。
MyFragment myFragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putString("DATA",values);//这里的values就是我们要传的值
myFragment.setArguments(bundle);
五、使用
implementation("androidx.fragment:fragment-ktx:1.6.2")
5.1 结合 ViewPager
-
onHiddenChanged(boolean hidden):用 if 对 hidden 进行判断,true不在前端显示了,false在前端显示。
-
setUservisibleHint(boolean isVisibleToUser):fragment结合viewpager时候,FragmentStateAdapter设置为BEHAVIOR_SET_USER_VISIBLE_HINT时候调用,同上。
5.2 结合 RadioGroup
hide()、show() 对 Fragment 生命周期没有任何影。
public class MainActivity extends Activity {
private Fragment mCurrentFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Fragment one = new OneFragment();
final Fragment two = new TwoFragment();
final Fragment three = new ThreeFragment();
//默认显示第一个fragment,一个事物只能提交一次
getFragmentManager().beginTransaction().add(R.id.container,one).commit();
mCurrentFragment = one;
RadioGroup rg = findViewById(R.id.rg);
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){
case R.id.one:
switchContent(one);
break;
case R.id.two:
switchContent(two);
break;
case R.id.three:
switchContent(three);
break;
}
}
});
}
public void switchContent(Fragment fragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (mCurrentFragment != fragment) {
//先判断是否被添加过
if (!fragment.isAdded()) {
transaction.hide(mCurrentFragment).add(R.id.container, fragment).commit(); // 隐藏当前的fragment,添加要显示的fragment
} else {
transaction.hide(mCurrentFragment).show(fragment).commit(); // 隐藏当前的fragment,显示下一个
}
mCurrentFragment = fragment;
}
}
}
5.3 结合 Dialog(DialogFragment)
class Demo : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
inflater.inflate(R.layout.fragment_chat, container, false)
return super.onCreateView(inflater, container, savedInstanceState)
}
}
class DemoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val demo = Demo()
supportFragmentManager
demo.show(supportFragmentManager, "FragmentChat") //显示
demo.dismiss() //隐藏
if (demo.isVisible){} //监听可见
}
}
六、常见问题
6.1 重叠显示
fragment根布局节点设置android:background,除transparent都行。
6.2 点击穿透
fragment根布局节点设置设置android:clickable="true"。
文章详细介绍了Fragment的生命周期,包括onAttach、onCreate、onCreateView等关键方法的调用时机。同时,讲解了如何静态和动态地将Fragment添加到Activity中,以及FragmentManager的使用,如事务处理、添加、移除和替换Fragment。此外,还提到了Fragment之间的数据通信方式和常见问题,如重叠显示及点击穿透的解决方案。
5053

被折叠的 条评论
为什么被折叠?



