I'm migrating from ActionBar
to Toolbar
in my application.
But I don't know how to display and set click event on Back Arrow on Toolbar
like I did on Actionbar
.
With ActionBar
, I call mActionbar.setDisplayHomeAsUpEnabled(true)
.
But there is no the similar method like this.
Has anyone ever faced this situation and somehow found a way to solve it?
This question is related to
android
android-actionbar
android-actionbar-compat
android-toolbar
I see a lot of answers but here is mine which is not mentioned before. It works from API 8+.
public class DetailActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
// toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// add back arrow to toolbar
if (getSupportActionBar() != null){
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle arrow click here
if (item.getItemId() == android.R.id.home) {
finish(); // close this activity and return to preview activity (if there is any)
}
return super.onOptionsItemSelected(item);
}
Simple and easy way to show back button on toolbar
Paste this code in onCreate method
if (getSupportActionBar() != null){
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
Paste this override method outside the onCreate method
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()== android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
This worked perfectly
public class BackButton extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_box);
Toolbar chatbox_toolbar=(Toolbar)findViewById(R.id.chat_box_toolbar);
chatbox_toolbar.setTitle("Demo Back Button");
chatbox_toolbar.setTitleTextColor(getResources().getColor(R.color.white));
setSupportActionBar(chatbox_toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
chatbox_toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Define Back Button Function
}
});
}
}
you can use the tool bar setNavigationIcon method. Android Doc
mToolBar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
mToolBar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handleOnBackPress();
}
});
First, you need to initialize the toolbar :
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
then call the back button from the action bar :
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
If your are using the androidx.appcompat.app.AppCompatActivity
just use:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Then just define in the Manifest.xml
the parent Activity.
<activity
android:name=".MyActivity"
...>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ParentActivity" />
</activity>
Instead if you are using a Toolbar
and you want a custom behavior just use:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
app:navigationIcon="?attr/homeAsUpIndicator"
.../>
and in your Activity:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//....
}
});
If you are using JetPack Navigation.
Here is the layout for MainActivity
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolBar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toBottomOf="@id/toolBar"
app:layout_constraintBottom_toTopOf="parent"
app:navGraph="@navigation/nav_graph"/>
SetUp your toolbar in your activity like below in onCreate() of your Activity class.
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
val navController = navHostFragment.findNavController()
val toolBar = findViewById<Toolbar>(R.id.toolBar)
setSupportActionBar(toolBar) // To set toolBar as ActionBar
setupActionBarWithNavController(navController)
setupActionBarWithNavController(navController) Will create a back button on the toolBar if needed and handles the backButton functionality. If you need to write a CustomBack functionality, create a callBack as below on your fragment onCreate() method
val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
// Handle the back button event
}
From Documentation:https://developer.android.com/guide/navigation/navigation-custom-back
You can always add a Relative layout
or a Linear Layout
in your Toolbar
and place a Image view for back icon or close icon anywhere in toolbar as you like
For example I have used Relative layout in my toolbar
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_top"
android:layout_width="match_parent"
android:layout_height="35dp"
android:minHeight="?attr/actionBarSize"
android:nextFocusDown="@id/netflixVideoGridView"
app:layout_collapseMode="pin">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Myflix"
android:textAllCaps="true"
android:textSize="19sp"
android:textColor="@color/red"
android:textStyle="bold" />
<ImageView
android:id="@+id/closeMyFlix"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
app:srcCompat="@drawable/vector_close" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
And it looks like this:
You can add click listener on that image view from Activity or fragment like this.
closeMyFlix.setOnClickListener({
Navigator.instance.showFireTV( activity!!.supportFragmentManager)
})
If you want to get the back arrow on a Toolbar that's not set as your SupportActionBar:
(kotlin)
val resId = getResIdFromAttribute(toolbar.context, android.R.attr.homeAsUpIndicator)
toolbarFilter.navigationIcon = ContextCompat.getDrawable(toolbar.context, resId)
toolbarFilter.setNavigationOnClickListener { fragmentManager?.popBackStack() }
to get res from attributes:
@AnyRes
fun getResIdFromAttribute(context: Context, @AttrRes attr: Int): Int {
if (attr == 0) return 0
val typedValueAttr = TypedValue()
context.theme.resolveAttribute(attr, typedValueAttr, true)
return typedValueAttr.resourceId
}
If you are using DrawerLayout with ActionBarDrawerToggle, then to show Back button instead of Menu button (and viceversa), you need to add this code in your Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.application_name, R.string.application_name);
mDrawerLayout.addDrawerListener(mDrawerToggle);
mDrawerToggle.setHomeAsUpIndicator(R.drawable.ic_arrow_back_white_32dp);
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed(); // Or you can perform some other action here when Back button is clicked.
}
});
mDrawerToggle.syncState();
// ...
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item))
return true;
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
// ...
}
return super.onOptionsItemSelected(item);
}
public void showBackInToolbar(boolean isBack) {
// Remove next line if you still want to be able to swipe to show drawer menu.
mDrawerLayout.setDrawerLockMode(isBack ? DrawerLayout.LOCK_MODE_LOCKED_CLOSED : DrawerLayout.LOCK_MODE_UNLOCKED);
mDrawerToggle.setDrawerIndicatorEnabled(!isBack);
mDrawerToggle.syncState();
}
So when you need to show Back button instead of Menu button, call showBackInToolbar(true), and if you need Menu button, call showBackInToolbar(false).
You can generate back arrow (ic_arrow_back_white_32dp) over here, search arrow_back in Clipart section (use default 32dp with 8dp padding). Just select the color you want.
In the AppCompatActivity
for example you can do
public class GrandStatActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_grand_stat);
}
@Override
public void onResume() {
super.onResume();
// Display custom title
ActionBar actionBar = this.getSupportActionBar();
actionBar.setTitle(R.string.fragment_title_grandstats);
// Display the back arrow
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
// Back arrow click event to go to the parent Activity
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
}
If you don't want to create a custom Toolbar
, you can do like this
public class GalleryActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
...
getSupportActionBar().setTitle("Select Image");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
}
In you AndroidManifest.xml
<activity
android:name=".GalleryActivity"
android:theme="@style/Theme.AppCompat.Light">
</activity>
you can also put this android:theme="@style/Theme.AppCompat.Light"
to <aplication>
tag, for apply to all activities
Easily you can do it.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
Credits: https://freakycoder.com/android-notes-24-how-to-add-back-button-at-toolbar-941e6577418e
Add this to activity's xml in layout folder:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/prod_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
Make toolbar clickable, add these to onCreate method:
Toolbar toolbar = (Toolbar) findViewById(R.id.prod_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
With Kotlin it became:
Xml:
<include
android:id="@+id/tbSignToolbar "
layout="@layout/toolbar_sign_up_in"/>
In your Activity:-
setSupportActionBar(tbSignToolbar as Toolbar?)//tbSignToolbar :id of your toolbar
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
I used this method from the Google Developer Documentation:
@Override
public void onCreate(Bundle savedInstanceState) {
...
getActionBar().setDisplayHomeAsUpEnabled(true);
}
If you get a null pointer exception it could depend on the theme. Try using a different theme in the manifest or use this alternatively:
@Override
public void onCreate(Bundle savedInstanceState) {
...
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
Then in the manifest, where I set the parent activity for current activity:
<activity
android:name="com.example.myapp.MyCurrentActivity"
android:label="@string/title_activity_display_message"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myapp.MyMainActivity" />
</activity>
I hope this will help you!
Possibly a more reliable way to get the up icon from your theme (if not using the toolbar as your action bar):
toolbar.navigationIcon = context.getDrawableFromAttribute(R.attr.homeAsUpIndicator)
In order to turn the theme attribute into a drawable I used an extension function:
fun Context.getDrawableFromAttribute(attributeId: Int): Drawable {
val typedValue = TypedValue().also { theme.resolveAttribute(attributeId, it, true) }
return resources.getDrawable(typedValue.resourceId, theme)
}
MyActivity extends AppCompatActivity {
private Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
toolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(arrow -> onBackPressed());
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.back_arrow); // your drawable
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed(); // Implemented by activity
}
});
And for API 21+ android:navigationIcon
<android.support.v7.widget.Toolbar
android:navigationIcon="@drawable/back_arrow"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
maybe it will help someone,I didn't find in the answares the thing I did by the end: with ActionBarDrawerToggle mDrawerToggle; to show the back arrow in toolbar set: mDrawerToggle.setDrawerIndicatorEnabled(false);
and if you want it to show the hamburger in the toolbar:
mDrawerToggle.setDrawerIndicatorEnabled(true);
private fun setupToolbar(){
toolbar.title = getString(R.string.YOUR_TITLE)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
}
// don't forget click listener for back button
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}
There are many ways to achieve that, here is my favorite:
Layout:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="?attr/homeAsUpIndicator" />
Activity:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// back button pressed
}
});
If you were using AppCompatActivity
and have gone down the path of not using it, because you wanted to not get the automatic ActionBar
that it provides, because you want to separate out the Toolbar
, because of your Material Design needs and CoordinatorLayout
or AppBarLayout
, then, consider this:
You can still use the AppCompatActivity
, you don't need to stop using it just so that you can use a <android.support.v7.widget.Toolbar>
in your xml. Just turn off the action bar style as follows:
First, derive a style from one of the NoActionBar themes that you like in your styles.xml
, I used Theme.AppCompat.Light.NoActionBar
like so:
<style name="SuperCoolAppBarActivity" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">@color/primary_dark</item>
...
...
</style>
In your App's manifest, choose the child style theme you just defined, like so:
<activity
android:name=".activity.YourSuperCoolActivity"
android:label="@string/super_cool"
android:theme="@style/SuperCoolAppBarActivity">
</activity>
In your Activity Xml, if the toolbar is defined like so:
...
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
/>
...
Then, and this is the important part, you set the support Action bar to the AppCompatActivity that you're extending, so that the toolbar in your xml, becomes the action bar. I feel that this is a better way, because you can simply do the many things that ActionBar allows, like menus, automatic activity title, item selection handling, etc. without resorting to adding custom click handlers, etc.
In your Activity's onCreate override, do the following:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_super_cool);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Your toolbar is now an action bar and you can use it like you always do, for example:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
In your manifest file for the activity where you want to add a back button, we will use the property android:parentActivityName
<activity
android:name=".WebActivity"
android:screenOrientation="portrait"
android:parentActivityName=".MainActivity"
/>
P.S. This attribute was introduced in API Level 16.
Source: Stackoverflow.com