Fragment

仅用于个人学习使用, 对大多数知识点进行了总结, 欢迎大家!

同 Activity 一样, Fragment 要有自己的布局文件 (无需在 AndroidManifest.xml 中注册)

Fragment 接近 view, 是帮助开发者封装view组合的工具类,你也可以把它理解为带有生命周期的Android提供的可自主定义布局的view容器. (子 Activity)

Fragment 关心更多的是view的拆分和组合 (适配手机和平板横竖屏)

创建

 ​
import android.os.Bundle;
 import androidx.fragment.app.Fragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 ​
 public class BlankFragment extends Fragment {
     private static final String ARG_PARAM1 = "param1";
     private static final String ARG_PARAM2 = "param2";
 ​
     public BlankFragment() {
         // Required empty public constructor
     }
 ​
     public static BlankFragment newInstance(String param1, String param2) {
         BlankFragment fragment = new BlankFragment();
         Bundle args = new Bundle();
         args.putString(ARG_PARAM1, param1);
         args.putString(ARG_PARAM2, param2);
         fragment.setArguments(args);
         return fragment;
     }
 ​
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
     }
 ​
     // 在 onCreateView() 中加载布局
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
         // Inflate the layout for this fragment
         return inflater.inflate(R.layout.fragment_blank, container, false);
     }
 }
 

静态创建

 1. 编写 fragment 的类: BlankFragment
 2. 在 activity 的布局文件中声明 <FragmentContainerView/> (代替 <fragment/> )
 <FragmentContainerView
     android:id="@+id/blankFragment"
     android:name="com.example.app.BlankFragment" <!--指定 fragment 的路径 -->
 />
 3. 创建 fragment_blank.xml

FragmentContainerView 位于androidx.fragment.app 包下,是专门为 Fragment 设计的自定义布局。它扩展了 FrameLayout,所以它可以可靠地处理Fragment事务,并且它还有其他功能来协调 Fragment 行为。FragmentContainerView 应该被用作 fragment 的容器,通常在一个 activity 的 xml 布局中设置

FragmentContainerView 只允许由 Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) 返回的 view。试图添加任何其他视图将导致 IllegalStateException。

动态创建 Fragment

FragmentActivity 已经被淘汰了, 用 Activity 就行

不在 activity 的布局文件中声明 <FragmentContainerView/> , 而是设置一个 view(不一定是 FragmentContainerView) 等待填充 fragment

 BlankFragment fragment = BlankFragment.newInstance(param1, param2);
 FragmentManager mFragmentManager = getSupportFragmentManager(); // 通过管理器处理 Fragment 事务
 ​
 // 事务需要开启和提交 (Fragment的动态添加)
 FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
 ​
 // 该fragment.getid()获取的是activity_main.xml中的fragment的容器的id,即R.id.xxx,
 // 因此没有通过 fragmentTransaction.add 加入的fragment是没有id的
 Log.d(TAG, "replaceFragment: " + fragment.getId());
 ​
 fragmentTransaction.replace(R.id.linear, fragment); // 第一个参数: 容器 view 的 id (建议用 FrameLayout)
 fragmentTransaction.addToBackStack(null); // 一般为 null (返回栈) (返回栈为空时才算真正退出)
 ​
 // 事务提交
 fragmentTransaction.commit(); // 安排一个针对该事务的提交。提交并没有立刻发生,会安排到在主线程下次准备好的时候来执行
 // 一个 fragmentTransaction 只能提交一次事务,因此要多次提交需要多个 fragmentTransaction
 ​
 链式调用:
 FragmentManager fragmentManager = getSupportFragmentManager();
 fragmentManager.beginTransaction()
     .replace(R.id.fragment_container, ExampleFragment.class, null)
     .setReorderingAllowed(true) //可优化事务中涉及的 Fragment 的状态变化,以使动画和过渡正常运行
     .addToBackStack("name") // name can be null
     .commit(); // 注意, commit() 是带延时的, 如果刚 commit() 就打算获取会为null的
 

