在使用片段时切换Android导航抽屉图像和向上插入符号

177

当使用导航抽屉时,Android开发人员建议在ActionBar中“只有那些在导航抽屉中表示的屏幕才实际拥有导航抽屉图像”,而“所有其他屏幕都有传统的向上符号”。

有关详细信息,请参见此处:http://youtu.be/F5COhlbpIbY

我正在使用一个活动来控制多个级别的片段,并且可以在所有级别上显示和使用导航抽屉图像。

创建较低级别片段时,我可以调用 ActionBarDrawerToggle setDrawerIndicatorEnabled(false)来隐藏导航抽屉图像并显示向上符号

LowerLevelFragment lowFrag = new LowerLevelFragment();

//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout, 
lowFrag, "lowerFrag").addToBackStack(null).commit();

我遇到的问题是,当我返回顶级片段时,“向上”字符仍然显示,而不是原始的导航抽屉图像。有没有建议如何在顶级片段上“刷新”操作栏以重新显示导航抽屉图像?


解决方案

汤姆的建议对我有用。以下是我的做法:

MainActivity

这个活动控制应用程序中的所有片段。

当准备新的片段来替换其他片段时,我会像这样设置 DrawerToggle setDrawerIndicatorEnabled(false)

LowerLevelFragment lowFrag = new LowerLevelFragment();

//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,   
lowFrag).addToBackStack(null).commit();

接下来,我在 onBackPressed 的覆盖中,通过像这样将 DrawerToggle 设置为 setDrawerIndicatorEnabled(true) 来恢复上述操作:

@Override
public void onBackPressed() {
    super.onBackPressed();
    // turn on the Navigation Drawer image; 
    // this is called in the LowerLevelFragments
    setDrawerIndicatorEnabled(true)
}

在LowerLevelFragments中

我修改了片段中的onCreateonOptionsItemSelected,如下所示:

onCreate中添加了setHasOptionsMenu(true)以启用配置选项菜单。还设置setDisplayHomeAsUpEnabled(true)以在操作栏中启用<

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // needed to indicate that the fragment would 
    // like to add items to the Options Menu        
    setHasOptionsMenu(true);    
    // update the actionbar to show the up carat/affordance 
    getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}

然后在onOptionsItemSelected中,每当按下<时,它都会调用活动中的onBackPressed()来在层次结构中向上移动一级并显示导航抽屉图像:

@Override
public boolean onOptionsItemSelected(MenuItem item) {   
    // Get item selected and deal with it
    switch (item.getItemId()) {
        case android.R.id.home:
            //called when the up affordance/carat in actionbar is pressed
            getActivity().onBackPressed();
            return true;
        … 
    }

2
在你的onBackPressed()方法中,你可以使用getFragmentManager().getBackStackEntryCount()方法检查后退栈中有多少条目,并仅在结果为0时启用抽屉指示器。在这种情况下,每个LowerLevelFragments中都不需要启用homeAsUpIndicator。 - pvshnik
3
非常有用!您应该将帖子中的“解决方案”部分移动并将其作为实际的“答案”。这样,您会获得更多的点赞,并且它毕竟是一个答案。 - Oleksiy
为什么要在这里替换片段:.replace(R.id.frag_layout。如果这是一个更高层次的层次结构,我会期望您将其.add到后退栈中。 - JJD
5
兄弟,你怎样在Fragment中引用theDrawerToggle.setDrawerIndicatorEnabled(false);?我认为它是在MainActivity的类文件中声明的。我找不到引用它的方法。有什么提示吗? - Skynet
1
当使用工具栏时,我不得不切换显示选项,以便在此期间不使用主页作为向上选项。否则,在第二次进入相同的片段时,ToolbarWidgetWrapper(内部android.support.v7.internal.widget包中的)中的setDisplayOptions()方法将无法重新创建图标。将此留在这里,以便其他人遇到此问题时可以参考。 - Wolfram Rittmeyer
@Wolfram Rittmeyer,您能详细解释一下您是如何解决使用工具栏时遇到的问题的吗? - Sanif SS
12个回答

1
逻辑清晰。 如果片段回退栈为空,则显示返回按钮。 如果片段栈不为空,则显示材料汉堡菜单-后退动画。
getSupportFragmentManager().addOnBackStackChangedListener(
    new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            syncActionBarArrowState();
        }
    }
);


private void syncActionBarArrowState() {
    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    mNavigationDrawerFragment.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}

//add these in Your NavigationDrawer fragment class

public void setDrawerIndicatorEnabled(boolean flag){
    ActionBar actionBar = getActionBar();
    if (!flag) {
        mDrawerToggle.setDrawerIndicatorEnabled(false);
        actionBar.setDisplayHomeAsUpEnabled(true);
        mDrawerToggle.setHomeAsUpIndicator(getColoredArrow());
    } else {
        mDrawerToggle.setDrawerIndicatorEnabled(true);
    }
    mDrawerToggle.syncState();
    getActivity().supportInvalidateOptionsMenu();
}

//download back button from this(https://www.google.com/design/icons/) website and add to your project

private Drawable getColoredArrow() {
    Drawable arrowDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_arrow_back_black_24dp);
    Drawable wrapped = DrawableCompat.wrap(arrowDrawable);

    if (arrowDrawable != null && wrapped != null) {
        // This should avoid tinting all the arrows
        arrowDrawable.mutate();
        DrawableCompat.setTint(wrapped, Color.GRAY);
    }
    return wrapped;
}

0

在我看来,使用onNavigateUp()(如此处所示)在riwnodennyk或Tom的解决方案中更加简洁且似乎效果更好。只需将onOptionsItemSelected代码替换为以下内容:

@Override
public boolean onSupportNavigateUp() {
    if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
        // handle up navigation
        return true;
    } else {
        return super.onSupportNavigateUp();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接