Fragment的创建

本文详细介绍了在AndroidX环境中创建Fragment的两种方法:通过XML布局文件和通过Java代码动态创建。强调了Fragment与Activity的关系,以及在AndroidX工程中使用Fragment的注意事项,包括添加依赖、使用FragmentManager和FragmentTransaction等关键知识点。

引言

上节我们介绍了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>

注意:

  1. fragment标签内必须声明 android:id或者android:tag 属性,否则会有错
  2. 声明tools:layout=“@layout/example_fragment”,可以在预览视图中看到fragment的预览界面
  3. 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>

注意:

  1. 必须声明 android:id 属性,否则会报错
  2. 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页面

方法二:通过代码动态创建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来获取。

这里我们就涉及到两个重要的类 FragmentTransactionFragmentManager

首先,我们来获取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代码创建、通过代码动态创建
  • 了解了两个重要的类 FragmentTransactionFragmentManager的用法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子林Android

感谢老板,老板大气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值