【问题标题】:Fragment management when the layout changes布局更改时的片段管理
【发布时间】:2014-07-02 16:34:56
【问题描述】:

我有一个包含一个 Activity 和两个片段的应用程序。期望的行为是(用户交互以蓝色突出显示):

纵向

横向

我目前的解决方案是:

横向布局

FrameLayout
   ContainerRed(FrameLayout)
   ContainerYellow(FrameLayout)

纵向布局

LinearLayout
   ContainerRed(FrameLayout weight=1)
   ContainerYellow(FrameLayout weight=1)

当用户点击绿色按钮时,我会进行以下交易:

  • 纵向:移除 FragmentA,将 FragmentB 添加到 containerYellow,addToBackstack
  • 横向:将 FragmentB 添加到 contanerYellow,addToBackstack

这实现了正确的行为,除非您在事务后旋转设备,例如,如果您是纵向的,则转到屏幕 B1,然后将设备旋转到横向 FragmentA 插槽为空。

此外,如果您在屏幕 B2 中并旋转屏幕以纵向显示 FragmentA 会出现在 FragmentB 的背景中。

我该如何解决?谢谢

【问题讨论】:

    标签: java android android-fragments fragment


    【解决方案1】:

    我有一个可行的解决方案:

    首先对 addToBackstack("FOO"); 使用相同的标签

    在Activity调用的onCreate方法结束时:

    Fragment fragmentB=getFragmentManager().findFragmentByTag("FRAGMENT_B_TAG");
    if (fragmentB!=null){
       getFragmentManager().popBackStackImmediate("FOO",
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
       attachFragmentB(fragmentB);
    }
    
    void attachFragmentB(Fragment fragmentB){
      //In portrait: Remove FragmentA, add FragmentB to containerYellow, addToBackstack("FOO")
      //In landscape: add FragmentB to contanerYellow, addToBackstack("FOO")
    }
    

    【讨论】:

    • 哦,我明白了,那么您是在使用标签来跟踪活动堆栈吗?此代码是否进入 FragmentA 的 onCreate?
    • 不,它进入包含两个片段的 Activity 的 onCreate 中。基本上使用此代码,您可以恢复在另一个方向上执行的片段事务并根据新方向重新执行
    【解决方案2】:

    另一种无需多个布局和回栈技巧的方法是在 onCreate() 和 onBackStackChanged() 中修改容器的可见性。

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (savedInstanceState == null) {
                if (getSupportFragmentManager().findFragmentByTag(AFragment.TAG) == null) {
                    Fragment fragment = new AFragment();
                    getSupportFragmentManager()
                            .beginTransaction()
                            .replace(R.id.layout_left, fragment,AFragment.TAG)
                            .commit();
                }
            }
            getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
                @Override
                public void   onBackStackChanged() {
                    updateScreen();
                }
            });
            updateScreen();
        }
    
        //called when A button's is clicked
        public void onClick() {
            if (getSupportFragmentManager().findFragmentByTag(BFragment.TAG) == null) {
                Fragment fragment = new BFragment();
                getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.layout_right, fragment, BFragment.TAG)
                        .addToBackStack(BFragment.TAG)
                        .commit();
            }
        }
    
        public void updateScreen(){
            if (getSupportFragmentManager().findFragmentByTag(BFragment.TAG) != null){
                if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
                    findViewById(R.id.layout_right).setVisibility(View.VISIBLE);
                    findViewById(R.id.layout_left).setVisibility(View.VISIBLE);
                }else{
                    findViewById(R.id.layout_right).setVisibility(View.VISIBLE);
                    findViewById(R.id.layout_left).setVisibility(View.GONE);
                }
            }else{
                findViewById(R.id.layout_right).setVisibility(View.GONE);
                findViewById(R.id.layout_left).setVisibility(View.VISIBLE);
            }
        }
    

    【讨论】: