简单用法
在一个活动中添加两个碎片,并让这两个碎片平分活动空间
先新建一个左侧碎片布局和一个右侧碎片布局
左侧碎片
<?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:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"/>
</LinearLayout>
右侧碎片
<?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:orientation="vertical"
android:background="#00ff00">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="这是文本"/>
</LinearLayout>
然后新建一个LeftFragment类和一个RightFragment类继承Fragment
package com.example.fragmentpractice;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class LeftFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
}
}
package com.example.fragmentpractice;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class RightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
修改activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmentpractice.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment
android:id="@+id/right_fragmgent"
android:name="com.example.fragmentpractice.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
使用了<fragment>添加碎片,需要用android:name
属性来显示指明要添加的碎片类名
动态添加碎片
步骤
- 创建待添加的碎片实例
- 获取FragmentManager,在活动中可直接通过调用getSupportFragmentManager()方法得到
- 开启一个事务,通过调用beginTransaction()方法开启
- 向容器内添加或替换碎片,一般使用replace()方法实现,需要传入容器的id和待添加的碎片实例
- 提交事务,调用commit()方法来完成
代码
新建another_rigth_fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="这是另一个文本"/>
</LinearLayout>
创建AnotherRightFragment(和之前的操作一样)
package com.example.fragmentpractice;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class AnotherRightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.another_right_fragment, container, false);
return view;
}
}
修改activity_main代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmentpractice.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</FrameLayout>
</LinearLayout>
修改MainActivity中的代码
package com.example.fragmentpractice;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
// 主活动类,继承自 AppCompatActivity,并实现 View.OnClickListener 接口
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// 活动创建时调用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 启用 Edge-to-Edge 模式
EdgeToEdge.enable(this);
// 设置活动的布局
setContentView(R.layout.activity_main);
// 找到布局中的按钮
Button button = (Button) findViewById(R.id.button);
// 为按钮设置点击监听器
button.setOnClickListener(this);
// 初始化时替换碎片
replaceFragment(new RightFragment());
}
// 点击事件处理
@Override
public void onClick(View v) {
if (v.getId() == R.id.button) {
// 当按钮被点击时,替换碎片
replaceFragment(new AnotherRightFragment());
}
}
// 替换碎片的方法
private void replaceFragment(Fragment fragment) {
// 获取 FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
// 开始一个新的事务
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 替换指定布局中的碎片
transaction.replace(R.id.right_layout, fragment);
// 提交事务
transaction.commit();
}
}
在碎片中模拟返回栈
在上面的例子中,点击按钮后返回会直接退出,如果想让他返回到上一个界面得模仿类似于栈的效果
只需要给MainActivity中的replaceFragment中添加:
transaction.replace(R.id.right_layout, fragment);
就行了。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.button) {
replaceFragment(new AnotherRightFragment());
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
碎片与活动之间的通信
FragmentManager提供了一个类似于findViewById()的方法,用于从布局文件中获取碎片的实例:
RightFragment rightFragment = (RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_layout);
碎片的生命周期
onAttach():
- 用法:当 Fragment 与 Activity 关联时调用。
- 常用操作:初始化需要与 Activity 交互的组件或回调,确保 Fragment 与其宿主 Activity 之间的通信。
onCreate():
- 用法:Fragment 被创建时调用。
- 常用操作:初始化不与 UI 相关的资源,如创建或恢复数据、启动后台线程等。
onCreateView():
- 用法:为 Fragment 创建视图层次结构时调用。
- 常用操作:通过
LayoutInflater
填充 Fragment 的布局,初始化与视图相关的资源。
onActivityCreated():
- 用法:确保与 Activity 相关的工作已经完成时调用。
- 常用操作:在 Activity 的
onCreate()
方法执行完成后调用,可以在这里与 Activity 交互。
onStart():
- 用法:Fragment 可见时调用。
- 常用操作:注册任何需要在 Fragment 可见时工作的广播接收器或其他组件。
onResume():
- 用法:Fragment 准备与用户交互时调用。
- 常用操作:恢复暂停的 UI 更新或交互。
onPause():
- 用法:Fragment 不再与用户交互时调用。
- 常用操作:暂停与 UI 相关的操作,保存重要数据或状态。
onStop():
- 用法:Fragment 不再可见时调用。
- 常用操作:停止耗时的操作,如动画或播放视频,注销在
onStart()
中注册的广播接收器。
onDestroyView():
- 用法:销毁 Fragment 的视图层次结构时调用。
- 常用操作:清理与视图相关的资源,避免内存泄漏。
onDestroy():
- 用法:销毁 Fragment 时调用。
- 常用操作:清理所有资源,包括后台线程、数据和其他持有的资源。
onDetach():
- 用法:Fragment 与 Activity 解除关联时调用。
- 常用操作:清理与 Activity 相关的资源或回调,确保 Fragment 可以正确地与新的 Activity 关联。
动态加载布局
使用限定符
修改activity_main文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmentpractice.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
只留下一个左侧碎片
在res目录下新建layout-large文件夹,在这个文件夹下新建一个布局,也叫做activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmentpractice.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmentpractice.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
添加方法如下:
使用最小宽度限定符
在res目录下新建layout-sw600dp文件夹,新建activity_main布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmentpractice.LeftFragm25ent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmentpractice.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"/>
</LinearLayout>
当程序运行在屏幕宽度大于等于600dp的设备上,会加载layout-sw600dp/activity_main布局,小于600dp加载默认的layout/activity_main布局
创建Fragment的生命周期
静态创建
- Fragment Constructor、onInflate、onCreate
- Fragment Constructor
- 当Fragment实例化时,调用其构造函数。此时可以进行一些初始设置,但不应涉及视图创建或其他可能耗时的操作。
- onInflate
- 当Fragment需要从布局文件中加载视图时调用。此时可以进行视图的初步配置。该方法在Fragment被附加到Activity之前调用。
- onCreate
- Fragment在创建时调用。此时可以进行非视图相关的初始化工作,比如初始化变量、设置配置等。
- Activity onCreate
- 当Activity首次创建时调用。在这个方法中,通常会进行视图的初始化、设置事件监听器、初始化数据等操作。这是Activity生命周期中非常重要的一个方法。
动态创建
- Activity onCreate
- 同静态创建中描述的一样,Activity在首次创建时调用
onCreate
方法。动态创建Fragment的步骤一般在这里进行,比如通过FragmentManager添加、替换Fragment。
- Fragment Constructor、onCreate
- Fragment Constructor
- 与静态创建类似,动态创建时Fragment实例化时也会调用构造函数进行初始设置。
- onCreate
- Fragment在创建时调用。动态创建时,可以在这里进行Fragment的初始化工作,比如从Activity传递过来的数据进行处理。与静态创建不同的是,这里通常会涉及到从Activity获取数据或传递数据给Activity。
工具
Fragment Transaction
Fragment Transaction是管理和操作Fragments的关键工具。
常用方法
-
add():添加一个Fragment到Activity中。
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.fragment_container, new ExampleFragment()); transaction.commit();
-
replace():替换当前的Fragment。
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, new ExampleFragment()); transaction.addToBackStack(null); // 可选,将事务添加到返回栈 transaction.commit();
-
remove():从Activity中移除一个Fragment。
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container); if (fragment != null) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.remove(fragment); transaction.commit(); }
-
hide():隐藏一个Fragment。
-
show():显示一个隐藏的Fragment。
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.hide(existingFragment); transaction.show(newFragment); transaction.commit();
-
attach():重新附加一个Fragment到UI。
-
detach():从UI中分离一个Fragment。
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.detach(existingFragment); transaction.attach(existingFragment); transaction.commit();
-
addToBackStack():将事务添加到返回栈中,以便用户可以按返回键撤销该事务。
-
commit():提交事务。
// 获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
// 开始一个事务
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 创建一个新的Fragment实例
Fragment fragment = new ExampleFragment();
// 添加Fragment到容器
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null); // 可选,将事务添加到返回栈
fragmentTransaction.commit(); // 提交事务
Fragment Manager
常用方法
-
findFragmentById(int id):通过Fragment的容器视图ID来查找Fragment。
FragmentManager fragmentManager = getSupportFragmentManager(); Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); if (fragment != null) { // 找到的Fragment实例 }
-
findFragmentByTag(String tag):通过Fragment的标签(tag)来查找Fragment。
FragmentManager fragmentManager = getSupportFragmentManager(); Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); if (fragment != null) { // 找到的Fragment实例 }
-
getFragments():获取当前
FragmentManager
中所有的Fragment(API Level 26及以上可用)。FragmentManager fragmentManager = getSupportFragmentManager(); List<Fragment> fragments = fragmentManager.getFragments(); for (Fragment fragment : fragments) { // 处理每个Fragment实例 }
增删查替
Fragment的增删查替是通过FragmentManager
和FragmentTransaction
来实现的
增加
添加一个Fragment到Activity中
-
获取FragmentManager:
FragmentManager fragmentManager = getSupportFragmentManager();
-
开启一个事务:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
添加Fragment:
MyFragment myFragment = new MyFragment(); fragmentTransaction.add(R.id.fragment_container, myFragment);
-
提交事务:
fragmentTransaction.commit();
删除
从Activity中移除一个Fragment
-
获取FragmentManager:
FragmentManager fragmentManager = getSupportFragmentManager();
-
找到要移除的Fragment:
MyFragment myFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_container);
-
开启一个事务:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
移除Fragment:
if (myFragment != null) { fragmentTransaction.remove(myFragment); }
-
提交事务:
fragmentTransaction.commit();
查找
根据ID或标签查找Fragment
-
获取FragmentManager:
FragmentManager fragmentManager = getSupportFragmentManager();
-
根据ID查找:
MyFragment myFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_container);
-
根据标签查找:
MyFragment myFragment = (MyFragment) fragmentManager.findFragmentByTag("MY_FRAGMENT_TAG");
替换
替换Activity中的一个Fragment
-
获取FragmentManager:
FragmentManager fragmentManager = getSupportFragmentManager();
-
开启一个事务:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
-
替换Fragment:
MyNewFragment newFragment = new MyNewFragment(); fragmentTransaction.replace(R.id.fragment_container, newFragment);
-
提交事务:
fragmentTransaction.commit();
Fragment与Activity之间的通信
Activity向Fragment
-
在Activity中设置数据:
使用Fragment的
setArguments
方法来传递数据。在创建Fragment实例时,可以通过Bundle
将数据传递给Fragment。
// 在Activity中
Bundle bundle = new Bundle();
bundle.putString("key", "value");
MyFragment myFragment = new MyFragment();
myFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, myFragment)
.commit();
-
在Fragment中接收数据:
在Fragment的
onCreate
方法中获取传递过来的数据。
// 在Fragment中
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
String value = getArguments().getString("key");
// 使用获取到的数据
}
}
Fragment向Activity
-
定义一个接口:
在Fragment中定义一个接口,Activity实现该接口来接收数据。
// 在Fragment中定义接口
public interface OnFragmentInteractionListener {
void onFragmentInteraction(String data);
}
private OnFragmentInteractionListener mListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
// 使用接口传递数据
public void sendDataToActivity(String data) {
if (mListener != null) {
mListener.onFragmentInteraction(data);
}
}
-
在Activity中实现接口:
实现Fragment定义的接口,在接口方法中处理接收到的数据。
// 在Activity中实现接口
public class MyActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {
@Override
public void onFragmentInteraction(String data) {
// 处理从Fragment接收到的数据
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyFragment myFragment = new MyFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, myFragment)
.commit();
}
}
Fragment之间的数据传递
Fragment之间的通信可以通过它们共同的Activity来实现。一个Fragment将数据传递给Activity,然后Activity将数据传递给另一个Fragment。
1.Fragment A 向 Activity 传递数据
使用上面描述的Fragment向Activity传递数据的方法。
2.Activity 接收数据并传递给 Fragment B
在Activity中接收数据:
@Override
public void onFragmentInteraction(String data) {
FragmentB fragmentB = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.fragment_b_container);
if (fragmentB != null) {
fragmentB.updateData(data);
}
}
在Fragment B中定义方法来接收数据:
// 在Fragment B中
public void updateData(String data) {
// 更新Fragment B中的数据
}
已经到底啦!