6

I used the following hack to change the homeAsupIndicator programmatically.

int upId = Resources.getSystem().getIdentifier("up", "id", "android");
if (upId > 0) {
    ImageView up = (ImageView) findViewById(upId);
up.setImageResource(R.drawable.ic_action_bar_menu);
up.setPadding(0, 0, 20, 0);
}

But this is not working on most new phones (HTC One, Galaxy S3, etc). Is there a way that can be changed uniformly across devices. I need it to be changed only on home screen. Other screens would have the default one. So cannot use the styles.xml

Cœur
  • 37,241
  • 25
  • 195
  • 267
Yasir
  • 453
  • 1
  • 6
  • 15
  • what are the versions of the phones in which they are not working? – user936414 Jul 11 '13 at 06:25
  • this not work on android 4.1.1 and older becouse thers no view with id="android:id/up" – Kenumir Dec 11 '13 at 10:03
  • @Kenumir You need to do that programmatically. It does not show up if you try it on xml. It works on 4.2 and above as well. I checked it on nexus 7. The problem was it does not show the same across all devices. For me it did not work on HTC one and Samsung S4, but worked fine on S3. However the solution is below. – Yasir Dec 16 '13 at 04:38

12 Answers12

18

This is what i did to acheive the behavior. I inherited the base theme and created a new theme to use it as a theme for the specific activity.

<style name="CustomActivityTheme" parent="AppTheme">
    <item name="android:homeAsUpIndicator">@drawable/custom_home_as_up_icon</item>
</style>

and in the android manifest i made the activity theme as the above.

<activity
        android:name="com.example.CustomActivity"
        android:theme="@style/CustomActivityTheme" >
</activity>

works great. Will update again when i check on all devices I have. Thanks @faylon for pointing in the right direction

Yasir
  • 453
  • 1
  • 6
  • 15
  • 1
    For sure this answer is the most compatible ofcourse it requires a little bit of more extra work but it does the trick!! – Necronet Oct 18 '13 at 21:53
11

The question was to change dynamically the Up Home Indicator, although this answer was accepting and it is about Themes and Styles. I found a way to do this programmatically, according to Adneal's answer which gives me the clue and specially the right way to do. I used the below snippet code and it works well on (tested) devices with APIs mentioned here.

For lower APIs, I use R.id.up which is not available on higher API. That's why, I retrieve this id by a little workaround which is getting the parent of home button (android.R.id.home) and its first child (android.R.id.up):

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
        .setImageResource(R.drawable.custom_icon_up));
} else {
    // get the up imageview directly with R.id.up
    ( (ImageView) findViewById(R.id.up) )
        .setImageResource(R.drawable.custom_icon_up));
} 

Note: If you don't use the SDK condition, you will get some NullPointerException.

Community
  • 1
  • 1
Blo
  • 11,903
  • 5
  • 45
  • 99
  • Does this work on all devices? It did not work for me on HTC One and Galaxy S4. Works fine on Galaxy S3 though – Yasir May 08 '14 at 04:11
  • Apparently not @Yasir, because you said so. However on all APIs tested with *NexusOne, NexusS, GalaxyNexus and Nexus4*, I got the right behaviour. Don't know why your devices aren't working. Does it crash or just nothing happen? It might crash relative to a null pointer exception. – Blo May 08 '14 at 10:47
  • @Filo.. It could be because of how the android OS is implemented by different providers. The devices you tested all have the pure stock android. It does not work on HTC One too. – Yasir Jun 25 '14 at 23:57
  • I edited the code a bit because there is no need to use `setImageDrawable()` to pass a drawable that was build using a resource id. Just use `setImageResource()` directly. – WarrenFaith Jul 29 '14 at 16:34
  • I was able to use this hack on Android 4+ but could not understand why the up/home indicator was back to the default one when search widget was expanded. Looking at the view hierarchy, turns out that the up/home indicator + icon section of the action bar has 2 implementations and of course the first on is the one for when the search widget is not expanded. See my code in my answer: http://stackoverflow.com/a/25773767/125916 – Bao-Long Nguyen-Trong Sep 10 '14 at 19:42
  • 1
    Tried 'N' number of solutions.But this one works like a charm..TQ @Fllo – Prabs Sep 29 '15 at 07:34
5

API 18 has new methods ActionBar.setHomeAsUpIndicator() - unfortunately these aren't supported in the support library at this moment

http://developer.android.com/reference/android/app/ActionBar.html#setHomeAsUpIndicator(android.graphics.drawable.Drawable)

edit: these are now supported by the support library http://developer.android.com/reference/android/support/v7/app/ActionBar.html#setHomeAsUpIndicator(android.graphics.drawable.Drawable)

kassim
  • 3,880
  • 3
  • 26
  • 27
  • Kwg, when I tried to use this method with support library, I got an error (undefined method) on this. I can't use it with *AppCompat*. It's weird. – Blo May 08 '14 at 11:08
  • it appears for me, perhaps you've got an older version of the support library? – kassim May 08 '14 at 14:10
  • Right Kmg! Even if I updated from the SDK Manager, it was not updated in my current projects. I finally resolve by deleting all old libraries manually and reupload them. Thanks for the advice. – Blo May 08 '14 at 16:33
3

All you need to do is to use this line of code:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

This will change the icon with the up indicator. To disable it later, just call this function again and pass false as the param.

Lawrence Choy
  • 6,088
  • 1
  • 20
  • 30
2

The solution by checking Resources.getSystem() doesn't work on all devices, A better solution to change the homeAsUpIndicator is to set it @null in style and change the logo resource programmatically.

Below is my code from style.xml

