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?
If you are using an ActionBarActivity then you can tell Android to use the Toolbar as the ActionBar like so:
Toolbar toolbar = (Toolbar) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);
And then calls to
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
will work. You can also use that in Fragments that are attached to ActionBarActivities you can use it like this:
((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayShowHomeEnabled(true);
If you are not using ActionBarActivities or if you want to get the back arrow on a Toolbar that's not set as your SupportActionBar then you can use the following:
mActionBar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_action_back));
mActionBar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//What to do on back clicked
}
});
If you are using android.support.v7.widget.Toolbar, then you should add the following code to your AppCompatActivity:
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
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);
}
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
}
});
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();
}
});
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
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"/>
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!
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);
}
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) {
//....
}
});
In Kotlin it would be
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
}
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);
}
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());
}
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
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;
}
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;
}
}
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.
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
}
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
}
});
}
}
Follow 3 steps if you want to handle your problem fastly & simply:
Add file ic_arrow.xml to Drawable folder with some codes below (add codes below into ic_arrow.xml)
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:tint="#color/black"
android:viewportWidth="24"
android:viewportHeight="24"
tools:ignore="ExtraText">
<path
android:fillColor="#android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>
Add ImageButton to Toolbar (make sure the Toolbar customized, not Titlebar or Statusbar) - You can customize the ImageButton (arrow button) position if you want
<ImageButton
android:id="#+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_arrow"
android:layout_marginTop="15dp"
android:layout_marginStart="15dp"
android:background="#android:color/transparent"
tools:ignore="ContentDescription" />
Add the setArrowButton method to DetailActivity.java (or any xxxActivity.java that you need)
public class DetailActivity extends AppCompatActivity {
ImageButton arrowButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
arrowButton = findViewById(R.id.arrow);
setArrowButton(arrowButton);
}
public void setArrowButton(ImageButton arrowButton) {
arrowButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish(); //will close the moment activity and return to
//the last activity
}
});
}
}
Done
Preview about arrowButton
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)
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)
}
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.
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 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
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);
I set up Toolbar in my app (for the first time) but the I can't set the Home (/Up) button to do anything when clicked.
I have 3 activitives (MainActivity , Second , Third) and I've defined the toolbar in all 3 but nothing happens when I click the Home button in each of the activitis I want the button to do his (in my understanding) default action which is go back to the Home Activity which is "MainActivity".
Here is some relevant code:
Toolbar layout (named: app_bar.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/toolBar_background"
android:elevation="5dp"
android:title="#string/app_name" />
</RelativeLayout>
my 3 activities layout xmls:
Activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.noamm_000.finaltoolbarproject.MainActivity">
<include layout="#layout/app_bar"/>
//More layout code...
Activity_Second.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.noamm_000.finaltoolbarproject.Second">
<include layout="#layout/app_bar"/>
//More layout code...
Activity_Third.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.noamm_000.finaltoolbarproject.Third">
<include layout="#layout/app_bar"/>
//More layout code
Actually all the 3 activities simply include the toolbar layout which names "app_bar.xml".
Here is part of my Mainfest file where I configured the app_parent:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Second"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
<intent-filter>
<action android:name="com.example.noamm_000.finaltoolbarproject.Second" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".Third"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
<intent-filter>
<action android:name="com.example.noamm_000.finaltoolbarproject.Third" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
and ofcourse parts of my java code for each of my 3 activities:
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar_id);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
mainBtn = (Button) findViewById(R.id.btn_main);
openSecondActivity();
}
public void openSecondActivity(){
mainBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent("com.example.noamm_000.finaltoolbarproject.Second");
startActivity(intent);
}
});
SecondActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btnSecond = (Button) findViewById(R.id.btn_second);
toolbar = (Toolbar) findViewById(R.id.toolbar_id);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
openThirdActivity();
}
public void openThirdActivity(){
btnSecond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent("com.example.noamm_000.finaltoolbarproject.Third");
startActivity(intent);
}
});
}
and ThirdActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
toolbar = (Toolbar) findViewById(R.id.toolbar_id);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
}
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.toolbar_menu,menu);
return super.onCreateOptionsMenu(menu);
}
You can see that all 3 Activities "onCreate" functions are pretty much the same..
When I start my app I can see the toolbar in all 3 activities and I can see the back arrow in all but clicking it do nothing.
I know I can set the toolbar.setNavigationOnClickListener but I just want it to make it default action which is go to home activity....
Thank you very much,
Noam
Try like this...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == android.R.id.home) {
Intent i = new Intent(CurrentActivity.this, HomeActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
//finish(); or Do wahtever you wnat to do
return true;
}
return true;
}
If you are having parent activity,Follow this code,
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
if(NavUtils.getParentActivityIntent(this)== null) {
onBackPressed();
}else{
NavUtils.navigateUpFromSameTask(this);
}
break;
}
return super.onOptionsItemSelected(item);
}
Try this in your activities
#Override
public boolean onOptionsItemIdSelected(int id) {
switch (id) {
case R.id.home:
//do stuff
break;
}
return true;
}
In your case, I recommend to you create a AbstractActivity which inherit all your activities. So you can factor a number of behavior , including management of the toolbar button
I want to use this theme in my preference activity because of the nice checkbox but my action bar isn't showing.
If you don't want to use PreferenceFragment inside an ActionBarActivity and still want to use your existing PreferenceActivity with AppCompat Support Library v7, you can use to use Toolbar and override PreferenceActvity.setContentView() with a customized layout
You can use Toolbar support while maintaining the current PreferenceActivity and it works well for 2.3.4 and above
private Toolbar mActionBar;
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Theme_MyApp_Settings);
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
mActionBar.setTitle(getTitle());
//other things to create/init
}
public void setContentView(int layoutResID) {
ViewGroup contentView = (ViewGroup) LayoutInflater.from(this).inflate(
R.layout.settings_activity, new LinearLayout(this), false);
mActionBar = (Toolbar) contentView.findViewById(R.id.action_bar);
mActionBar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
ViewGroup contentWrapper = (ViewGroup) contentView.findViewById(R.id.content_wrapper);
LayoutInflater.from(this).inflate(layoutResID, contentWrapper, true);
getWindow().setContentView(contentView);
}
settings_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize" />
<FrameLayout
android:id="#+id/content_wrapper"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
styles.xml
<style name="Theme.MyApp.Settings" parent="#style/Theme.AppCompat">
<item name="android:windowNoTitle">true</item>
<item name="toolbarStyle">#style/Widget.Toolbar</item>
</style>
<style name="Widget.Toolbar" parent="#style/Widget.AppCompat.Toolbar">
<item name="android:background">?attr/colorPrimary</item>
<item name="navigationIcon">?attr/homeAsUpIndicator</item>
</style>
PreferenceActivity does not extend ActionBarActivity, which is required for action bar to be available.
If you need a preferences screen with action bar, try to use PreferenceFragment inside an ActionBarActivity instead.
public class SettingsActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
public static class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
...
}
Reference: http://developer.android.com/guide/topics/ui/settings.html#Fragment
I'm trying to display a actionbar in my preference screen.
In order to do so I added the following code in my SettingActivity
public class PreferencesActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
getFragmentManager().beginTransaction()
.replace(R.id.container, new PreferencesFragment()).commit();
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
then the rest of my code in PreferencesFragment.
This works fine, but as soon as I press on a PreferenceScreen preference, the actionbar is hidden. If I go back to the preference main screen I can see it again.
Any idea how to keep the actionbar displayed (and updated with the PreferenceScreen label) ?
Edit: Looking at the PreferenceScreen code it looks like a full screen Dialog is opened when the PreferenceScreen is clicked on. Because my preference has a title the Dialog should display a title as well... but it doesn't
// Set the title bar if title is available, else no title bar
final CharSequence title = getTitle();
Dialog dialog = mDialog = new Dialog(context, context.getThemeResId());
if (TextUtils.isEmpty(title)) {
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
} else {
dialog.setTitle(title);
}
I finally managed to find a way to do this.
It's kind of ugly but it works.
First I add an the same Intent to every PreferenceScreen definition in my preferences.xml file (make sure to update the value of the extra parameter)
<PreferenceScreen
android:key="pref1"
android:summary="Summary1"
android:title="Title1" >
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="my.package"
android:targetClass="my.package.activity.PreferencesActivity" >
<extra android:name="page" android:value="pref1" />
</intent>
...
</PreferenceScreen>
BTW my.package.activity.PreferencesActivity is my current Preference Activity
Then I add an intent-filter in the Manifest
<activity
android:name=".activity.PreferencesActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="#string/settings" >
<intent-filter android:label="Pref" >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
I add some code in the PreferenceActivity to handle this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences_activity);
this.fragment = new PreferencesFragment();
this.fragment.setActivityIntent(getIntent());
getFragmentManager().beginTransaction()
.replace(R.id.container, this.fragment).commit();
}
Finally I add the following code in my PreferencesFragment class
public void setActivityIntent(final Intent activityIntent) {
if (activityIntent != null) {
if (Intent.ACTION_VIEW.equals(activityIntent.getAction())) {
if (intent.getExtras() != null) {
final String page = intent.getExtras().getString("page");
if (!TextUtils.isEmpty(page)) {
openPreferenceScreen(page);
}
}
}
}
private void openPreferenceScreen(final String screenName) {
final Preference pref = findPreference(screenName);
if (pref instanceof PreferenceScreen) {
final PreferenceScreen preferenceScreen = (PreferenceScreen) pref;
((PreferencesActivity) getActivity()).setTitle(preferenceScreen.getTitle());
setPreferenceScreen((PreferenceScreen) pref);
}
}
Had the same issue. Nested PreferenceScreens did not have an ActionBar. After stepping through the code, it appears to be caused by a conflict between AppCompatActivity and PreferenceScreen.
On one hand AppCompatActivity provides its own action bar, and therefore requires a theme descending from Theme.AppCompat which specifies windowNoTitle = true somewhere (could not pinpoint exactly where). On the other -- PreferenceScreen uses platform Dialog with the activity theme (rather than sub-theme, e.g., dialogTheme). Could be a bug.
If you don't care about Theme.AppCompat, here's a simple workaround that works on API 21+:
use android.preference.PreferenceActivity as the base class for your activity
create a theme for that activity:
<!-- This theme is used to show ActionBar on sub-PreferenceScreens -->
<style name="PreferenceTheme" parent="">
<item name="android:windowActionBar">true</item>
<item name="android:windowNoTitle">false</item>
</style>
specify android:theme="#style/PreferenceTheme" for this activity in the AndroidManifest.xml
What you'll get is more like a standard window title than a full ActionBar. I haven't yet figured out how to add a working back button, etc.
If you want to remain compatible with AppCompatActivity and the related themes, you'll need to request FEATURE_NO_TITLE on the activity window. Otherwise, you'll end up with two action bars (the built-in on top, and the support on bottom) in the top-level PreferenceScreen.
Since google sadly didn't fixed it until now, there is actually one much easier solution:
Set your SettingsActivity class to extend from just "Activity".
public class SettingsActivity extends Activity { ...
Create a new Theme in your v21/styles folder for your SettingsActivty and set the parent to "Theme.Material.*"
<style name="CustomThemeSettings" parent="android:Theme.Material">
<item name="android:colorPrimary">#color/...</item>
<item name="android:colorPrimaryDark">#color/...</item>
<item name="android:colorAccent">#color/...</item>
</style>
Set your new theme in your Manifest.xml file:
<activity
android:name=".SettingsActivity"
android:label="#string/title_activity_settingsactivity"
android:theme="#style/CustomThemeSettings" >
</activity>
It just works :)
(Optional) If you want to provide Material Design support for older Devices
you can put the SettingsActivity in an v21+ folder and create a other
SettingsActivity for older devices which has the parent AppCompat.
I have made an app that does have an action bar in the preferences activity. I can't seem to see the key to doing that, although I do remember it took me some time to nail it right.
It seems like our codes are quite similar. The only thing that gets to my attention is this import: import android.support.v7.app.ActionBarActivity;
Let me know if that helps any
public class SettingsActivity extends ActionBarActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment() ).commit();
} // End of onCreate
static public class PrefsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences); // Load the preferences from an XML resource
}
} // end of PrefsFragment
}
Addition: do you have this in your styles.xml?
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
but as soon as I press on a PreferenceScreen preference, the actionbar is hidden. If I go back to the preference main screen I can see it again.
I guess you are launching a new activity when clicked on the preference
Your Preference fragment should look like this
public static class PreferencesFragment extends PreferenceFragment {
public PlaceholderFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.your_preferences);
}
}
Then sample your_preferences as below
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent" >
<PreferenceCategory
android:title="#string/pref_category_title">
<PreferenceScreen
android:title="#string/title"
android:summary="#string/summary">
<intent
android:targetClass="com.your.package.Youractivity "
android:targetPackage="com.your.package"/>
</PreferenceScreen>
<PreferenceScreen
android:title="#string/another_title">
<intent
android:targetClass="com.your.package.activity2"
android:targetPackage="com.your.package.activity"/>
</PreferenceScreen>
</PreferenceCategory>
And finally the main thing Youractivity should extend from ActionBarActivity
public class Youractivity extends ActionBarActivity {
}
The above code works for me.
As you mentioned in the question the fullscreen Dialog might be a problem.
Try to change the Dialog style to:
<style name="Theme.Holo.Dialog">
or to style which has these properties:
<item name="windowActionBar">true</item>
<item name="windowNoTitle">false</item>
Here you can read how to get reference to the Dialog.
Note: Only for API>=14
Source1 and Source2
PreferenceActivity1.java
public class PreferenceActivity1 extends android.preference.PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref1);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
}
PreferenceActivity2.java
public class PreferenceActivity2 extends android.preference.PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref2);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
LinearLayout root = (LinearLayout)findViewById(android.R.id.list).getParent().getParent().getParent();
Toolbar bar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.settings_toolbar, root, false);
root.addView(bar, 0); // insert at top
bar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
}
settings_toolbar.xml(layout)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
app:navigationContentDescription="#string/abc_action_bar_up_description"
android:background="?attr/colorPrimary"
app:navigationIcon="?attr/homeAsUpIndicator"
app:title="#string/app_name"
/>
pref1.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#android:style/Theme.Light" >
<PreferenceCategory android:title="Main Preferences" >
<CheckBoxPreference
android:key="wifi enabled"
android:title="WiFi" />
</PreferenceCategory>
<PreferenceScreen
android:key="key1"
android:summary=""
android:title="Wifi Settings" >
<intent
android:action="android.intent.action.VIEW"
android:targetClass="com.example.PreferenceActivity2"
android:targetPackage="com.example" />
</PreferenceScreen>
</PreferenceScreen>
pref2.xml(xml)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#android:style/Theme.Light" >
<PreferenceCategory android:title="Wifi Settings" >
<CheckBoxPreference
android:key="prefer wifi"
android:title="Prefer WiFi" />
</PreferenceCategory>
</PreferenceScreen>
Manifest
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="com.example.PreferenceActivity1"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.PreferenceActivity2"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
Result
I created PreferenceCompatActivity that is an AndroidX-compatible drop-in replacement for the old PreferenceActivity.
It uses a compat fragment internally. Be sure to use the import only the androidx.preference.XXX classes instead of the android.preference.XXX ones.
public class PreferenceCompatActivity extends AppCompatActivity implements AppCompatCallback, PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private PreferenceFragmentCompat fragment;
public void addPreferencesFromResource(#XmlRes int preferencesResId) {
fragment = new RootPreferencesFragment(preferencesResId);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commitNow();
}
public PreferenceManager getPreferenceManager() {
return fragment.getPreferenceManager();
}
public PreferenceScreen getPreferenceScreen() {
return fragment.getPreferenceScreen();
}
public Preference findPreference(CharSequence key) {
return fragment.findPreference(key);
}
#Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
LowerPreferencesFragment lowerFragment = new LowerPreferencesFragment(pref);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, lowerFragment).addToBackStack("lower").commit();
return true;
}
public static class RootPreferencesFragment extends PreferenceFragmentCompat {
private int preferencesResId;
public RootPreferencesFragment(int preferencesResId) {
this.preferencesResId = preferencesResId;
}
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(preferencesResId);
}
}
public static class LowerPreferencesFragment extends PreferenceFragmentCompat {
private PreferenceScreen prefs;
public LowerPreferencesFragment() {
}
public LowerPreferencesFragment(PreferenceScreen prefs) {
this.prefs = prefs;
}
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
if (prefs != null) {
setPreferenceScreen(prefs);
prefs = null;
}
}
}
}
Or see this gist.