Android - 将 ActionBar 后退按钮切换为导航按钮
Android - Switch ActionBar Back Button to Navigation Button
我遇到了以下问题:
我知道如何设置工具栏以显示后退按钮图标而不是汉堡包按钮图标。
由此:
对此:
使用:getSupportActionBar().setDisplayHomeAsUpEnabled(true);
现在,我想做反向操作,我想从后退按钮图标转到汉堡图标:
到这里:
我该怎么做?
更新:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
private void enableViews(boolean enable) {
if(enable) {
// Enables back button icon
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
// TODO: Enables burger icon
}
}
您可以通过以下方式更改操作栏按钮:
getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
使用这个
getSupportActionBar().setDisplayShowHomeEnabled(true);
final Toolbar toolbar = (Toolbar) findViewById(R.id.actionbar);
toolbar.setTitle(Html.fromHtml("<font color=#ffffff>" + getString(R.string.print_s) + "</font>"));
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.menu_icon));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DetailActivity.this.finish();
}
});
toolbar.inflateMenu(R.menu.fav);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
item.setIcon(R.drawable.back_icon)
return true;
}
return false;
}
});
尝试将下面的 style
AppTheme
代码添加到您的 activity's theme/style.xml
中,这将使您的 hamburger icon
变为 back icon
animation
。
条件 如果您使用带有 NavigationDrawer
和 AppCompatActivity/ActionBarActivity
的汉堡包图标
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="windowActionBar">false</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">@android:color/white</item>
</style>
希望对您有所帮助!或者你只需要用 drawable 来做。
勾选这个
如果我假设您在布局中使用 android.support.v4.widget.DrawerLayout
,那么这种方法可能适合您;我只在 API 21
上测试过,但鉴于它主要使用支持库,它 应该 在较低或较高的目标上工作(著名的遗言)。
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v4.widget.DrawerLayout
ActionBarDrawerToggle mDrawerToggle;
DrawerLayout drawerLayout;
private boolean mToolBarNavigationListenerIsRegistered = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
// Get DrawerLayout ref from layout
drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
// Initialize ActionBarDrawerToggle, which will control toggle of hamburger.
// You set the values of R.string.open and R.string.close accordingly.
// Also, you can implement drawer toggle listener if you want.
mDrawerToggle = new ActionBarDrawerToggle (this, drawerLayout, mToolbar, R.string.open, R.string.close);
// Setting the actionbarToggle to drawer layout
drawerLayout.addDrawerListener(mDrawerToggle);
// Calling sync state is necessary to show your hamburger icon...
// or so I hear. Doesn't hurt including it even if you find it works
// without it on your test device(s)
mDrawerToggle.syncState();
}
/**
* To be semantically or contextually correct, maybe change the name
* and signature of this function to something like:
*
* private void showBackButton(boolean show)
* Just a suggestion.
*/
private void enableViews(boolean enable) {
// To keep states of ActionBar and ActionBarDrawerToggle synchronized,
// when you enable on one, you disable on the other.
// And as you may notice, the order for this operation is disable first, then enable - VERY VERY IMPORTANT.
if(enable) {
//You may not want to open the drawer on swipe from the left in this case
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
// Remove hamburger
mDrawerToggle.setDrawerIndicatorEnabled(false);
// Show back button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// when DrawerToggle is disabled i.e. setDrawerIndicatorEnabled(false), navigation icon
// clicks are disabled i.e. the UP button will not work.
// We need to add a listener, as in below, so DrawerToggle will forward
// click events to this listener.
if(!mToolBarNavigationListenerIsRegistered) {
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Doesn't have to be onBackPressed
onBackPressed();
}
});
mToolBarNavigationListenerIsRegistered = true;
}
} else {
//You must regain the power of swipe for the drawer.
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
// Remove back button
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
// Show hamburger
mDrawerToggle.setDrawerIndicatorEnabled(true);
// Remove the/any drawer toggle listener
mDrawerToggle.setToolbarNavigationClickListener(null);
mToolBarNavigationListenerIsRegistered = false;
}
// So, one may think "Hmm why not simplify to:
// .....
// getSupportActionBar().setDisplayHomeAsUpEnabled(enable);
// mDrawer.setDrawerIndicatorEnabled(!enable);
// ......
// To re-iterate, the order in which you enable and disable views IS important #dontSimplify.
}
该解决方案使用 ActionBarDrawerToggle.setDrawerIndicatorEnabled
切换汉堡包图标的可见性,并使用 ActionBar.setDisplayHomeAsUpEnabled
切换 Up 按钮的可见性,本质上是利用它们各自的drawable
资源。
其他假设
- 您的 Activity 主题扩展了
Theme.AppCompat.Light.NoActionBar
。
我在 The Google I/O 2017 Android App 中找到了灵活的解决方案。
public Toolbar getToolbar() {
if (mToolbar == null) {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
mToolbar.setNavigationContentDescription(R.string.navdrawer_description_a11y);
mToolbarTitle = (TextView) mToolbar.findViewById(R.id.toolbar_title);
if (mToolbarTitle != null) {
int titleId = getNavigationTitleId();
if (titleId != 0) {
mToolbarTitle.setText(titleId);
}
}
// We use our own toolbar title, so hide the default one
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}
return mToolbar;
}
/**
* @param clickListener The {@link android.view.View.OnClickListener} for the navigation icon of
* the toolbar.
*/
protected void setToolbarAsUp(View.OnClickListener clickListener) {
// Initialise the toolbar
getToolbar();
if (mToolbar != null) {
mToolbar.setNavigationIcon(R.drawable.ic_up);
mToolbar.setNavigationContentDescription(R.string.close_and_go_back);
mToolbar.setNavigationOnClickListener(clickListener);
}
}
所以用法真的很简单
setToolbarAsUp(new View.OnClickListener() {
@Override
public void onClick(View v) {
// onBackPressed();
// or navigate to parent or some other intent
}
});
对我来说,我想通过 Fragment
左侧的 后退箭头 图标来更改 Burger 图标的 ActionBar,因为我使用的是 Navigation Drawer
。还在右侧添加一个 Menu。
在 Main Activity 中,它已经设置 - 默认情况下,当 Android Studio 为我创建导航抽屉时 - 如下所示:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
问题是如何在 Fragment
中自定义 ActionBar
,所以当我转到 Fragment
时,它会显示自定义的 ActionBar
以及后退箭头图标被点击,它应该离开片段并且ActionBar
应该回到第一个状态。
在片段中(完整实现):
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true); // To show the menu options
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
showActionBar(); // the method to change ActionBar
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// inflate the customized menu which already created in XML
getActivity().getMenuInflater().inflate(R.menu.fragment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// add implementation when user select an item from the menu
switch (item.getItemId()) {
case R.id.option1:
// do something
return true;
case R.id.option2:
// do something
return true;
case R.id.option3:
// do something
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void showActionBar() {
// get the ToolBar from Main Activity
final Toolbar toolbar = getActivity().findViewById(R.id.toolbar);
// get the ActionBar from Main Activity
final ActionBar actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
// inflate the customized Action Bar View
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.fragment_actionbar, null);
if (actionBar != null) {
// enable the customized view and disable title
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setCustomView(v);
// remove Burger Icon
toolbar.setNavigationIcon(null);
// add click listener to the back arrow icon
v.findViewById(R.id.back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// reverse back the show
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
//get the Drawer and DrawerToggle from Main Activity
// set them back as normal
DrawerLayout drawer = getActivity().findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
getActivity(), drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
// All that to re-synchronize the Drawer State
toggle.syncState();
// Implement Back Arrow Icon
// so it goes back to previous Fragment
getActivity().onBackPressed();
}
});
}
}
fragment_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_horizontal" >
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="@drawable/ic_menu_back"
android:layout_marginLeft="@dimen/_5sdp"
android:layout_alignParentStart="true"
android:layout_marginStart="@dimen/_5sdp" />
</RelativeLayout>
ic_menu_back.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="459"
android:viewportWidth="459">
<path
android:fillColor="#ffffff"
android:pathData="M178.5,140.25v-102L0,216.75l178.5,178.5V290.7c127.5,0,216.75,40.8,280.5,130.05C433.5,293.25,357,165.75,178.5,140.25z"/>
</vector>
fragment_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/border_shadow">
<item
android:id="@+id/option1"
android:title="@string/show_profile"
app:showAsAction="never"/>
<item
android:id="@+id/option2"
android:title="@string/report_pic"
app:showAsAction="never"/>
<item
android:id="@+id/option3"
android:title="@string/delete_pic"
app:showAsAction="never"/>
</menu>
我一直在我的应用程序上尝试其中一些示例,但其中 none 似乎有效。我正在使用片段,其中一些片段必须显示后退选项而不是主页。这是我的实现(在 Kotlin 中):
override fun onResume() {
super.onResume()
var drawerLayout: DrawerLayout = activity.findViewById(R.id.drawer_layout)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
var actionBar = (activity as MainActivity).supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(true)
var toggle= (activity as MainActivity).drawerToggle
toggle.isDrawerIndicatorEnabled = false
toggle.setToolbarNavigationClickListener { v -> activity.onBackPressed() }
}
override fun onStop() {
super.onStop()
var drawerLayout: DrawerLayout = activity.findViewById(R.id.drawer_layout)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
var actionBar = (activity as MainActivity).supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(false)
var toggle= (activity as MainActivity).drawerToggle
toggle.setToolbarNavigationClickListener {null}
toggle.syncState()
}
注意:这些是片段中重写的 onResume 和 onStop 方法。
备注: 汉堡包 图标只有在调用 toggle.syncState() 方法时才会显示。我已经将近 24 小时弄清楚为什么主页图标没有显示。
希望我的 post 可以帮助到别人。
-> 如果你家里有一个抽屉activity 和 initalfragment 你必须显示 drawertoggle 并且在内部 fragement 之后你不想显示抽屉代表抽屉你必须显示后退按钮并像这样更改所有片段的标题。
在 activity 中切换 public。
在你的主页片段中写下这段代码。
@Override
public void onResume()
{
super.onResume();
((HomeActivity)getActivity()).getSupportActionBar().setTitle("Home");
((HomeActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false);
((HomeActivity)getActivity()).actionBarDrawerToggle.setDrawerIndicatorEnabled(true);}
并在其他片段中写下这段代码:
@Override
public void onResume()
{ super.onResume();
((HomeActivity)getActivity()).getSupportActionBar().setTitle("My Account");
((HomeActivity)getActivity()).actionBarDrawerToggle.setDrawerIndicatorEnabled(false);
((HomeActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
并在你的主要 activity 中写下 backpressed :
@Override
public void onBackPressed()
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
} else {
super.onBackPressed();
}
}
在我看来,所选答案太老套了。
我尝试实现它,但在这样做的过程中我意识到 ActionBarDrawerToggle
实际上没有什么用处(也许这就是为什么它从关于 [=14 的官方 android 教程中删除的原因=]): 当你想在导航抽屉和操作栏之间协调时,它不会让你的生活更轻松。
问题是您只有 1 个家 "button",并且它有 2 个不同的功能 - 在主屏幕中打开抽屉,并且当您在您的应用程序中处于更下方时,请向上。将工具栏作为参数传递给 ActionBarDrawerToggle
构造函数,向其添加菜单图标,并在单击事件时调用 openDrawer。现在,如果你想切换到向上事件,你必须关闭这个特殊图标,并重新启用操作栏固有的返回功能......这仍然是一团糟。
因此,如果 ActionBarDrawerToggle
对您没有帮助(但是,也许有人会想出办法解决它),为什么首先要使用它?以下是没有它的方法:
boolean homeShouldOpenDrawer; // flag for onOptionsItemSelected
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// if you're using NoActionBar theme
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionbar = getSupportActionBar();
// enables the home button with a <-
actionbar.setDisplayHomeAsUpEnabled(true);
// replaces the <- with the menu (hamburger) icon
// (ic_menu should be in every empty project, and can be easily added)
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);
// I assume your first fragment/state should be main screen, i.e. home = opens drawer
homeShouldOpenDrawer = true;
...
}
private void enableViews(boolean enable) {
if(enable) {
// Enables back button icon
// passing null or 0 brings back the <- icon
getSupportActionBar().setHomeAsUpIndicator(null);
homeShouldOpenDrawer = false;
} else {
// Enables burger icon
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
homeShouldOpenDrawer = true;
}
}
// this is called whenever a selection is made from the action bar
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (homeShouldOpenDrawer) {
drawerLayout.openDrawer(GravityCompat.START);
} else {
onBackPressed();
}
}
return super.onOptionsItemSelected(item);
}
最佳解决方案在这种情况下不起作用:
- 一个Activity和多个片段
- 一个片段 (SettingsFragment) 应该显示后退图标而不是汉堡菜单
- 使用 com.google.android.material.appbar.AppBarLayout、androidx.appcompat.widget.Toolbar 和 ActionBarDrawerToggle
我在 Activity 的 onCreate():
中调用了这个方法
private fun initBackStackChangeListener() {
supportFragmentManager.addOnBackStackChangedListener {
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (fragment is SettingsFragment) {
menuDrawerToggle?.isDrawerIndicatorEnabled = false
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
menuDrawerToggle?.setToolbarNavigationClickListener { onBackPressed() }
supportActionBar?.setDisplayHomeAsUpEnabled(true)
} else {
supportActionBar?.setDisplayHomeAsUpEnabled(false)
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
menuDrawerToggle?.isDrawerIndicatorEnabled = true
menuDrawerToggle?.toolbarNavigationClickListener = null
menuDrawerToggle?.syncState()
}
}
}
menuDrawerToggle 是这样的:
menuDrawerToggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
).apply {
drawer_layout.addDrawerListener(this)
this.syncState()
}
很有魅力。也许它对任何人都有帮助。
您可以使用以下内容来显示后退按钮而不是导航菜单。
(activity as MainActivity).supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_arrow_back)
我有最简单的 Kotlin 开发者解决方案
只需将其添加到您的根 activity 片段抵抗
if (supportFragmentManager.backStackEntryCount > 0) {
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
toolbar.setNavigationOnClickListener {
if (supportFragmentManager.backStackEntryCount > 0) {
super.onBackPressed()
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
drawerLayout.openDrawer(GravityCompat.START)
}
}
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
}
在这里,每当 setDisplayHomeAsUpEnabled
设置 true
时,我都会显示后退按钮。在点击它时,我正在调用 super.onBackPressed()
,这与您的后退按钮的作用相似!
我遇到了以下问题:
我知道如何设置工具栏以显示后退按钮图标而不是汉堡包按钮图标。
由此:
对此:
使用:getSupportActionBar().setDisplayHomeAsUpEnabled(true);
现在,我想做反向操作,我想从后退按钮图标转到汉堡图标:
到这里:
我该怎么做?
更新:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
private void enableViews(boolean enable) {
if(enable) {
// Enables back button icon
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
// TODO: Enables burger icon
}
}
您可以通过以下方式更改操作栏按钮:
getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
使用这个
getSupportActionBar().setDisplayShowHomeEnabled(true);
final Toolbar toolbar = (Toolbar) findViewById(R.id.actionbar);
toolbar.setTitle(Html.fromHtml("<font color=#ffffff>" + getString(R.string.print_s) + "</font>"));
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.menu_icon));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DetailActivity.this.finish();
}
});
toolbar.inflateMenu(R.menu.fav);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
item.setIcon(R.drawable.back_icon)
return true;
}
return false;
}
});
尝试将下面的 style
AppTheme
代码添加到您的 activity's theme/style.xml
中,这将使您的 hamburger icon
变为 back icon
animation
。
条件 如果您使用带有 NavigationDrawer
和 AppCompatActivity/ActionBarActivity
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="windowActionBar">false</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">@android:color/white</item>
</style>
希望对您有所帮助!或者你只需要用 drawable 来做。
勾选这个
如果我假设您在布局中使用 android.support.v4.widget.DrawerLayout
,那么这种方法可能适合您;我只在 API 21
上测试过,但鉴于它主要使用支持库,它 应该 在较低或较高的目标上工作(著名的遗言)。
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v4.widget.DrawerLayout
ActionBarDrawerToggle mDrawerToggle;
DrawerLayout drawerLayout;
private boolean mToolBarNavigationListenerIsRegistered = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
// Get DrawerLayout ref from layout
drawerLayout = (DrawerLayout)findViewById(R.id.drawer);
// Initialize ActionBarDrawerToggle, which will control toggle of hamburger.
// You set the values of R.string.open and R.string.close accordingly.
// Also, you can implement drawer toggle listener if you want.
mDrawerToggle = new ActionBarDrawerToggle (this, drawerLayout, mToolbar, R.string.open, R.string.close);
// Setting the actionbarToggle to drawer layout
drawerLayout.addDrawerListener(mDrawerToggle);
// Calling sync state is necessary to show your hamburger icon...
// or so I hear. Doesn't hurt including it even if you find it works
// without it on your test device(s)
mDrawerToggle.syncState();
}
/**
* To be semantically or contextually correct, maybe change the name
* and signature of this function to something like:
*
* private void showBackButton(boolean show)
* Just a suggestion.
*/
private void enableViews(boolean enable) {
// To keep states of ActionBar and ActionBarDrawerToggle synchronized,
// when you enable on one, you disable on the other.
// And as you may notice, the order for this operation is disable first, then enable - VERY VERY IMPORTANT.
if(enable) {
//You may not want to open the drawer on swipe from the left in this case
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
// Remove hamburger
mDrawerToggle.setDrawerIndicatorEnabled(false);
// Show back button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// when DrawerToggle is disabled i.e. setDrawerIndicatorEnabled(false), navigation icon
// clicks are disabled i.e. the UP button will not work.
// We need to add a listener, as in below, so DrawerToggle will forward
// click events to this listener.
if(!mToolBarNavigationListenerIsRegistered) {
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Doesn't have to be onBackPressed
onBackPressed();
}
});
mToolBarNavigationListenerIsRegistered = true;
}
} else {
//You must regain the power of swipe for the drawer.
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
// Remove back button
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
// Show hamburger
mDrawerToggle.setDrawerIndicatorEnabled(true);
// Remove the/any drawer toggle listener
mDrawerToggle.setToolbarNavigationClickListener(null);
mToolBarNavigationListenerIsRegistered = false;
}
// So, one may think "Hmm why not simplify to:
// .....
// getSupportActionBar().setDisplayHomeAsUpEnabled(enable);
// mDrawer.setDrawerIndicatorEnabled(!enable);
// ......
// To re-iterate, the order in which you enable and disable views IS important #dontSimplify.
}
该解决方案使用 ActionBarDrawerToggle.setDrawerIndicatorEnabled
切换汉堡包图标的可见性,并使用 ActionBar.setDisplayHomeAsUpEnabled
切换 Up 按钮的可见性,本质上是利用它们各自的drawable
资源。
其他假设
- 您的 Activity 主题扩展了
Theme.AppCompat.Light.NoActionBar
。
我在 The Google I/O 2017 Android App 中找到了灵活的解决方案。
public Toolbar getToolbar() {
if (mToolbar == null) {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
mToolbar.setNavigationContentDescription(R.string.navdrawer_description_a11y);
mToolbarTitle = (TextView) mToolbar.findViewById(R.id.toolbar_title);
if (mToolbarTitle != null) {
int titleId = getNavigationTitleId();
if (titleId != 0) {
mToolbarTitle.setText(titleId);
}
}
// We use our own toolbar title, so hide the default one
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
}
return mToolbar;
}
/**
* @param clickListener The {@link android.view.View.OnClickListener} for the navigation icon of
* the toolbar.
*/
protected void setToolbarAsUp(View.OnClickListener clickListener) {
// Initialise the toolbar
getToolbar();
if (mToolbar != null) {
mToolbar.setNavigationIcon(R.drawable.ic_up);
mToolbar.setNavigationContentDescription(R.string.close_and_go_back);
mToolbar.setNavigationOnClickListener(clickListener);
}
}
所以用法真的很简单
setToolbarAsUp(new View.OnClickListener() {
@Override
public void onClick(View v) {
// onBackPressed();
// or navigate to parent or some other intent
}
});
对我来说,我想通过 Fragment
左侧的 后退箭头 图标来更改 Burger 图标的 ActionBar,因为我使用的是 Navigation Drawer
。还在右侧添加一个 Menu。
在 Main Activity 中,它已经设置 - 默认情况下,当 Android Studio 为我创建导航抽屉时 - 如下所示:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
问题是如何在 Fragment
中自定义 ActionBar
,所以当我转到 Fragment
时,它会显示自定义的 ActionBar
以及后退箭头图标被点击,它应该离开片段并且ActionBar
应该回到第一个状态。
在片段中(完整实现):
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true); // To show the menu options
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
showActionBar(); // the method to change ActionBar
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// inflate the customized menu which already created in XML
getActivity().getMenuInflater().inflate(R.menu.fragment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// add implementation when user select an item from the menu
switch (item.getItemId()) {
case R.id.option1:
// do something
return true;
case R.id.option2:
// do something
return true;
case R.id.option3:
// do something
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void showActionBar() {
// get the ToolBar from Main Activity
final Toolbar toolbar = getActivity().findViewById(R.id.toolbar);
// get the ActionBar from Main Activity
final ActionBar actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
// inflate the customized Action Bar View
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.fragment_actionbar, null);
if (actionBar != null) {
// enable the customized view and disable title
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setCustomView(v);
// remove Burger Icon
toolbar.setNavigationIcon(null);
// add click listener to the back arrow icon
v.findViewById(R.id.back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// reverse back the show
actionBar.setDisplayShowCustomEnabled(false);
actionBar.setDisplayShowTitleEnabled(true);
//get the Drawer and DrawerToggle from Main Activity
// set them back as normal
DrawerLayout drawer = getActivity().findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
getActivity(), drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
// All that to re-synchronize the Drawer State
toggle.syncState();
// Implement Back Arrow Icon
// so it goes back to previous Fragment
getActivity().onBackPressed();
}
});
}
}
fragment_actionbar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_horizontal" >
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="@drawable/ic_menu_back"
android:layout_marginLeft="@dimen/_5sdp"
android:layout_alignParentStart="true"
android:layout_marginStart="@dimen/_5sdp" />
</RelativeLayout>
ic_menu_back.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="459"
android:viewportWidth="459">
<path
android:fillColor="#ffffff"
android:pathData="M178.5,140.25v-102L0,216.75l178.5,178.5V290.7c127.5,0,216.75,40.8,280.5,130.05C433.5,293.25,357,165.75,178.5,140.25z"/>
</vector>
fragment_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/border_shadow">
<item
android:id="@+id/option1"
android:title="@string/show_profile"
app:showAsAction="never"/>
<item
android:id="@+id/option2"
android:title="@string/report_pic"
app:showAsAction="never"/>
<item
android:id="@+id/option3"
android:title="@string/delete_pic"
app:showAsAction="never"/>
</menu>
我一直在我的应用程序上尝试其中一些示例,但其中 none 似乎有效。我正在使用片段,其中一些片段必须显示后退选项而不是主页。这是我的实现(在 Kotlin 中):
override fun onResume() {
super.onResume()
var drawerLayout: DrawerLayout = activity.findViewById(R.id.drawer_layout)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
var actionBar = (activity as MainActivity).supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(true)
var toggle= (activity as MainActivity).drawerToggle
toggle.isDrawerIndicatorEnabled = false
toggle.setToolbarNavigationClickListener { v -> activity.onBackPressed() }
}
override fun onStop() {
super.onStop()
var drawerLayout: DrawerLayout = activity.findViewById(R.id.drawer_layout)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
var actionBar = (activity as MainActivity).supportActionBar
actionBar!!.setDisplayHomeAsUpEnabled(false)
var toggle= (activity as MainActivity).drawerToggle
toggle.setToolbarNavigationClickListener {null}
toggle.syncState()
}
注意:这些是片段中重写的 onResume 和 onStop 方法。
备注: 汉堡包 图标只有在调用 toggle.syncState() 方法时才会显示。我已经将近 24 小时弄清楚为什么主页图标没有显示。
希望我的 post 可以帮助到别人。
-> 如果你家里有一个抽屉activity 和 initalfragment 你必须显示 drawertoggle 并且在内部 fragement 之后你不想显示抽屉代表抽屉你必须显示后退按钮并像这样更改所有片段的标题。
在 activity 中切换 public。
在你的主页片段中写下这段代码。
@Override public void onResume() { super.onResume(); ((HomeActivity)getActivity()).getSupportActionBar().setTitle("Home"); ((HomeActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false); ((HomeActivity)getActivity()).actionBarDrawerToggle.setDrawerIndicatorEnabled(true);}
并在其他片段中写下这段代码:
@Override public void onResume() { super.onResume(); ((HomeActivity)getActivity()).getSupportActionBar().setTitle("My Account"); ((HomeActivity)getActivity()).actionBarDrawerToggle.setDrawerIndicatorEnabled(false); ((HomeActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
并在你的主要 activity 中写下 backpressed :
@Override public void onBackPressed() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { getSupportFragmentManager().popBackStackImmediate(); } else { super.onBackPressed(); } }
在我看来,所选答案太老套了。
我尝试实现它,但在这样做的过程中我意识到 ActionBarDrawerToggle
实际上没有什么用处(也许这就是为什么它从关于 [=14 的官方 android 教程中删除的原因=]): 当你想在导航抽屉和操作栏之间协调时,它不会让你的生活更轻松。
问题是您只有 1 个家 "button",并且它有 2 个不同的功能 - 在主屏幕中打开抽屉,并且当您在您的应用程序中处于更下方时,请向上。将工具栏作为参数传递给 ActionBarDrawerToggle
构造函数,向其添加菜单图标,并在单击事件时调用 openDrawer。现在,如果你想切换到向上事件,你必须关闭这个特殊图标,并重新启用操作栏固有的返回功能......这仍然是一团糟。
因此,如果 ActionBarDrawerToggle
对您没有帮助(但是,也许有人会想出办法解决它),为什么首先要使用它?以下是没有它的方法:
boolean homeShouldOpenDrawer; // flag for onOptionsItemSelected
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// if you're using NoActionBar theme
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionbar = getSupportActionBar();
// enables the home button with a <-
actionbar.setDisplayHomeAsUpEnabled(true);
// replaces the <- with the menu (hamburger) icon
// (ic_menu should be in every empty project, and can be easily added)
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);
// I assume your first fragment/state should be main screen, i.e. home = opens drawer
homeShouldOpenDrawer = true;
...
}
private void enableViews(boolean enable) {
if(enable) {
// Enables back button icon
// passing null or 0 brings back the <- icon
getSupportActionBar().setHomeAsUpIndicator(null);
homeShouldOpenDrawer = false;
} else {
// Enables burger icon
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
homeShouldOpenDrawer = true;
}
}
// this is called whenever a selection is made from the action bar
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
if (homeShouldOpenDrawer) {
drawerLayout.openDrawer(GravityCompat.START);
} else {
onBackPressed();
}
}
return super.onOptionsItemSelected(item);
}
最佳解决方案在这种情况下不起作用:
- 一个Activity和多个片段
- 一个片段 (SettingsFragment) 应该显示后退图标而不是汉堡菜单
- 使用 com.google.android.material.appbar.AppBarLayout、androidx.appcompat.widget.Toolbar 和 ActionBarDrawerToggle
我在 Activity 的 onCreate():
中调用了这个方法private fun initBackStackChangeListener() {
supportFragmentManager.addOnBackStackChangedListener {
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (fragment is SettingsFragment) {
menuDrawerToggle?.isDrawerIndicatorEnabled = false
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
menuDrawerToggle?.setToolbarNavigationClickListener { onBackPressed() }
supportActionBar?.setDisplayHomeAsUpEnabled(true)
} else {
supportActionBar?.setDisplayHomeAsUpEnabled(false)
drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
menuDrawerToggle?.isDrawerIndicatorEnabled = true
menuDrawerToggle?.toolbarNavigationClickListener = null
menuDrawerToggle?.syncState()
}
}
}
menuDrawerToggle 是这样的:
menuDrawerToggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
).apply {
drawer_layout.addDrawerListener(this)
this.syncState()
}
很有魅力。也许它对任何人都有帮助。
您可以使用以下内容来显示后退按钮而不是导航菜单。
(activity as MainActivity).supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_arrow_back)
我有最简单的 Kotlin 开发者解决方案
只需将其添加到您的根 activity 片段抵抗
if (supportFragmentManager.backStackEntryCount > 0) {
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
toolbar.setNavigationOnClickListener {
if (supportFragmentManager.backStackEntryCount > 0) {
super.onBackPressed()
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
drawerLayout.openDrawer(GravityCompat.START)
}
}
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
}
在这里,每当 setDisplayHomeAsUpEnabled
设置 true
时,我都会显示后退按钮。在点击它时,我正在调用 super.onBackPressed()
,这与您的后退按钮的作用相似!