方向更改时显示错误的片段

Wrong fragment is displayed on orientation change

我知道这个特定问题有几个答案,但是 none 帮助我解决了这个问题。

我正在开发一个具有抽屉导航(Mike Penz 抽屉导航)的应用程序。通过选择任何项目,用户将导航到相应的片段。这些片段完美地工作,并在方向改变时保持它们的状态。但是,其中一个片段有一个按钮,可以用新片段替换当前片段。当新片段出现在屏幕上时,如果用户更改设备的方向,则会显示前一个片段。

流程:抽屉项目 Select > 片段 A > 按钮 > 片段 B > 更改方向 > 片段 A。

编辑: 这就是第一个片段的调用方式:(switch)

case R.string.drawer_item_a:
      FragmentA A = FragmentA.newInstance();
      getSupportFragmentManager().beginTransaction()
           .replace(R.id.container, A)
           .commit();
      break;

这是第二个片段的调用方式:

@Override
   public void onClick(View v) {
       FragmentManager fm = getActivity().getSupportFragmentManager();
       FragmentB B = FragmentB.newInstance();
       fm.beginTransaction()
           .replace(R.id.container, B, String.valueOf(R.string.settings_pin_request))
           .commit();
   }

抽屉

result = new Drawer()
            .withActivity(this)
            .withToolbar(mToolbar)
            .withActionBarDrawerToggle(true)
            .addDrawerItems(
                    new PrimaryDrawerItem().withName("FragmentA"),
        new PrimaryDrawerItem().withName("FragmentB")
            )
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) {

                    if (drawerItem instanceof Nameable) {
                        mCurrentDrawerItem = position;

                        // Display appropriate fragment
                        switch (((Nameable) drawerItem).getNameRes()) {
                  case R.string.drawer_item_a:
                    FragmentA A = FragmentA.newInstance();
                    getSupportFragmentManager().beginTransaction()
                       .replace(R.id.container, A)
                       .commit();
                  break;
                  case R.string.drawer_item_b:
                    FragmentA A = FragmentA.newInstance();
                    getSupportFragmentManager().beginTransaction()
                       .replace(R.id.container, A)
                       .commit();
                  break;

                        }
                        mToolbar.setTitle(MainActivity.this.getString(((Nameable) drawerItem).getNameRes()));
                    }
                }
            }).build();

    // Set the current drawer item
    result.setSelection(mCurrentDrawerItem);

onResume() 方法实现用户同步的逻辑。没有为片段状态写任何内容。

Answer based on the version used in the question (MaterialDrawer v3.x.y). The answer will require some changes to work with the latest MaterialDrawer v4.x.y


如果应用程序已创建但您未激活它,抽屉将不会触发 OnDrawerItemClickListener。您可以通过 withFireOnInitialOnClick(true) 标志启用它。这将允许您在 OnDrawerItemClickListener

中拥有整个片段切换逻辑

如果未设置,您必须在方向更改后自行设置正确的片段。

您为此使用此代码:

// Set the current drawer item
result.setSelection(mCurrentDrawerItem);

回到你的 OnDrawerItemClickListener 就你上面发布的代码显示你使用基于 R.string 的开关。通过 getNameRes() 方法。这不会真正起作用,因为您没有通过资源设置项目的 name,而是直接设置为字符串。 .withName("FragmentA")。你应该在这两种情况下使用相同的。 一个更好的解决方案(我强烈建议这样做)是你切换你的代码和 OnDrawerItemClickListener 切换基于你在 DrawerItems

上设置的标识符
result = new Drawer()
    .withActivity(this)
    .withToolbar(mToolbar)
    .withActionBarDrawerToggle(true)
    .addDrawerItems(
            new PrimaryDrawerItem().withName("FragmentA").withIdentifier(1),
          new PrimaryDrawerItem().withName("FragmentB").withIdentifier(2)
    )
    .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id, IDrawerItem drawerItem) {
              if(drawerItem != null) {
                  Fragment f = null;
                  switch(drawerItem.getIdentifier) {
                  case 1:
                    f = FragmentA.newInstance();
                  break;
                  case 2:
                    f = FragmentA.newInstance();

                  break;
                  }

                  if (drawerItem instanceof Nameable) {
                    mToolbar.setTitle(MainActivity.this.getString(((Nameable) drawerItem).getNameRes()));
                  }
              }
            }
        }
    }).build();