I want to create my own ActionBar Layout.
Like this (created in Paint for example)
Is it possible to give the second Button the Up-Navigation Properties? So if I press it, it finish this Activity and starts it's parent.
I want to have the burger Icon for the Navigation Drawer, the Up-Icon for Up-Navigation and the Title of the Activity.
Is it possible? Or is there a solution already?
Actually, it's fairly easy(though it's little hacky) to do.
First, create a drawable for back button(preferably - as a selector, to distinguish pressed/normal state:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/back_button_pressed"/>
<item android:drawable="#drawable/back_button"/>
</selector>
Next, set this drawable to the logo of the toolbar toolbar.setLogo(R.drawable.back_button_selector);
Then the only thing left is to set click-listener.
View logoView = getToolbarLogoIcon(toolbar);
logoView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
...
private View getToolbarLogoIcon(Toolbar toolbar){
//check if contentDescription previously was set
boolean hadContentDescription = android.text.TextUtils.isEmpty(toolbar.getLogoDescription());
String contentDescription = String.valueOf(!hadContentDescription ? toolbar.getLogoDescription() : "logoContentDescription");
toolbar.setLogoDescription(contentDescription);
ArrayList<View> potentialViews = new ArrayList<>();
//find the view based on it's content description, set programatically or with android:contentDescription
toolbar.findViewsWithText(potentialViews,contentDescription, View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
//Nav icon is always instantiated at this point because calling setLogoDescription ensures its existence
View logoIcon = null;
if (potentialViews.size() > 0) {
logoIcon = potentialViews.get(0);
}
//Clear content description if not previously present
if (hadContentDescription) {
toolbar.setLogoDescription(null);
}
return logoIcon;
}
(Thanks Nicola's post here). Or if you are not scared of reflection, it can be easily done like this:
try {
Field declaredField = toolbar.getClass().getDeclaredField("mLogoView");
declaredField.setAccessible(true);
View logoView = (View) declaredField.get(toolbar);
logoView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
} catch (Exception ex) {
//error
}
Another possible solution would be to set custom layout to the ActionBar.
Though, I'm advocating to follow the UI/UX guidelines and double-check, if navigation drawer is essential in the secondary activity.
I am using AppCompat action bar and i want to change the back icon of the searchview I use in the action bar. I searched but i couldn't find a solution.
I have tried setting the icon in the style :
<item name="homeAsUpIndicator">#drawable/myBackButton</item>
but I want to set another one programmatically when the user selects the search view.
Any ideas on how I can do it?
To customize SearchView "up" icon, you can use style attribute:
collapseIcon="#drawable/ic_discard_icon"
in your Toolbar layout:
<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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:collapseIcon="#drawable/ic_discard_icon"/>
Or you can move this attribute into Toolbar style. As you wish.
Try this code snippet:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// get the parent view of home (app icon) imageview
ViewGroup home = (ViewGroup) findViewById(android.R.id.home).getParent();
// get the first child (up imageview)
( (ImageView) home.getChildAt(0) )
// change the icon according to your needs
.setImageDrawable(getResources().getDrawable(R.drawable.custom_icon_up));
} else {
// get the up imageview directly with R.id.up
( (ImageView) findViewById(R.id.up) )
.setImageDrawable(getResources().getDrawable(R.drawable.custom_icon_up));
}
You can change the background of the back icon like this
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initToolbar();
}
private void initToolbar() {
toolbar = (Toolbar) findViewById(R.id.tbMaster);
setSupportActionBar(toolbar);
if (toolbar != null) {
toolbar.setBackgroundColor(getResources().getColor(R.color.base_color));
getSupportActionBar().setTitle("Title");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.image);
}
}
I am working on Android L trying to implement a drawer menu that overlaps the action bar. I have done it the normal way where it appears under the action bar, as described here: http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/.
It was done in the google IO 2014 app and I would like to replicate it. I have been looking through the code (https://github.com/google/iosched) but I can't figure out how they done it.
Here is an image:
Does anyone have any idea how they done it?
To obtain this you have to use the new Toolbar.
You can use a layout like this:
<Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#style/ActionBarThemeOverlay"
android:id="#+id/toolbar_actionbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize" />
Then in your activity you can do:
Toolbar mActionBarToolbar = (Toolbar) mActivity.findViewById(R.id.toolbar_actionbar);
if (mActionBarToolbar != null) {
mActivity.setActionBar(mActionBarToolbar);
}
Finally you have to setup the toolbar to work with the navigation drawer:
if (mActionBarToolbar != null) {
mActionBarToolbar.setNavigationIcon(R.drawable.ic_navigation_drawer);
mActionBarToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
mDrawerLayout.closeDrawer(Gravity.START);
} else {
mDrawerLayout.openDrawer(Gravity.START);
}
}
});
}
Pay attention because currently the new Toolbar class is only API-21.
I am working on android application where I am using ActionBar so there one is navigation drawer icon to open it and title of ActionBar in ActionBar. I want to set a click listener on title of ActionBar such that it start a new Activity and set click listener different on navigation drawer icon to open navigation drawer menu.
I achieved a click on navigation drawer icon but when I click on title of ActionBar title also then it open the navigation drawer menu. Is there any way to set different click listener on title of ActionBar.
Thanks in advance.
Try adding this code under the onCreate() function. This will grab the resource the action bar title is under, and assign it an id you can use to add an OnClickListener to. Let me know how it goes!
final int abTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
findViewById(abTitleId).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Do something
}
});
You could use a custom layout for the title and assign a listener to it:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
// Disable the default and enable the custom
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
View customView = getLayoutInflater().inflate(R.layout.actionbar_title, null);
// Get the textview of the title
TextView customTitle = (TextView) customView.findViewById(R.id.actionbarTitle);
// Change the font family (optional)
customTitle.setTypeface(Typeface.MONOSPACE);
// Set the on click listener for the title
customTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.w("MainActivity", "ActionBar's title clicked.");
}
});
// Apply the custom view
actionBar.setCustomView(customView);
}
}
actionbar_title.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<TextView
android:id="#+id/actionbarTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:text="#string/app_name"/>
</LinearLayout>
I think Simas's answer is the best one, but here's a hacky version in case you prefer that.
ViewTools.findActionBarTitle(getWindow().getDecorView()).setOnClickListener(...);
This one should be universal in that it works with:
stock Android ActionBar
Theme.AppCompat support ActionBar
v21-style setActionBar
use <Toolbar android:id="#+id/action_bar"
or pass in the inflated Toolbar as root
v21-style setSupportActionBar
use <android.support.v7.widget.Toolbar android:id="#id/action_bar"
or pass in the inflated Toolbar as root
custom Toolbar implementations may need a little adjustment,
but then you could encapsulate this in that custom class.
Though I only tested with support:v22.
/** #param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
public static #Nullable View findActionBarTitle(#NonNull View root) {
return findActionBarItem(root, "action_bar_title", "mTitleTextView");
}
/** #param root usually Activity.getWindow().getDecorView() or your custom Toolbar */
public static #Nullable View findActionBarSubTitle(#NonNull View root) {
return findActionBarItem(root, "action_bar_subtitle", "mSubtitleTextView");
}
private static #Nullable View findActionBarItem(#NonNull View root,
#NonNull String resourceName, #NonNull String toolbarFieldName) {
View result = findViewSupportOrAndroid(root, resourceName);
if (result == null) {
View actionBar = findViewSupportOrAndroid(root, "action_bar");
if (actionBar != null) {
result = reflectiveRead(actionBar, toolbarFieldName);
}
}
if (result == null && root.getClass().getName().endsWith("widget.Toolbar")) {
result = reflectiveRead(root, toolbarFieldName);
}
return result;
}
#SuppressWarnings("ConstantConditions")
private static #Nullable View findViewSupportOrAndroid(#NonNull View root, #NonNull String resourceName) {
Context context = root.getContext();
View result = null;
if (result == null) {
int supportID = context.getResources().getIdentifier(resourceName, "id", context.getPackageName());
result = root.findViewById(supportID);
}
if (result == null) {
int androidID = context.getResources().getIdentifier(resourceName, "id", "android");
result = root.findViewById(androidID);
}
return result;
}
#SuppressWarnings("unchecked")
public static <T> #Nullable T reflectiveRead(#NonNull Object object, #NonNull String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T)field.get(object);
} catch (Exception ex) {
Log.w("HACK", "Cannot read " + fieldName + " in " + object, ex);
}
return null;
}
If you are using Toolbar with support v7:21.
Check out the following code:
Field titleField = Toolbar.class.getDeclaredField("mTitleTextView");
titleField.setAccessible(true);
TextView barTitleView = (TextView) titleField.get(mToolbar);
barTitleView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
You can do this easily using Toolbar. Define toolbar in layout xml file as given below:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="?colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<TextView
android:id="#+id/toolbarTitle"
style="#style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:background="?attr/selectableItemBackground"
android:layout_width="wrap_content"
android:gravity="center_vertical"
android:layout_height="match_parent" />
</android.support.v7.widget.Toolbar>
Then you can set the listener in Activity using this code:
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
TextView toolbarTitle= (TextView) findViewById(R.id.toolbarTitle);
toolbarTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// DO SOMETHING HERE
}
});
If you want to use the currently existing ActionBar and not the Toolbar, use the following:
ActionBar actBar = getSupportActionBar();
if(actBar != null) {
actBar.setTitle(R.string.your_ab_title);
}
//Set actions to take when the AB is clicked
Toolbar ab = findViewById(R.id.action_bar);
if(ab != null){
for (int i= 0; i < ab.getChildCount(); i++){
View child = ab.getChildAt(i);
if(child instanceof TextView || child instanceof ImageView) {
child.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String url = "http://www.HoverDroids.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
});
}
}
}
If you know the actual text that is in your Title, and you are reasonably sure that no other TextView on the screen shares that title, you can use a recursive View tree search to find it.
This is a great solution because it doesn't require reflection of internal knowledge of how to Toolbar is constructed, and gives you direct access to the TextView.
#Nullable
public static TextView findTextViewWithText(#Nullable View toCheck, String toFind) {
if (toCheck instanceof TextView) {
String foundText = ((TextView) toCheck).getText().toString();
if (foundText.equals(toFind)) {
return (TextView) toCheck;
}
} else if (toCheck instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) toCheck).getChildCount(); i++) {
TextView found = findTextViewWithText(((ViewGroup) toCheck).getChildAt(i), toFind);
if (found != null) {
return found;
}
}
}
return null;
}
The most reliable view to call this on is the decor view but feel free to experiment what works best for your purposes, your mileage may vary.
View found = findTextViewWithText(
getActivity().getWindow().getDecorView(), "My Title");
if (found != null) {
// Do something, like set a click listener
}
I know its too late, but for or those who use SupportActionBar like this and still have not found a clean solution:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
For the default configuration without logo and custom views, 1st item (index 0) will be the Home/Back ImageView, 2nd item will be our Title TextView and 3rd item will be the OptionMenu Imageview.
Getting child at index 1 would return title. Adding an OnClickListener to the child will make it work like a chram:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.getChildAt(1).setOnClickListener(v -> {
// title is clicked, call ur function here
// can also verify that the view is title itself by converting it to textview
try {
String title = ((TextView)v).getText().toString();
// title will be your activity title
} catch (Exception e) {
e.printStackTrace();
// if you got an exception, the view is not title.
// Check changing the index, in case you have custom views in the toolbar.
}
});
You can do this easily using Toolbar. Define toolbar in layout xml file as given below:
<android.support.v7.widget.Toolbar
android:id="#+id/MainActivityToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="#string/app_name"
android:textSize="30sp"
tools:ignore="RelativeOverlap"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
/>
<Button
android:id="#+id/LogOutButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:text="#string/logout" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
Then you can set the listener in Activity using this code:
setSupportActionBar((Toolbar) findViewById(R.id.MainActivityToolbar));
logOutButton = findViewById(R.id.LogOutButton);
logOutButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//define your function for logout or something else
LogOut();
}
});
I know it's very late to comment here but I came across this question when I searched for how to add OnClick for Action bar title.
Below is what I found and worked for me, hope it will help someone like me.
I wrote it for a fragment in my app.
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
actionBar.setTitle("");
((AppCompatActivity) getActivity()).setSupportActionBar((Toolbar) getActivity().findViewById(R.id.toolbar));
TextView toolbarTitle = (TextView) getActivity().findViewById(R.id.toolbarTitle);
toolbarTitle.setText("New title");
toolbarTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Action bar title clicked
}
});
actionBar.show();
I'm trying put text in to bar, I only put (buttons), I don't know if I can put text 2 lines + image.
Here are references as changing the color:
https://developer.android.com/training/basics/actionbar/styling.html
in this other picture is displayed, as you can put more text in the top bar
http://www.whatsapp.com/img/v3/es/s1-chat.png
Simply create your own view and set it for your ActionBar: setCustomView().
You cannot achieve what you want with the standard layout. For plenty of examples look here:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}
Source: vogella.com
I don't think you can do it.
I'd advise you just to create a layout that would act like a top bar in your application.
This way you would be able to put there anything you want.
If you have more than one activity that needs to have this top bar, then use fragments instead of activities (to avoid your custom top bar from being animated when new activities are being opened).