首页 文章

碎片和方向改变

提问于
浏览
31

使用碎片时处理方向更改的正确方法是什么?

我有一个包含2个片段的横向布局(在代码中实例化为 FrameLayout ) . 当我切换到纵向模式(其布局仅包含一个仅保留左窗格的 FrameLayout )时,不再需要右侧片段 .

我收到一个错误:

E/AndroidRuntime(4519): Caused by: java.lang.IllegalArgumentException: No view found for id 0x7f060085 for fragment myFragment{418a2200 #2 id=0x7f060085}

假设是我的活动试图重新附加方向更改之前的片段,但由于包含片段的视图在纵向模式下不存在,因此会引发错误 .

我尝试了以下隐藏/删除/分离方法但仍然得到错误 . 告诉片段它不再需要的正确方法是什么,不要尝试显示?

@Override
public void onCreate(Bundle b) {
    super.onCreate(b);
    Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragholder2);

    //rightPane is a framelayout that holds my fragment.
    if (rightPane == null && f != null) {
         FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
         ft.hide(f);     // This doesnt work
         ft.remove(f);   // neither does this
         ft.detach(f);   // or this
         ft.commit;
    }
}

7 回答

  • -1

    我遇到了同样的问题,我想我想出了另一个解决方案 . 此解决方案可能更好,因为您不必将片段添加到后台堆栈 .

    Activity.onSaveInstanceState() before 中调用 super.onSaveInstanceState() 的活动中删除右侧片段 . 这对我有用:

    public MyActivity extends Activity
    {   
        @Override
        public onCreate(Bundle state)
        {
            super.onCreate(state);
    
            // Set content view
            setContentView(R.layout.my_activity);
    
            // Store whether this is a dual pane layout
            mDualPane = findViewById(R.id.rightFragHolder) != null;
    
            // Other stuff, populate the left fragment, etc.
            .
            .
            .
            if (mDualPane)
            {
                mRightFragment = new RightFragment();
                FragmentManager fm = getFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                ft.replace(R.id.rightFragHolder, mRightFragment);
                ft.commit()
            }
        }
    
    
        @Override
        public void onSaveInstanceState(Bundle state)
        {
            if (mDualPane)
            {
                FragmentManager fm = getFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                ft.remove(mRightFragment);
                ft.commit()
            }
    
            super.onSaveInstanceState(state);
        }
    
    
        private boolean mDualPane;
        private Fragment mRightFragment;
    }
    
  • -1

    如果要保留片段,请尝试不保留它 .

    setRetainInstance(false)
    

    代替

    setRetainInstance(true)
    
  • 13

    通常,您将有两个片段(左/右),一个主要活动和一个容器活动用于正确的片段(仅在电话设备上显示时) . 此博客文章中描述了这一点:The Android 3.0 Fragments API

    public class MyActivity extends FragmentActivity
        implements MyListFragment.MyContextItemSelectedListener {
    
        @Override
        public void onCreate(final Bundle bundle) {
            super.onCreate(bundle);
    
            setContentView(R.layout.activity);
        }
    
        // Callback from ListFragment
        @Override
        public void myContextItemSelected(final int action, final long id) {
            if (action == R.id.men_show) {
                processShow(id);
            }
        }
    
        private void processShow(final long id) {
            if (Tools.isXlargeLand(getApplicationContext())) {
                Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.right);
                if (fragment == null ||
                        fragment instanceof MyEditFragment ||
                        (fragment instanceof MyShowFragment && ((MyShowFragment) fragment).getCurrentId() != id)) {
                    fragment = new MyShowFragment(id);
    
                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.replace(R.id.right, fragment);
                    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                    transaction.commit();
                }
            } else {
                Intent intent = new Intent();
                intent.setClass(this, MyShowActivity.class);
                intent.putExtra("ID", id);
                startActivityForResult(intent, MyConstants.DLG_TABLE1SHOW);
            }
        }
    
        private static boolean isXlargeLand(final Context context) {
            Configuration configuration = context.getResources().getConfiguration();
    
            return (((configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) &&
                            configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
        }
    }
    
  • 1

    如果您有一个带有左窗格和右窗格的双窗格活动,并且其中一个窗格(通常是右窗格)假设在设备切换到纵向模式时不显示,请让Android执行其操作并重新创建右窗格 . 但是在右窗格的onCreateView中,您应该做的第一件事是检查窗格使用的布局元素之一是否可用 . 如果不是,请使用FragmentManager删除片段并立即返回:

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
    {
        View myView = getActivity().findViewById(R.id.myView);
    
        if (myView == null)
        {
          FragmentTransaction fragTransaction = getFragmentManager().beginTransaction();
          fragTransaction.remove(this);
          fragTransaction.commit();
          return null;
        }
     }
    
  • 0

    我想我已经解决了 .

    我将片段添加到后台堆栈中,然后在活动关闭之前再将其弹出,这有效地消除了它 . 到目前为止似乎工作 .

  • 0

    Android会在屏幕旋转期间重新创建两个片段 . 但是如果你将下面的检查添加到onCreateView()中,它将阻止你解决问题:

    @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                                 @Nullable Bundle savedInstanceState) {
            if (container == null) {
                // Currently in a layout without a container, so no
                // reason to create our view.
                return null;
            }
    
            // inflate view and do other stuff
        }
    

    我从Android Developers blog拿走了这个 .

  • -4

    您不再需要此活动,因为片段将以内嵌方式显示 . 所以你可以完成这项活动

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // we are in landscape so you do not need this activity anymore
            finish();
            return;
        }
    
        if (savedInstanceState == null) {
             // plugin right pane fragment
             YourFragment frgm = new YourFragment();
             getSupportFragmentManager().beginTransaction()
                    .add(..., frgm).commit();
        }
    }
    

相关问题