android - 为什么 detach() 对 FragmentTransaction 不起作用,而 remove() 却可以?

标签 android android-fragments

我正在开发 TabHost其选项卡关联了 Fragment (每个选项卡不同)。其中每一个 Fragment s 内部有另一个 Fragment 的实例这是一个登录栏,有两种状态:登录或未登录。

注销示例

Logged out

登录示例

Logged in

在布局方面,每个状态都关联了 View (TextView 表示未登录的情况,LinearLayout 表示登录的情况),因此如果其中之一是 VISIBLE ,另一个是GONE 。根据选项卡内容,这是其中之一的代码示例 ( firsttab.xml ):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:ads="http://schemas.android.com/apk/lib/com.google.android.gms.ads"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#0000FF"
  android:orientation="vertical">

  <!-- That's the login bar -->
  <fragment 
    android:id="@+id/firsttab_loginrow"
    class="com.mydomain.myproject.LoginRowFragment"
    android:tag="1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

  <LinearLayout
    android:id="@+id/firsttab_content"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:gravity="center"
    android:orientation="horizontal">
  </LinearLayout>
</LinearLayout>

内部 fragment ( com.mydomain.myproject.LoginRowFragment )是这样定义的:

<!-- If the user is not logged in -->
<TextView
   android:id="@+id/identification_nologin"
   android:layout_width="wrap_content"
   android:layout_height="match_parent"
   android:textColor="#FFFFFF" />

<!-- if the user is logged in -->
<LinearLayout
   android:id="@+id/identification_didlogin"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:orientation="horizontal" >

   ...      
</LinearLayout>

一般架构如下所示:

Schema

当我通过 attach() 处理选项卡更改事件时,问题就出现了。 ing 或 detach()联系通讯家长Fragment (在本例中为 firsttab.xml )。在附加/分离父级之前,我尝试 detach()登录Fragment (内部的),但它不会触发 onDetach()打回来。当 attach() 时也会发生同样的情况ing。奇怪的是,如果我替换 .detach().remove() ,它工作得很好。

@Override
public void onTabChanged(final String tag) {
  final TabInfo newTab = mTabInfo.get(tag);

  if (lastTab != newTab) {

    final FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
    if ((lastTab != null) && (lastTab.getFragment() != null)) {

      // This is where it fails detaching. tabInfo is just a structure where I store some data
      // about the tabs to handle them. If I use remove() instead of the next detach() on loginFrag,
      // the onAttach()/onDetach() callbacks are not called. I'm quite sure everything is ok, loginFrag
      // is not null, it's actually the Fragment that should be detached, etc.

      final Fragment loginFrag = (Fragment) lastTab.getFragment().getActivity().getSupportFragmentManager().findFragmentById(lastTab.getLoginFragId());
      ft.detach(loginFrag);

      ft.detach(lastTab.getFragment());
    }

    if (newTab != null) {
      if (newTab.getFragment() == null) {
        final TabFragmentInflater tabInf = new TabFragmentInflater();
        newTab.setFragment(Fragment.instantiate(this, tabInf.getClass().getName(), newTab.getArgs()));
        ft.add(R.id.realtabcontent, newTab.getFragment(), newTab.getTag());
      }
      else
        ft.attach(newTab.getFragment());
    }

    ft.commit();
    this.getSupportFragmentManager().executePendingTransactions();

    lastTab = newTab;
  }
}

所以问题如下:

为什么 onAttach()/onDetach() LoginRowFragment 中不会触发回调使用 .attach() 时的类或.detach()对他们来说,但如果我使用 .add() 就会被解雇或.remove()分别?

最佳答案

您无法删除已在布局 XML 文件中声明的 Fragment 实例(按设计)

当您使用 FragmentTransactions 时,您正在操作包含 Fragment 布局的 ViewGroup。

当您在布局中声明 fragment/类时,它是 View 层次结构的一部分,因此您无法删除它。

但是,您可以将新 fragment 添加到该布局中,因为它将充当容器。

尝试更改您的布局:

    <fragment 
      android:id="@+id/firsttab_loginrow"
      class="com.mydomain.myproject.LoginRowFragment"
      android:tag="1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />

至:

    <FrameLayout 
      android:id="@+id/firsttab_loginrow"
      android:tag="1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />

并创建一个FragmentTransaction来根据您想要执行的操作添加/替换/显示/隐藏。

关于android - 为什么 detach() 对 FragmentTransaction 不起作用,而 remove() 却可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22408600/

相关文章:

java - Android 使用共享首选项来检查首次运行

Windows 10 上的 Android 模拟器

Android:检测圆形中的触摸事件

android - 在 Android EditText 中设置两个复合绘图

android - android :orientation ="vertical" vs android:orientation ="horizontal"之间的区别

java - 调用超父类(super class)onResume()和onCreae()

android - 将 fragment 部分移出屏幕

android - 使 AppBarLayout/CollapsingToolbarLayout 对 ViewPager 中的 RecyclerView 中的滚动使用react

android - 如何在非 FragmentActivity 上使用 ViewModelProviders.of() 获取 ViewModel?

android - fragment与activity之间的通信