Android - 将ActionBar后退按钮切换到导航按钮

时间:2016-04-12 17:07:35

标签: android android-actionbar navigation-drawer android-toolbar back-button

我遇到以下问题:

我知道如何设置工具栏以显示后退按钮图标而不是汉堡按钮图标。

由此:
enter image description here

到此:

enter image description here

使用:getSupportActionBar().setDisplayHomeAsUpEnabled(true);

现在,我想做反向动作,我想从后退按钮图标转到汉堡图标:

enter image description here

到这里:

enter image description here

我该怎么做?

更新

@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
    }
}

13 个答案:

答案 0 :(得分:105)

如果我假设您在布局中使用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.setDrawerListener(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资源。

其他假设

  • 您的活动主题扩展为Theme.AppCompat.Light.NoActionBar

答案 1 :(得分:3)

我在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
    }
});

答案 2 :(得分:1)

您可以使用以下命令更改操作栏按钮

        getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

答案 3 :(得分:1)

我已经在我的App上尝试了其中一些示例,但是似乎都没有用。我正在使用片段,其中一些片段必须显示back选项而不是home。这是我的实现(在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()方法时才会显示 hamburger 图标。我已经花了将近24小时的时间才弄清楚为什么没有显示主页图标。

希望我的帖子可以帮助某人。

答案 4 :(得分:1)

我认为选择的答案太不客气了。

我尝试实现它,同时我意识到ActionBarDrawerToggle实际上没有什么用(也许就是为什么它从关于Navigation Drawer的官方android教程中删除了):要在导航抽屉和操作栏之间进行协调,不会让您的生活更轻松。

问题是您只有1个主页“按钮”,并且具有2种不同的功能-在主屏幕中打开抽屉,然后上移ActionBarDrawerToggle构造函数,向其中添加菜单图标,并在click事件上调用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);
}

答案 5 :(得分:1)

在这种情况下,最佳解决方案无效:

  • 一个活动和多个片段
  • 一个片段(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()
    }

像魅力一样工作。也许对任何人都有帮助。

答案 6 :(得分:0)

使用此

getSupportActionBar().setDisplayShowHomeEnabled(true);

答案 7 :(得分:0)

Sub import()

Dim Range_to_Copy As Range
Dim Range_Destination As Range

Dim Sheet_Data As Worksheet 'sheet from where we pull the data
Dim Sheet_Destination As Worksheet ' destination
Dim workbook_data As Workbook
Dim workbook_destination As Workbook



Set workbook_data = "N:\blah\deposit" & "\*" & ActiveWorkbook.Name
Set workbook_detination = ActiveWorkbook
Set Sheet_Data = ThisWorkbook.Sheets("Sheet1") 'help, how do i do this?
Set Sheet_Destination = ThisWorkbook.Sheets("Sheet1") ' and this?

Set Range_to_Copy = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row

Set Range_Destination = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row

Range_to_Copy.Copy Range_Destination  'this copies from range A to B (basically A.copy B), but i changed variable names to make it easier...


'you can simplify without variables like this:
'Sheets("Sheet1").Range("D1").Copy Sheets("Summary).Range("A1")          <=====    does the same as the above coding

答案 8 :(得分:0)

尝试将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>

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>Testing...</h1>'
})

export class AppComponent {
  title = 'Tour of Heroes';
}

我希望它有所帮助!或者你只需​​要用drawable来做。

选中此link

答案 9 :(得分:0)

对我来说,我想通过Fragment的ActionBar左侧的 Back Arrow 图标更改 Burger 图标,因为我使用的是Navigation Drawer。另外在右侧添加菜单

主要活动中,它已经设置 - 默认情况下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();

问题是如何自定义ActionBar中的Fragment,因此当我转到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>

答案 10 :(得分:0)

->如果您有关于家庭活动和初始片段的抽屉,则必须显示抽屉切换,内部碎裂之后,您不想显示抽屉代表抽屉,则必须显示“后退”按钮并更改所有碎裂的标题这样。

  • 在活动中公开动作栏。

  • 在您的家庭片段中编写以下代码。

    @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);
        }
    
  • ,然后在您的主要活动中写上backpressed:

    @Override
        public void onBackPressed() 
        {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
    
                getSupportFragmentManager().popBackStackImmediate();
    
            } else {
    
                super.onBackPressed();
    
            }
        }
    

答案 11 :(得分:0)

您可以使用以下命令显示后退按钮,而不是导航菜单。

(activity as MainActivity).supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_arrow_back)

答案 12 :(得分:0)

我为Kotlin开发人员提供了最简单的解决方案

只需在片段抵抗的根活动中添加

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(),它与您的后退按钮的作用类似!