FragmentContainerView

FragmentContainerView 位于androidx.fragment.app包下面,是专门为Fragment设计的自定义布局。它扩展了FrameLayout,所以它可以可靠地处理Fragment事务,并且它还有其他功能来协调Fragment行为。FragmentContainerView应该被用作fragment的容器,通常在一个activity的xml布局中设置,例如:

  <androidx.fragment.app.FragmentContainerView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/fragment_container_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
  </androidx.fragment.app.FragmentContainerView>

FragmentContainerView也可以通过使用android:name属性来添加一个Fragment。FragmentContainerView将执行一次操作:

  • 创建Fragment的新实例

  • 调用Fragment.onInflate(Context, AttributeSet, Bundle)

  • 执行FragmentTransaction将Fragment添加到适当的FragmentManager

可以选择包括 android:tag, 它允许你使用FragmentManager.findFragmentByTag(String)来检索添加的Fragment。

  <androidx.fragment.app.FragmentContainerView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/fragment_container_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:name="com.example.MyFragment"
     android:tag="my_tag">
  </androidx.fragment.app.FragmentContainerView>

FragmentContainerView不应该被用作Fragment用例之外的其他 viewgroup (FrameLayout, LinearLayout等)的替代。

FragmentContainerView只允许由Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle)返回的view。试图添加任何其他视图将导致IllegalStateException。

对于大于17的api, FragmentContainerView禁用布局动画和transitions。否则,动画应该通过FragmentTransaction.setCustomAnimations(int, int, int, int)完成。如果animateLayoutChanges被设置为true或setLayoutTransition(LayoutTransition)被直接调用,将抛出UnsupportedOperationException。

在FragmentContainerView中,使用exit动画的片段在所有其他动画之前绘制。这确保了退出片段不会出现在视图的顶部。

FragmentTransaction

常用方法:

 add(int containerViewId, Fragment fragment, String tag) // 向Activity state中添加一个Fragment
     // add方法 : 参数 containerViewId 一般会传 Activity 中某个视图容器的 id. 如果 containerViewId 传 0,则这个 Fragment 不会被放置在一个容器中 
     // (不要认为 Fragment 没添加进来,只是我们添加了一个没有视图的 Fragment,这个Fragment 可以用来做一些类似 于service 的后台工作)
     // Tag: Optional tag name for the fragment, to later retrieve the fragment with FragmentManager.findFragmentByTag(String)
     
 remove(Fragment fragment) // 移除一个已经存在的Fragment
     
 replace(int containerViewId, Fragment fragment) // 方法作用:类似于先 remove 掉视图容器所有的 Fragment,再add一个想要添加的 Fragment (当前视图为空时类似于 add)(会使fragment初始化, 有更优解(hide & show))

获得 Fragment 依附的 activity

 getActivity();
 /**
 返回一个和此fragment绑定的FragmentActivity或者其子类的实例。
 相反,如果此fragment绑定的是一个context的话,可能会返回null。
 因为getActivity()大部分都是在fragment中使用到,而fragment需要依赖于activity,
 所有我们在fragment里头需要做一些动作,比如启动一个activity,
 就需要拿到activity对象才可以启动,而fragment对象是没有startActivity()方法的。*/
 final public FragmentActivity getActivity() {
     return mHost == null ? null : (FragmentActivity) mHost.getActivity();
 }

获取 Fragment

访问 FragmentManager

在 Activity 中访问

每个及其子类(如 AppCompatActivity) 都可以通过 getSupportFragmentManager() 方法访问 FragmentManager

在 Fragment 中访问

Fragment 也能够托管一个或多个子 Fragment。在 Fragment 内,您可以通过 getChildFragmentManager() 获取对管理 Fragment 子级的 FragmentManager 的引用。如果您需要访问其宿主 FragmentManager,可以使用 getParentFragmentManager()

另外: 只要是继承 FragmentActivity 或者 FragmentActivity 本身,都可通过 getSupportFragmentManager()方法获取到 FragmentManager(后面简称 FM)