<style name="Theme.HomeScreen" parent="AppBaseTheme">
  <item name="displayOptions">showHome|useLogo</item>
  <item name="homeAsUpIndicator">@null</item>
  <item name="android:homeAsUpIndicator">@null</item>
</style>

In code you can change the logo using setLogo() method.

getSupportActionBar().setLogo(R.drawable.abc_ic_ab_back_holo_light); //for ActionBarCompat
getActionBar().setLogo(R.drawable.abc_ic_ab_back_holo_light); //for default actionbar for post 3.0 devices

Also note that the Android API 18 has methods to edit the homeAsUpIndicator programatically, refer documentation.

Lalith B
  • 11,843
  • 6
  • 29
  • 47
  • setLogo changes the logo, not the homeAsUpIndicator. So setting them @null just removes the upIndicator everywhere. The ActionBar.setHomeAsUpIndicator() method is really what we need but it's not in the support library "yet?" – Jordy Jan 07 '14 at 11:48
  • @Jordy the setHomeAsUpIndicator() is not available in the support library yet, http://developer.android.com/reference/android/support/v7/app/ActionBar.html – Lalith B Jan 14 '14 at 13:32
1

You can achieve this in an easier way. Try to can change the homeAsUpIndicator attribute of actionBarStyle in your theme.xml and styles.xml.

If you want some padding, just add some white space in your image.

faylon
  • 7,360
  • 1
  • 30
  • 28
  • setting it in the styles.xml changes it for all activities. I need it changed for one activity only(the one with the menu) – Yasir Jul 11 '13 at 06:00
  • @Yasir thus you can apply a new theme for this activity. – faylon Jul 11 '13 at 07:22
  • Thanks for the pointer. I inherited the app theme and created a separate theme for the specific activity. – Yasir Jul 11 '13 at 12:19
1

You can try this:

this.getSupportActionBar().setHomeAsUpIndicator( R.drawable.actionbar_indicator ); //for ActionBarCompat
this.getActionBar().setHomeAsUpIndicator( R.drawable.actionbar_indicator ); //for default actionbar for post 3.0 devices

If you need change the position of the icon, you must create a drawable file containing a "layer-list" like this:

actionbar_indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@drawable/indicator"
        android:right="5dp"
        android:left="10dp" />
</layer-list>
wbelarmino
  • 509
  • 3
  • 7
0

use getActionBar().setCustomView(int yourView); because ActionBar haven't method to change homeUp icon!

Ozik Abdullaev
  • 1,026
  • 1
  • 9
  • 26
  • getActionBar().setCustomView() adds a custom view to the action bar. Can it be modified to change the homeAsUpIndicator? – Yasir Jul 11 '13 at 05:59
0

Adding to Fllo answer Change the actionbar homeAsUpIndicator Programamtically

I was able to use this hack on Android 4+ but could not understand why the up/home indicator was back to the default one when search widget was expanded. Looking at the view hierarchy, turns out that the up/home indicator + icon section of the action bar has 2 implementations and of course the first on is the one for when the search widget is not expanded. So here is the code I used to work around this and get the up/home indicator changed in both cases.

    mSearchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // https://stackoverflow.com/questions/17585892/change-the-actionbar-homeasupindicator-programamtically
            int actionBarId = getResources().getIdentifier("android:id/action_bar", null, null);
            View view = getActivity().getWindow().getDecorView().findViewById(actionBarId);
            if (view == null
                    || !(view instanceof ViewGroup)) {
                return true;
            }
            final ViewGroup actionBarView = (ViewGroup)view;

            // The second home view is only inflated after 
            // setOnActionExpandListener() is first called
            actionBarView.post(new Runnable() {
                @Override
                public void run() {
                    //The 2 ActionBarView$HomeView views are always children of the same view group
                    //However, they are not always children of the ActionBarView itself
                    //(depends on OS version)
                    int upId = getResources().getIdentifier("android:id/up", null, null);
                    View upView = actionBarView.findViewById(upId);
                    ViewParent viewParent = upView.getParent();
                    if (viewParent == null) {
                        return;
                    }
                    viewParent = viewParent.getParent();
                    if (viewParent == null
                            || !(viewParent instanceof ViewGroup)) {
                        return;
                    }

                    ViewGroup viewGroup = (ViewGroup) viewParent;
                    int childCount = viewGroup.getChildCount();
                    for (int i = 0; i < childCount; i++) {
                        View childView = viewGroup.getChildAt(i);
                        if (childView instanceof ViewGroup) {
                            ViewGroup homeView = (ViewGroup) childView;
                            upView = homeView.findViewById(upId);
                            if (upView != null
                                    && upView instanceof ImageView) {
                                Drawable upDrawable = getResources().getDrawable(R.drawable.ic_ab_back_holo_dark_am);
                                upDrawable.setColorFilter(accentColorInt, PorterDuff.Mode.MULTIPLY);
                                ((ImageView) upView).setImageDrawable(upDrawable);
                            }
                        }
                    }
                }
            });
Community
  • 1
  • 1
0

If someone uses the library support-v7 appcompat, you can directly call this method:

  • getSupportActionBar().setHomeAsUpIndicator(int redId)

In other case you can use this solution:

Community
  • 1
  • 1
encastellano
  • 435
  • 3
  • 5
0

If you are using DrawerLayout with ActionBarDrawerToggle, then check out this answer.

Community
  • 1
  • 1
Borzh
  • 5,069
  • 2
  • 48
  • 64
-1
this.getSupportActionBar().setDisplayUseLogoEnabled(true);
this.getSupportActionBar().setLogo(R.drawable.about_selected);

Also you can define the logo in manifest in attribute android:logo of and tags and set in theme that you want to use logo instead of app icon in the action bar.

Muhammad Aamir Ali
  • 20,419
  • 10
  • 66
  • 57