使用“Fragments”在“AppCompatActivity”中向上导航

Up navigation in `AppCompatActivity` with `Fragments`

我正在尝试在我的应用程序中设置正确的导航,它取代了主要内容区域中的 Fragment,因此我只有一个 Activity。我有一个主 Fragment 和几个子 Fragments,例如一个 Fragment 用于偏好设置。使用后退按钮时一切正常,但除此之外我还想实现包括图标在内的向上导航。我正在使用通过 Activity.getSupportActionBar() 获取的 ActionBar 以及来自 appcompat 的 ToolbarActionBarDrawerToggle.

我一开始就按照 this tutorial 设置 Drawer

当前行为: 当我启动应用程序时,list/drawer 图标显示在 ActionBar 的左侧。单击此按钮时,Drawer 打开,我可以 select 项。子 Fragment 被替换到我的内容中,后退按钮弹出堆栈,带我回到之前的 Fragment

缺失行为: 左上角的 list/drawer 图标永远不会被后退箭头图标取代,我不知道如何正确实现它。 Drawer 总是 在单击 list/drawer 图标时被拉出,无论我在哪个 Fragment

我尝试了什么:

  1. 我尝试按照 this 回答。它有点工作,这意味着后退箭头图标设置在子 Fragment 中,但单击后退箭头仍会打开 Drawer 而不是提供向上导航。此外,当使用后退按钮转到 "up" 时,list/drawer 图标将被替换为任何内容。
  2. 我也试过按照 this 回答。这里,想要的ActionBarbehavior/look是在各个FragmentonCreate()方法中实现的。使用这个我可以让后退箭头向上,但点击箭头时 Drawer 仍然被拉动。
  3. 其他各种小事和技巧。

我的问题:

  1. 我下面的代码有什么问题?
  2. 是否correct/normal使用组合ActionBarToolbarActionBarDrawerToggle来实现Drawer导航和向上导航?

MyActivity.onCreate():

@Override
protected void onCreate(Bundle savedInstanceState)
{
    // Other stuff

    // Setup drawer.
    mDrawerFragment = (DrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.mm_navigation_drawer);
    mDrawerFragment.initialize(this, (DrawerLayout)findViewById(R.id.mm_drawer_layout), toolbar);
}

抽屉片段class

public class DrawerFragment extends Fragment
{
    private MyActivity                      mMyActivity;
    private MyActionBarDrawerToggle         mMyBarDrawerToggle;
    private DrawerLayout                    mDrawerLayout;
    private FragmentDrawerListener          mFragmentDrawerListener;
    private View                            mContainerView;

    public void initialize(MyActivity myActivity, final DrawerLayout drawerLayout, final Toolbar toolbar)
    {
        mMyActivity = myActivity;
        mFragmentDrawerListener = mMyActivity;
        mContainerView = myActivity.findViewById(R.id.mm_navigation_drawer);

        mMyActionBarDrawerToggle = new MyActionBarDrawerToggle(myActivity, drawerLayout, toolbar, R.string.mm_drawer_open, R.string.mm_drawer_close);

        mDrawerLayout = drawerLayout;
        mDrawerLayout.setDrawerListener(mMyActionBarDrawerToggle);
        mDrawerLayout.post(new Runnable()
        {
            @Override
            public void run()
            {
                mMyActionBarDrawerToggle.syncState();
            }
        });
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState)
    {
        // Not relevant, just create and return the View.
    }
}

MyActivity.onDrawerItemSelected()

接口 FragmentDrawerListener 的实现在 MyActivity class 中完成。它只是将内容区域替换为其他 Fragments,使用 FragmentTransactions.

@Override
public void onDrawerItemSelected(View view, int postion)
{
    switch (postion)
    {
        case DrawerAdapter.ITEM_FILTERED_RECIPES:
            showFilteredRecipesFragment();
            break;

        case DrawerAdapter.ITEM_SELECTED_RECIPES:
            showSelectedRecipesFragment();
            break;

        case DrawerAdapter.ITEM_SHOPPING_LIST:
            showShoppingListFragment();
            break;

        case DrawerAdapter.ITEM_SETTINGS:
            showSettingsFragment();
            break;

        case DrawerAdapter.ITEM_ABOUT:
            showAboutFragment();
            break;
    }
}

MyActionBarDrawerToggle class

public class MyActionBarDrawerToggle extends ActionBarDrawerToggle
{
    private MyActivity mMyActivity;
    private Toolbar mToolbar;

    public MyActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes)
    {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);
        mMyActivity = (MyActivity) activity;
        mToolbar = toolbar;
    }

    @Override
    public void onDrawerOpened(View drawerView)
    {
        super.onDrawerOpened(drawerView);
        mMyActivity.invalidateOptionsMenu();
    }

    @Override
    public void onDrawerClosed(View drawerView)
    {
        super.onDrawerClosed(drawerView);
        mMyActivity.invalidateOptionsMenu();
    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset)
    {
        super.onDrawerSlide(drawerView, slideOffset);
        mToolbar.setAlpha(1 - slideOffset / 2);
    }
}

DrawerFragment 使用简单的静态 Fragment 实例在主布局中膨胀:

<fragment
    android:id="@+id/my_navigation_drawer"
    android:name="com.my.company.gui.drawer.DrawerFragment"
    android:layout_width="@dimen/my_nav_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:layout="@layout/my_drawer_navigation_fragment"
    tools:layout="@layout/my_drawer_navigation_fragment">
</fragment>

如果您的应用使用 material 设计,那么您应该使用 Toolbar 替换 activity 中的 Actionbar。您仍将保持 ActionBarDrawerToggle 并且功能将保持不变。

至于你的片段,只要它们是'housed'同一个活动(即activity与抽屉),改变片段不会导致抽屉切换改变后退箭头.它只会在您导航到新的 activity 时发生变化。只有这样,主要的 activity 才会被视为主页,而其他活动将有一个后退箭头可以返回