引言
上节我们介绍了Fragment的相关概念,对Fragment是什么,为什么需要Fragment,Fragment与Activity的关系有了初步的认识。本小节,我们就来学习一下如何创建Fragment。
首先需要明确的是,Fragment是依附于Activity而存在的,它是Activity页面上的一部分,我们可以在Activity上对Fragment做添加、移除、替换、隐藏、显示等操作。
添加依赖
Fragment有好几种版本,最古老的是存在于android.app.Fragment包里的Fragment,后来在支持库Support包里也出现了具备兼容性的Fragment,即android.support.v4.app.Fragment ,目前Android已经普遍使用了AndroidX来替代Android support库来实现兼容性,推荐大家使用AndroidX里的Fragment,即androidx.fragment.app.Fragment
- 注意观察自己代码文件最上方导入的包是否为 import androidx.fragment.app.Fragment;
- 确保工程中的所有的Fragment及相关类来自同一种包。(千万不要三种Fragment共存,混用)
我们这里主要以AndroidX里的Fragment作为演示(首先要确保你的工程是AndroidX工程)
build.gradle(app Module)里的dependencies节点里添加
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
// 或者也可以用下面这个
// implementation "androidx.fragment:fragment:1.3.0"
}
创建Fragment
有两种方式:
- 通过xml代码创建
- 通过Java代码动态创建
方法一:通过xml代码创建Fragment
首先,需要定义一个自己的Fragment类
例如,ExampleFragment
import androidx.fragment.app.Fragment;
class ExampleFragment extends Fragment {
public ExampleFragment() {
super(R.layout.example_fragment);
}
}
可以看出Fragment也是需要布局文件的,这里随便写一个:
example_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是Fragment页面"
android:textSize="30sp" />
</LinearLayout>
然后,在MainActivity的对应xml布局代码里用一个容器承接它,这里有两种方式:fragment标签和FragmentContainerView标签。这里推荐用fragment标签
- 用fragment标签承接的activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/fragment"
android:name="com.example.fragmenttest2.ExampleFragment"
tools:layout="@layout/example_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
注意:
- fragment标签内必须声明 android:id或者android:tag 属性,否则会有错
- 声明tools:layout=“@layout/example_fragment”,可以在预览视图中看到fragment的预览界面
- android:name属性也可以用class代替,即class=“com.example.fragmenttest2.ExampleFragment”
- 用 FragmentContainerView 标签承接的activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:name="com.example.fragmenttest2.ExampleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
注意:
- 必须声明 android:id 属性,否则会报错
- android:name属性也可以用class代替,即class=“com.example.fragmenttest2.ExampleFragment”
上面代码里的 android:name="com.example.fragmenttest2.ExampleFragment",表示指向了我们上面定义的ExampleFragment 。注意,这里需要是全路径的引用(包名+类名)。
当布局文件activity_main加载后,ExampleFragment 就被初始化了,并且会调用其onInflate方法。
最后附上MainActivity的代码:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
运行看下效果:

方法二:通过代码动态创建Fragment
上面通过xml代码创建Fragment的方式虽然简单,但不常用。
实际应用中,我们更多的是通过Java代码动态创建Fragment。
首先,我们仍然需要定义好自己的Fragment,如ExampleFragment (同上,不再赘述)。仍然也需要盛放Fragment的容器控件:FragmentContainerView,但我们不通过 android:name="com.example.fragmenttest2.ExampleFragment"将ExampleFragment 放入其中,而是等会儿在代码中动态的添加进去。
在动态创建添加Fragment时,以往普遍用了一般的容器控件来承接,如FrameLayout、RelativeLayout等。
虽然这些容器也能用,但这里推荐用FragmentContainerView,这是官方推荐的专门用来盛放Fragment的容器控件,它针对Fragment的需要做了一些特定的修复。
为了和上面MainActivity等文件区分,这里分别拷贝了一份文件,命名为MainActivity2、activity_main2等,下面的带2的命名都是如此。
activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity2">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
然后,在对应的MainActivity2中把Fragment添加进去。我们需要使用一个叫FragmentTransaction的类,它可以对Fragment做添加、移除、替换等操作,并且可以组合多个操作,批量执行。而FragmentTransaction需要用FragmentManager来获取。
这里我们就涉及到两个重要的类 FragmentTransaction 和 FragmentManager
首先,我们来获取FragmentManager。在FragmentActivity中执行下面代码:
FragmentManager fragmentManager = getSupportFragmentManager();
- 只有在FragmentActivity及其子类(如,AppCompatActivity)下才有getSupportFragmentManager这个方法。
- 普通的Activity是没有该方法的,它有的是getFragmentManager。顾名思义,它获取的是非兼容的Fragment。而我们这里用的是AndroidX里面的,具有兼容性的Fragment,自然需要同样具有兼容性的FragmentManager,即需要用getSupportFragmentManager
然后,用FragmentManager来获取FragmentTransaction :
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
这样我们就拿到了这两个关键的类。
接下来使用fragmentTransaction ,将Fragment添加到容器里即可:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container_view2, ExampleFragment.class, null);
fragmentTransaction.commit();
这里的add方法传入了三个参数:R.id.fragment_container_view2, ExampleFragment.class, null
- 第一个是盛放Fragment的容器控件id,
- 第二个是目标Fragment对应的Class类
- 第三个是用来相Fragment传递的参数,类型为Bundle。传null的话,就是没传参数
注意,以往我们见到的add Fragment的方法是这样的:
fragmentTransaction.add(R.id.fragment_container_view2, new ExampleFragment());,两个参数,并且传进去的是一个对象。
而上面三个参数是最新的写法,也是强烈推荐的写法,传进去对应类的Class,这样能保证从保存的状态中恢复Fragment的时候使用的是同样的机制。
完整的MainActivity2代码如下:
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.add(R.id.fragment_container_view2, ExampleFragment.class, null)
.commit();
}
}
}
- 上面代码采用了链式写法,更加简洁。
- 并且多了
if (savedInstanceState == null)的判断,目的是保证Fragment只添加一次。因为有特殊情况:当屏幕配置变化时(如屏幕旋转),Activity会重建,并且Fragment会自动从savedInstanceState 里被恢复。如果我们不加那个判断,那么Fragment又会被添加一次了。- 多加了一行
setReorderingAllowed(true),这个是官方推荐加的,为了保证fragmentTransaction 在进行多个执行出现回退时能够有合适的表现。
最终,运行的效果和方法一所示的图片一样。
总结
本小节我们学到了以下内容
- 了解了Fragment的几种版本,对应版本需要添加的依赖
- 掌握了创建Frament的两种方式:通过xml代码创建、通过代码动态创建
- 了解了两个重要的类
FragmentTransaction和FragmentManager的用法
本文详细介绍了在AndroidX环境中创建Fragment的两种方法:通过XML布局文件和通过Java代码动态创建。强调了Fragment与Activity的关系,以及在AndroidX工程中使用Fragment的注意事项,包括添加依赖、使用FragmentManager和FragmentTransaction等关键知识点。
1171

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



