Android - Switch ActionBar Back Button to Navigati

2019-01-04 09:46发布

I am having the following problem:

I know how to set up a toolbar to show a back button icon instead of a burger button icon.

From this:
enter image description here

to this:

enter image description here

using: getSupportActionBar().setDisplayHomeAsUpEnabled(true);


Now, I want to do the reverse action, I want to go from back button icon to burger icon:

enter image description here

to here:

enter image description here

How can I do this?

Update:

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

10条回答
成全新的幸福
2楼-- · 2019-01-04 10:00

For me, I wanted to change the Burger icon by a Back Arrow icon on the left side of Fragment's ActionBar as I am using a Navigation Drawer. Also Adding a Menu on the right side.

In Main Activity, it's already set - by default when Android Studio create the Navigation Drawer for me - like this:

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();

The issue is how to customize the ActionBar in the Fragment, so when I go to the Fragment it shall show me the customized ActionBar and when the Back Arrow icon is clicked, it shall leave the fragment and the ActionBar should back to the first state.

In Fragment (Complete Implementation):

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

查看更多
啃猪蹄的小仙女
3楼-- · 2019-01-04 10:05

I found flexible solutions in 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);
    }
}

So the usage is really simple.

setToolbarAsUp(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // onBackPressed();
        // or navigate to parent or some other intent
    }
});
查看更多
Viruses.
4楼-- · 2019-01-04 10:07

Try adding below code of style AppTheme to your activity's theme/style.xml it will make your hamburger icon to back icon with animation.

Condition if you are using hamburger icon with NavigationDrawer and 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>

I hope it helps! or you just have to do it with drawable only.

Check this link

查看更多
Ridiculous、
5楼-- · 2019-01-04 10:08

The selected answer is too hacky in my opinion.

I tried implementing it, and while doing so I realized that there's actually no good use for the ActionBarDrawerToggle (maybe that is why it was removed from the official android tutorial regarding Navigation Drawer): it doesn't make your life easier when you want to co-ordinate between the navigate drawer and the action bar.

The problem is that you only have 1 home "button", and that it has 2 different functionalities - open the drawer when you are in the main screen, and go up when you are further down in your app. Passing the toolbar as a parameter to ActionBarDrawerToggle constructor, adds the menu icon to it, and calls openDrawer on click event. Now if you want to switch to an up event you have to turn off this special icon, and re-enable the inherent back functionality of the action bar... which is still a mess.

So if ActionBarDrawerToggle doesn't help you (yet, maybe someone will figure out a way where it does), why use it in the first place? Here's how to do it without it:

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);
}
查看更多
霸刀☆藐视天下
6楼-- · 2019-01-04 10:08

Use this

getSupportActionBar().setDisplayShowHomeEnabled(true);
查看更多
欢心
7楼-- · 2019-01-04 10:10

you can change the action bar button with:

        getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
查看更多
登录 后发表回答