参考:
33.3-Fragment的创建-静态创建2_哔哩哔哩_bilibili
Fragment的创建_从现有代码创建foutran-CSDN博客
【Android】Fragment的基本用法、Fragment和活动间的通信、Fragment的生命周期、动态加载布局的技巧_android fragment-CSDN博客
文章目录
Fragment的静态创建
- 创建一个Fragment
- 布局代码中用一个容器承接并绑定
- fragment标签
- FragmentContainView标签
先创建一个导航界面
先创建一个带按钮的空白界面吧!
然后创建一个Fragment
创建一个Activity用来承载Fragment
由于Fragment依赖于Activity存在,故而我们首先需要创建一个Activity用来承载fragment。
Be like:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<fragment
android:id="@+id/my_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.fragment.fragment.StaticFragment1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
做到这一步,还并没有感觉到Fragment跟普通的Activity有什么区别,我们给fragment加点控件再看看。
<?xml version="1.0" encoding="utf-8"?>
<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"
android:orientation="vertical"
tools:context=".fragment.StaticFragment1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请给我的App打分吧!"
android:textSize="20sp"
android:id="@+id/tv_like"/>
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_notlike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="不喜欢"/>
<RadioButton
android:id="@+id/rb_verynotlike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="特别不喜欢"/>
</RadioGroup>
</LinearLayout>
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
在Fragment中完成事件的绑定
先做成这样,而后去fragment的.java文件中进行控件的绑定。
fragment的绑定其实与Activity中的绑定比较相似,在Activity中的绑定往往是:
在这里写或者直接用ViewBinding工具。
而在fragment中:
可以看到上方的onCreateView函数负责引入布局,而控件的绑定需要我们重写onViewCreated函数,大概像这样:(顺便把事件监听也写了)
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
tvlike = view.findViewById(R.id.tv_like);
rbDislike = view.findViewById(R.id.rb_notlike);
rbVeryDislike = view.findViewById(R.id.rb_verynotlike);
rbStar = view.findViewById(R.id.rating_bar);
rbDislike.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
tvlike.setText("我不喜欢这个");
}
}
});
rbVeryDislike.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
tvlike.setText("我非常不喜欢这个");
}
}
});
rbStar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
if (fromUser) {
Toast.makeText(getActivity(), "你给我评了"+rating, Toast.LENGTH_SHORT).show();
}
}
});
}
注:这里也可以用ViewBinding进行绑定,笔者为了演示方便故而直接用的findViewById。
此时点击运行,就能正常使用啦!
在Activity中预览Fragment
我们再切换回创建的用于承载Fragment的Activity中。
可以看到,虽然能运行,但是预览界面中我们是看不到的。
只需要加上这句话即可
可以预览界面了。
注意与额外事项
关于FragmentContainerView标签
谷歌目前更加推荐开发者使用这个标签,专为Fragment设计,添加了一些关于生命周期销毁以及恢复的优化。
注意事项
- Fragment标签必须声明 android:id 属性,否则会出问题
- name属性可以用class属性代替
Fragment的动态创建
- 创建一个Fragment
- 布局代码中用一个容器来承接,但不直接绑定
- 在代码中用FragmentManager、FragmentTransaction添加Fragment到容器中
在Activity中设置一个容器
在Activity的代码中,设置动态创建Fragment的代码
public class DynamicFragmentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_dynamic_fragment);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
if(savedInstanceState == null){
FragmentManager supportFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container_view_tag, ExampleFragment1.class,null)
.setReorderingAllowed(true)
.addToBackStack(null)
.commit();
}
}
}
if(savedInstanceState == null){
:- 这是一个条件判断语句。
savedInstanceState
是一个Bundle对象,通常用于保存Fragment的实例状态。如果savedInstanceState
为null,说明Fragment是首次创建,而不是从保存的状态中恢复。
- 这是一个条件判断语句。
FragmentManager supportFragmentManager = getSupportFragmentManager();
:- 获取当前Activity的FragmentManager实例。FragmentManager用于管理Fragment的生命周期和事务。
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
:- 创建一个Fragment事务(FragmentTransaction),用于执行添加、替换、删除Fragment等操作。
fragmentTransaction.add(R.id.fragment_container_view_tag, ExampleFragment1.class,null)
:- 向FragmentManager中添加一个新的Fragment。
R.id.fragment_container_view_tag
是Fragment要添加到的容器视图的ID。ExampleFragment1.class
是要添加的Fragment的类。null
是用于标识Fragment的标签,这里传入null表示不使用标签。
- 向FragmentManager中添加一个新的Fragment。
.setReorderingAllowed(true)
:- 允许Fragment事务中的视图重新排序。这通常用于动画效果,使Fragment的添加或替换看起来更平滑。
.addToBackStack(null)
:- 将这个Fragment事务添加到后退栈中。用户可以通过按后退键来返回到这个Fragment事务之前的状态。传入null表示不使用标签。
.commit();
:- 提交Fragment事务。这会触发Fragment的生命周期方法,如
onCreate
、onStart
等,并最终将Fragment显示在界面上。
- 提交Fragment事务。这会触发Fragment的生命周期方法,如
两种方式创建Fragment的生命周期的区别
Fragment生命周期
Fragment
的生命周期主要分为以下几个阶段:
- onAttach(Context context):
- 调用时机:当
Fragment
被附加到Activity
时。 - 作用:可以在这里获取
Activity
的引用。
- 调用时机:当
- onCreate(Bundle savedInstanceState):
- 调用时机:在
Fragment
被创建时,通常在Activity
的onCreate
之后。 - 作用:进行初始化操作,如设置布局和初始化数据。
- 调用时机:在
- onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState):
- 调用时机:在
Fragment
的视图被创建时。 - 作用:加载和返回
Fragment
的视图。
- 调用时机:在
- onViewCreated(View view, Bundle savedInstanceState):
- 调用时机:在
Fragment
的视图创建后,但在onStart
之前。 - 作用:可以在视图已经创建但还未显示时进行一些操作。
- 调用时机:在
- onActivityCreated(Bundle savedInstanceState):
- 调用时机:在
Activity
的onCreate
方法调用后。 - 作用:可以访问
Activity
的初始化数据。
- 调用时机:在
- onStart():
- 调用时机:当
Fragment
开始与用户交互时。 - 作用:开始动画或处理用户输入。
- 调用时机:当
- onResume():
- 调用时机:当
Fragment
可见并与用户交互时。 - 作用:恢复之前暂停的操作。
- 调用时机:当
- onPause():
- 调用时机:当
Fragment
不再与用户交互时。 - 作用:暂停动画或停止处理用户输入。
- 调用时机:当
- onStop():
- 调用时机:当
Fragment
不再可见时。 - 作用:释放资源。
- 调用时机:当
- onDestroyView():
- 调用时机:当
Fragment
的视图被销毁时。 - 作用:销毁视图相关的资源。
- 调用时机:当
- onDestroy():
- 调用时机:当
Fragment
被销毁时。 - 作用:释放所有资源。
- 调用时机:当
- onDetach():
- 调用时机:当
Fragment
从Activity
中分离时。 - 作用:清理与
Activity
的关联。
- 调用时机:当
静态创建与动态创建的区别
- 静态创建:
- 静态创建通常在
Activity
的布局文件中定义Fragment
。 - 生命周期方法按顺序调用,从
onAttach
到onDetach
。 - 视图创建和销毁的时机与
Activity
的生命周期一致。
- 静态创建通常在
- 动态创建:
- 动态创建是在代码中通过
FragmentManager
添加或替换Fragment
。 - 生命周期方法的调用顺序可能会有所不同,例如:
Fragment
在Activity
的onCreate
之前被创建。Fragment
的视图在Activity
的视图创建之后才创建。
Activity的布局文件中定义
Fragment`。
- 生命周期方法按顺序调用,从
onAttach
到onDetach
。 - 视图创建和销毁的时机与
Activity
的生命周期一致。
- 动态创建是在代码中通过
- 动态创建:
- 动态创建是在代码中通过
FragmentManager
添加或替换Fragment
。 - 生命周期方法的调用顺序可能会有所不同,例如:
Fragment
在Activity
的onCreate
之前被创建。Fragment
的视图在Activity
的视图创建之后才创建。
- 动态创建的
Fragment
可以被添加到不同的Activity
中,并且可以多次创建和销毁。
- 动态创建是在代码中通过