在使用片段时,在Android导航抽屉图像和上方插入符号之间切换
当使用导航抽屉时,Android开发人员build议在ActionBar中“只有在导航抽屉中表示的那些屏幕实际上应该具有导航抽屉图像”,并且“所有其他屏幕都具有传统的向上克拉”。
详情请看这里:http: //youtu.be/F5COhlbpIbY
我正在使用一个活动来控制多个片段级别,并且可以让导航抽屉图像在各个级别显示和运行。
在创build较低级别的片段时,我可以调用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();
我遇到的问题是,当我导航回顶层的碎片时,上克拉仍然显示,而不是原始的导航抽屉图像。 有关如何“刷新”顶级碎片上的ActionBar以重新显示导航抽屉图像的任何build议?
解
汤姆的build议为我工作。 以下是我所做的:
主要活动
此活动控制应用程序中的所有片段。
当准备新的片段来replace别人,我设置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中
在片段我修改onCreate
和onOptionsItemSelected
像这样:
在onCreate
添加了setHasOptionsMenu(true)
来启用configuration选项菜单。 还要设置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()
从activity中调用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; … }
您已经写道,为了实现较低级别的片段,您将replace现有的片段,而不是在新活动中实现较低级别的片段。
我认为你将不得不手动实现后端function:当用户按下你有代码popup堆栈(例如在Activity::onBackPressed
覆盖)。 所以,无论你在哪里做,都可以反转setDrawerIndicatorEnabled
。
这很容易,如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); }
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); } }
PS请参阅在Android Developers上创build导航抽屉,了解有关3线指示器行为的其他提示。
我用了下面的东西:
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); } } });
如果您的向上操作栏button不起作用,请不要忘记添加侦听器:
// Navigation back icon listener mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } });
用homebutton实现抽屉导航时遇到了一些麻烦,除了动作button之外,所有的东西都可以工作。
尝试处理MainActivity中的Home项目选项,具体取决于DrawerToggle的状态。 这样你就不必为每个片段添加相同的代码。
@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); } }
跟进
@dzeikei提供的解决scheme是整洁的,但是当使用碎片时,它可以被扩展,以在后台空置时自动处理抽屉指示器的设置。
@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); } }
编辑
对于@JJD的问题。
片段被保存/pipe理在一个活动中。 上面的代码在该活动中被写入一次,但只处理onOptionsItemSelected
的上一个字符。
在我的一个应用程序中,我还需要处理后退button被按下时的行为。 这可以通过重写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); } } };
注意onOptionsItemSelected
和onBackPressed
之间的代码重复,可以通过在两个地方创build一个方法并调用该方法来避免。
另外请注意,我再多加两次executePendingTransactions
,在我的情况下是必需的,否则我有时会有一些奇怪的行为。
我为托pipe活动创build了一个界面来更新汉堡包菜单的视图状态。 对于最高级别的片段,我将切换设置为true
,对于我要显示的片段<箭头,我将切换设置为false
。
public class SomeFragment extends Fragment { public interface OnFragmentInteractionListener { public void showDrawerToggle(boolean showDrawerToggle); } private OnFragmentInteractionListener mListener; @Override public void onAttach(Activity activity) { super.onAttach(activity); try { this.mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onResume() { super.onResume(); mListener.showDrawerToggle(false); } }
然后在我的活动…
public class MainActivity extends Activity implements SomeFragment.OnFragmentInteractionListener { private ActionBarDrawerToggle mDrawerToggle; public void showDrawerToggle(boolean showDrawerIndicator) { mDrawerToggle.setDrawerIndicatorEnabled(showDrawerIndicator); } }
这个答案正在工作,但有一个小问题。 没有明确调用getSupportActionBar().setDisplayHomeAsUpEnabled(false)
,即使在后台堆栈中没有项目时,也会导致抽屉图标被隐藏,所以更改setActionBarArrowDependingOnFragmentsBackStack()
方法对我很有用。
private void setActionBarArrowDependingOnFragmentsBackStack() { int backStackEntryCount = getSupportFragmentManager() .getBackStackEntryCount(); // If there are no items in the back stack if (backStackEntryCount == 0) { // Please make sure that UP CARAT is Hidden otherwise Drawer icon // wont display getSupportActionBar().setDisplayHomeAsUpEnabled(false); // Display the Drawer Icon mDrawerToggle.setDrawerIndicatorEnabled(true); } else { // Show the Up carat getSupportActionBar().setDisplayHomeAsUpEnabled(true); // Hide the Drawer Icon mDrawerToggle.setDrawerIndicatorEnabled(false); } }
逻辑清晰。 如果碎片堆栈清除,则显示回退button。 如果片段堆栈不清晰,则显示素材汉堡后退animation。
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; }
如果您查看GMAIL应用程序并来此searchcarret /的可爱图标..
我会请你这样做,上面的答案都不清楚。 我能够修改接受的答案。
-
NavigationDrawer – > Listview包含子片段。
-
亚片段将如此列出
-
firstFragment == position 0 —>这将有subfragments – > fragment
- secondFragment
- 第三个片段等等。
在firstFragment中你有其他的片段。
在DrawerActivity上调用它
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if (getFragmentManager().getBackStackEntryCount() > 0) { mDrawerToggle.setDrawerIndicatorEnabled(false); } else { mDrawerToggle.setDrawerIndicatorEnabled(true); } } });
并在片段
setHasOptionsMenu(true); @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 activity.onBackPressed(); return true; } return false; }
在OnBackPressed Drawer活动方法上,将抽屉切换为true以再次启用导航列表图标。
谢谢,Pusp
你可以看看这个小例子! https://github.com/oskarko/NavDrawerExample
国际海事组织,使用onNavigateUp()(如图所示)在riwnodennyk的或汤姆的解决scheme是更清洁,似乎更好地工作。 只需用下面的代码replaceonOptionsItemSelected代码:
@Override public boolean onSupportNavigateUp() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { // handle up navigation return true; } else { return super.onSupportNavigateUp(); } }