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的用法
Android 中,创建 Fragment 有多种常见的方法,以下为你详细介绍: ### 静态创建 Fragment 静态创建 Fragment 是指在布局文件中直接声明 Fragment,这是一种较为简单的方式。步骤如下: 1. **创建 Fragment 类**:继承 `Fragment` 类,重写 `onCreateView` 方法,为 Fragment 提供布局。 ```java import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.fragment.app.Fragment; public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 为 fragment 提供 XML 布局文件 return inflater.inflate(R.layout.fragment_my, container, false); } } ``` 2. **创建 Fragment 布局文件**:在 `res/layout` 目录下创建 `fragment_my.xml` 文件。 ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- 这里可以添加 Fragment 的具体布局 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is a fragment" /> </LinearLayout> ``` 3. **在 Activity 布局文件中添加 Fragment**:在 `activity_main.xml` 中添加 `fragment` 标签。 ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:name="com.example.MyFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> ``` ### 动态创建 Fragment 动态创建 Fragment 允许在运行时添加、替换或移除 Fragment,提供了更高的灵活性。步骤如下: 1. **创建 Fragment 类**:与静态创建相同。 ```java import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.fragment.app.Fragment; public class MyDynamicFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_my_dynamic, container, false); } } ``` 2. **在 Activity 中动态添加 Fragment**:使用 `FragmentManager` 和 `FragmentTransaction` 来添加 Fragment。 ```java import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentTransaction; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 创建 Fragment 实例 MyDynamicFragment fragment = new MyDynamicFragment(); // 获取 FragmentManager FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 添加 Fragment 到布局容器 transaction.add(R.id.fragment_container, fragment); // 提交事务 transaction.commit(); } } ``` 3. **Activity 布局文件**:在 `activity_main.xml` 中添加一个 `FrameLayout` 作为 Fragment 的容器。 ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> ``` ### 使用工厂方法创建 Fragment 使用工厂方法创建 Fragment 可以方便地传递参数给 Fragment。步骤如下: 1. **创建 Fragment 类**:在 Fragment 类中定义一个静态工厂方法。 ```java import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.fragment.app.Fragment; public class ParamFragment extends Fragment { private static final String ARG_PARAM = "param"; private String mParam; public static ParamFragment newInstance(String param) { ParamFragment fragment = new ParamFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM, param); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam = getArguments().getString(ARG_PARAM); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_param, container, false); } } ``` 2. **在 Activity 中使用工厂方法创建 Fragment**: ```java import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentTransaction; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 使用工厂方法创建 Fragment 实例 ParamFragment fragment = ParamFragment.newInstance("Hello, Fragment!"); // 获取 FragmentManager FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 添加 Fragment 到布局容器 transaction.add(R.id.fragment_container, fragment); // 提交事务 transaction.commit(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

子林Android

感谢老板,老板大气!

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

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

打赏作者

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

抵扣说明:

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

余额充值