【问题标题】:How to replace fragment C with fragment A when back button is pressed?按下后退按钮时如何用片段A替换片段C?
【发布时间】:2012-12-08 17:20:50
【问题描述】:

我的场景:活动 1 由片段 A-> B-> C 组成。所有片段都使用以下代码添加:

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.content, fragment, TAG);
        ft.addToBackStack(TAG);
        ft.commit();

现在,我想从片段 C 直接返回到片段 A。因此,我在添加片段 C 时评论了ft.addToBackStack(TAG)。所以当我从 CI 按下返回按钮时,直接在屏幕上获取片段 A。

但是,Fragment C 并没有被 A 取代。事实上,这两个 Fragment 都是可见的。我该如何解决这个问题?

【问题讨论】:

    标签: android android-fragments back-stack fragmenttransaction


    【解决方案1】:

    您需要做 2 件事 - 从 A->B 命名 FragmentTransaction,然后在您的包含活动中覆盖 onBackPressed() 以在您使用 Fragment C 时调用 FragmentManager#popBackStack (String name, int flags)。示例:

    从 A->B 过渡

    getSupportFragmentManager()
      .beginTransaction()
      .replace(R.id.container, new FragmentB(), "FragmentB")
      .addToBackStack("A_B_TAG")
      .commit();
    

    从 B->C 的转换将使用类似的交易,其标签为“FragmentC”。

    然后在你包含的Activity中重写onBackPressed():

    @Override
    public void onBackPressed() {
      if (getSupportFragmentManager().findFragmentByTag("FragmentC") != null) {
        // I'm viewing Fragment C
        getSupportFragmentManager().popBackStack("A_B_TAG",
          FragmentManager.POP_BACK_STACK_INCLUSIVE);
      } else {
        super.onBackPressed();
      }
    }
    

    【讨论】:

    • 你确定这条线是正确的吗?:.replace(new FragmentB(), "FragmentB")我不这么认为
    • .replace(new FragmentB(), "FragmentB") 应该是.replace(R.id.container, new FragmentB(), "FragmentB")
    【解决方案2】:

    理论

    使用FragmentTransaction 中的addToBackStack(tag: String): FragmentTransaction 方法来标记要返回的点。 此方法返回 FragmentTransaction 实例仅用于链式能力。

    然后从FragmentManager 使用popBackStackImmediate(tag: String, flag: int): void 方法返回。标签是您之前指定的。该标志要么是常量POP_BACK_STACK_INCLUSIVE 以包含标记的事务,要么是0

    示例

    下面是一个示例,其布局具有 FrameLayout 和 id content_frame,片段被加载到其中。

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_below="@id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
    </RelativeLayout>
    

    以下代码在将布局元素的内容替换为 id content_frame 时,通过片段类名标记片段。

    public void loadFragment(final Fragment fragment) {
        
        // create a transaction for transition here
        final FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();
                
        // put the fragment in place
        transaction.replace(R.id.content_frame, fragment);
    
        // this is the part that will cause a fragment to be added to backstack,
        // this way we can return to it at any time using this tag
        transaction.addToBackStack(fragment.getClass().getName());
    
        transaction.commit();
    }
    

    为了完成这个例子,一个方法可以让你在加载时使用标签返回到完全相同的片段。

    public void backToFragment(final Fragment fragment) {
    
        // go back to something that was added to the backstack
        getSupportFragmentManager().popBackStackImmediate(
                fragment.getClass().getName(), 0);
        // use 0 or the below constant as flag parameter
        // FragmentManager.POP_BACK_STACK_INCLUSIVE);
    
    }
    

    当你真正实现这个时,你可能想要在片段参数上添加一个空检查;-)。

    【讨论】:

    • 我的片段是动作栏中的TAB A,当点击TAB A时,我调用主要活动用另一个片段替换TAB A内容,代码为getFragmentManager().beginTransaction().replace( R.id.container, newFragment) .addToBackStack(null).commit();但是,没有显示返回 btn id 让我返回 TAB A。有什么想法吗?
    【解决方案3】:

    我就是这样做的..

    使用 FragmentA.java 和任何其他片段。

    用它的类名替换你的片段作为标签:

    private void showFragment(Fragment fragment){
            if(fragment != null){
                getSupportFragmentManager().beginTransaction().replace(R.id.container,fragment,fragment.getClass().getSimpleName()).commit();
            }
        }
    

    现在在 onBackPressed():

    @Override
        public void onBackPressed()
        {
    if(getSupportFragmentManager().findFragmentByTag("FragmentA") == null)
                showFragment(new FragmentA());
            else
                super.onBackPressed();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多