若是 Fragment 嵌套 Fragment 的情况,父 Fragment 可通过 getChildFragmentManager() 方法获取 FM 来管理子 Fragment,同样,子 Fragment 也可通过 getParentFragmentManager() 来获取 FM

 1. 通过 FragmentContainerView, 无论是静态还是动态生成的(其实都利用 FragmentTransaction 进行注册)
 2. FragmentManager (getParentFragmentManager() & getSupportFragmentManager()), 为单例模式. 
 3. getChildFragmentManager() 获取的 FragmentManager,分别管理不同的分支, 彼此不相干

获取Fragment

  1. 通过动态注册的, 可通过容器(androidx.fragment.app.FragmentContainerView)的 Id 来获取

  • getParentFragmentManager().findFragmentById(Fragment的容器的id);

  1. 注册 Tag 的, 无论动态还是静态, 都可以通过 Tag 获取

  • getParentFragmentManager().findFragmentByTag("tag");

  1. FragmentManager宿主环境 FragmentManager宿主环境指的是其管理类,通常在Activity中通过接口getSupportFragmentManager或者getFragmentManager获得FragmentManager对象, 可以认为Activity是FragmentManager的宿主环境类.FragmentManager宿主环境类状态变化时(如onStart, onResume, onStop等回调),FragmentManager的状态也随之更新(FragmentManager类有一个成员变量mCurState来记录当前状态),同时会同步其管理的所有Fragment的状态. 从用户的角度来看, FragmentManager的宿主环境类管理了一系列Fragment,并且Fragment随着FragmentMannager的宿主环境类的状态变化而变化.

  2. 当前级和向上一级 fragment 由 getParentFragmentManager() 管理, 子级 fragment 由 getChildFragmentManager() 管理

  3. 一个 fragment 树中, 每一级都有唯一的 FragmentManager 管理. (不同 Activity 对应不同的 fragment 树)

举例:

Activity1
getSupportFragmentManager(): FragmentManager{59e006d in HostCallbacks{9b594a2}}}
BlankFragment1BlankFragment2
getParentFragmentManager(): FragmentManager{59e006d in HostCallbacks{9b594a2}}} getChildFragmentManager(): FragmentManager{7fc58ee in BlankFragment1{f9e918f}}}getParentFragmentManager(): FragmentManager{59e006d in HostCallbacks{9b594a2}}} getChildFragmentManager(): FragmentManager{f527e08 in BlankFragment2{2f6e084}}}
ChildFragment1ChildFragment2
getParentFragmentManager(): FragmentManager{7fc58ee in BlankFragment1{f9e918f}}} getChildFragmentManager(): FragmentManager{2ccdedd in ChildFragment1{a77bc1c}}}getParentFragmentManager(): FragmentManager{f527e08 in BlankFragment2{2f6e084}}} getChildFragmentManager(): FragmentManager{7bd8bd9 in ChildFragment2{ab649a1}}}

