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

Evi*_*Ash 177 android android-fragments android-actionbar navigation-drawer

当使用导航抽屉时,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();
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是当我导航回到最高级别的片段时,向上克拉仍然显示而不是原始的导航抽屉图像.有关如何"刷新"顶级片段上的ActionBar以重新显示导航抽屉图像的任何建议?


汤姆的建议对我有用.这是我做的:

主要活动

此活动控制应用程序中的所有片段.

在准备新片段以替换其他片段时,我将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();
Run Code Online (Sandbox Code Playgroud)

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

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

在LowerLevelFragments中

在我修改过的片段中onCreate,onOptionsItemSelected像这样:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后,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;
        … 
    }
Run Code Online (Sandbox Code Playgroud)

riw*_*nyk 83

这很简单,1-2-3.

如果你想实现:

1)抽屉指示器 - 当后堆栈中没有碎片或抽屉打开时

2)箭头 - 当一些碎片在后堆栈中时

private FragmentManager.OnBackStackChangedListener
        mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        syncActionBarArrowState();
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    mDrawerToggle = new ActionBarDrawerToggle(
            this,             
            mDrawerLayout,  
            R.drawable.ic_navigation_drawer, 
            0, 
            0  
    ) {

        public void onDrawerClosed(View view) {
            syncActionBarArrowState();
        }

        public void onDrawerOpened(View drawerView) {
            mDrawerToggle.setDrawerIndicatorEnabled(true);
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
    getSupportFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener);
}

@Override
protected void onDestroy() {
    getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener);
    super.onDestroy();
}

private void syncActionBarArrowState() {
    int backStackEntryCount = 
        getSupportFragmentManager().getBackStackEntryCount();
    mDrawerToggle.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}
Run Code Online (Sandbox Code Playgroud)

3)两个指标根据其形状行事

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mDrawerToggle.isDrawerIndicatorEnabled() && 
        mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    } else if (item.getItemId() == android.R.id.home && 
               getSupportFragmentManager().popBackStackImmediate()) {
        return true;
    } else {
        return super.onOptionsItemSelected(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

PS请参阅在Android开发者创建有关3行指示器行为的其他提示的导航抽屉.

  • 我最终在NavigationDrawer片段中完成了所有这些操作.像btw的魅力一样,谢谢. (5认同)
  • 我最终得到了类似于你的东西.我认为这个解决方案(使用BackStackChangedListener在显示的内容之间切换)是最优雅的.不过我有两个变化:1)我不叫/改变抽屉指标在onDrawerClosed/onDrawerOpened电话 - 不需要它,和2)我让自己片段通过使AbstractFragment他们都继承处理向上导航哪实现onOptionsItemSelected(..)并始终调用setHasOptionsMenu(true); (3认同)
  • Yout还应该以箭头模式锁定导航抽屉的滑动手势:mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); 并在抽屉指示器模式下再次启用它 (2认同)
  • 当我从片段A转到B并将A添加到backstack时,这不显示我的向上按钮.:( (2认同)

Tom*_*Tom 29

您已经写过,为了实现较低级别的片段,您将替换现有片段,而不是在新活动中实现较低级别片段.

我认为你必须手动实现后退功能:当用户按下时你有代码弹出堆栈(例如在Activity::onBackPressed覆盖中).所以,无论你做什么,你都可以扭转局面setDrawerIndicatorEnabled.

  • 如何在较低级别的片段中引用theDrawerToggle?它已在主要活动中定义,无法理解这个! (6认同)

小智 14

我用过下一件事:

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                if(getSupportFragmentManager().getBackStackEntryCount() > 0){
                    mDrawerToggle.setDrawerIndicatorEnabled(false);
                    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
                }
                else {
                    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                    mDrawerToggle.setDrawerIndicatorEnabled(true);
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)


Bur*_*ich 12

如果您的向上操作栏按钮不起作用,请不要忘记添加监听器:

// Navigation back icon listener
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
});
Run Code Online (Sandbox Code Playgroud)

我在使用主页按钮实现抽屉导航方面遇到了一些麻烦,除了动作按钮外,一切正常.


dze*_*kei 10

尝试根据DrawerToggle的状态处理MainActivity中的Home项目选择.这样您就不必为每个片段添加相同的代码.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Only handle with DrawerToggle if the drawer indicator is enabled.
    if (mDrawerToggle.isDrawerIndicatorEnabled() &&
            mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    // Handle action buttons
    switch (item.getItemId()) {
        // Handle home button in non-drawer mode
        case android.R.id.home:
            onBackPressed();
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}
Run Code Online (Sandbox Code Playgroud)


HpT*_*erm 6

跟进

@dzeikei给出的解决方案很简洁,但是当使用碎片时,它可以在后台堆叠为空时自动处理抽屉指示器的设置.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Only handle with DrawerToggle if the drawer indicator is enabled.
    if (mDrawerToggle.isDrawerIndicatorEnabled() &&
            mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    // Handle action buttons
    switch (item.getItemId()) {
        // Handle home button in non-drawer mode
        case android.R.id.home:
            // Use getSupportFragmentManager() to support older devices
            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.popBackStack();
            // Make sure transactions are finished before reading backstack count
            fragmentManager.executePendingTransactions();
            if (fragmentManager.getBackStackEntryCount() < 1){
                mDrawerToggle.setDrawerIndicatorEnabled(true);  
            }
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

关于@JJD的问题.

片段在活动中保存/管理.上面的代码在该活动中写入一次,但只处理该插入符号onOptionsItemSelected.

在我的一个应用程序中,我还需要在按下后退按钮时处理向上插入符的行为.这可以通过覆盖来处理onBackPressed.

@Override
public void onBackPressed() {
    // Use getSupportFragmentManager() to support older devices
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.executePendingTransactions();
    if (fragmentManager.getBackStackEntryCount() < 1){
        super.onBackPressed();
    } else {
        fragmentManager.executePendingTransactions();
        fragmentManager.popBackStack();
        fragmentManager.executePendingTransactions();
        if (fragmentManager.getBackStackEntryCount() < 1){
            mDrawerToggle.setDrawerIndicatorEnabled(true);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

注意之间的重复代码onOptionsItemSelected,并onBackPressed可以通过创建一个方法,并呼吁在这两个地方是方法来避免.

还要注意我再添加两次executePendingTransactions,在我的情况下是需要的,否则我有时会出现奇怪的插入符号.