优雅地动态添加

 getSupportFragmentManager().beginTransaction()
     .setReorderingAllowed(true) // 不要省略
     .add(R.id.fragment_container_view, ExampleFragment.class, null)
     .addToBackStack(null)
     .commit();
 // 如果添加fragment时使用了 .addToBackStack(null),会将Fragment添加到回退栈中, 此时点击back键,回调Activity的onBackPressed()函数会把当前展示的fragment弹出回退栈 (要用栈管理就都用栈,要么都不入栈)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Android中,可以使用FragmentManager来管理Fragment的跳转。具体步骤如下: 1. 获取FragmentManager对象: FragmentManager fragmentManager = getSupportFragmentManager(); 2. 开始Fragment事务: FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 3. 创建要跳转的Fragment对象: MyFragment myFragment = new MyFragment(); 4. 调用FragmentTransaction的replace方法,将当前Fragment替换为要跳转的FragmentfragmentTransaction.replace(R.id.container, myFragment); 5. 调用FragmentTransaction的commit方法,提交事务: fragmentTransaction.commit(); 其中,R.id.container是一个FrameLayout,用于显示Fragment的布局容器。 ### 回答2: 在Android中,使用Fragment的一个常见的需求是在一个Fragment中点击某个按钮或者view后跳转到另一个Fragment,也就是所谓的Fragment跳转Fragment。 在实现这个需求之前,需要先明确一些基本概念。在Android中,使用Fragment的最基本的方式是使用FragmentTransaction来进行添加、移除、替换、隐藏等操作。当一个新的Fragment需要被展示时,也就是所谓的Fragment跳转Fragment时,我们需要使用FragmentTransaction来进行以下步骤: 1. 创建要跳转的Fragment实例。 2. 使用FragmentManager获取FragmentTransaction实例。 3. 调用FragmentTransaction的替换方法(replace)来将当前Fragment替换为要跳转的Fragment。 4. 添加到回退栈(addToBackStack)中。 5. 调用FragmentTransaction的提交方法(commit)来提交这一操作。 示例代码如下: ``` FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, new MyFragment()); transaction.addToBackStack(null); transaction.commit(); ``` 在这段代码中,我们使用了SupportFragmentManager来获取了一个FragmentTransaction对象,并将其替换为了新的Fragment,并将其添加到回退栈中。最后,调用了提交方法来提交这一操作。 需要注意的是,在跳转Fragment时,我们也可以传递一些数据给新的Fragment,例如某些参数、对象等。我们可以使用Bundle将这些数据打包传递给新的Fragment。在新的Fragment中,我们可以使用getArguments()方法获取这些数据。 总体来说,Fragment跳转FragmentAndroid中常见的一种场景,使用FragmentTransaction进行操作可以轻松地实现这一需求。在进行操作时,需要注意保存当前状态并添加到回退栈中,以便用户可以使用返回按钮返回上一个Fragment。 ### 回答3: Fragment 跳转 Fragment 是指在一个 Fragment 中通过代码的方式启动另一个 Fragment。在实际开发中,这种方式常常被用于实现页面之间的跳转或者数据的传递等操作。 在 Android 中,Fragment 跳转 Fragment 有多种方式,其中最常用的方式是使用 FragmentManager 开启一个新的 Fragment,具体流程如下: 1. 首先需要获取到 FragmentManager 对象,可以通过 getActivity().getSupportFragmentManager() 方法获取当前 Fragment 所在的 Activity 的 FragmentManager 对象。 2. 创建一个新的 Fragment 对象,这个对象可以在 FragmentManager 中进行管理,在后面我们会用到。 3. 随着 Fragment 的增多,一个问题也就显现出来,如何在父 Fragment 中实现多个 Fragment 之间的切换?这个时候可以选择使用 FragmentTransaction 对象,通过 add()、replace() 等方法实现对 Fragment 的增删操作。 代码实现如下: // 获取 FragmentManager 对象 FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); // 创建一个新的 Fragment 对象 SecondFragment fragment = new SecondFragment(); // 开启一个事务 FragmentTransaction transaction = fragmentManager.beginTransaction(); // 通过 add()、replace() 等方法实现对 Fragment 的增删操作 transaction.replace(R.id.container, fragment); transaction.addToBackStack(null); // 提交事务,启动 Fragment transaction.commit(); 在这段代码中,R.id.container 表示存放 Fragment 的容器,这个可以根据实际需要进行修改。 同时,我们还需要注意 addToBackStack() 方法的使用。这个方法可以将当前 Fragment 加入 BackStack 中,也就是将当前 Fragment 放入到一个栈中,方便用户在返回时直接返回到上一个 Fragment。需要注意的是,如果不使用 addToBackStack() 方法,则用户在返回时会直接退出当前 Activity。 总之,Fragment 跳转 Fragment 功能十分重要,能够帮助开发者实现程序中各种场景的操作。通过 Fragment 嵌套来实现页面嵌套,通过 Fragment 之间的跳转来实现页面之间的切换,是 Android 开发中不可或缺的一部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值