Changing the Android Toolbar's Back Arrow Color
As part of updating our apps to use the latest Android support library to bring in some of the nice material design classes in there, we also started switching over to using a Toolbar
as our action bar. If you're just getting started in making the same upgrades in your app I suggest starting with this excellent post on Xamarin's blog that outlines what you need to do.
Getting things migrated was easy enough but we unexpectedly hit some snags in trying to customize the color of the back button shown in the upper left of the toolbar consistently across Android versions. After spending far longer on this than I'd care to admit and countless permutations of styles and settings, I wanted to share what we settled on in hopes of saving someone else that pain. I also want to give my colleague Sasha a hat tip here because when I say that "we" went through some pain here, I mostly mean her.
Our Solution
After some digging we ended up on this Stackoverflow post that offers a variety of potential solutions to the problem. Our initial preference was to keep things contained entirely in the style XML. This answer seemed promising, but despite working in Android 4.x, Lollipop always seemed to completely ignore anything we set. Frustrating.
Feeling defeated, we opted to try the code solution mentioned in this answer. Success! A bit hacky, but hey, it works. #yolo
Translated to Xamarin.Android it looks like this:
var upArrow = Resources.GetDrawable(Resource.Drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.SetColorFilter(Resources.GetColor(Resource.Color.actionbartext), PorterDuff.Mode.SrcIn);
SupportActionBar.SetHomeAsUpIndicator(upArrow);
On a related note, that has to be one of the worst named resources I've ever seen.
But Wait, There's More
Unfortunately that wasn't where the pain ended for us. Our apps make use of a DrawerLayout
, where on the root view of the app the home indicator in the toolbar is the standard menu icon. As you navigate away from the root view the indicator changes to the back button we just talked about. Our host activity monitors for changes to the fragment backstack and updates this indicator accordingly. Despite having set the color filter earlier, we found that it was being lost and defaulting back to black.
The culprit? Updating the DrawerIndicatorEnabled
property on our ActionBarDrawerToggle
, which resets this drawable to the value set by the theme. Since we're doing the tinting in code, we just needed to make sure to reset the indicator when showing it. The resulting code boils down to something like this:
FragmentManager.BackStackChanged += (sender, e) =>
{
if (FragmentManager.BackStackEntryCount == 0)
{
_drawerToggle.DrawerIndicatorEnabled = true;
}
else
{
_drawerToggle.DrawerIndicatorEnabled = false;
SupportActionBar.SetHomeAsUpIndicator(upArrow);
}
};
There are undoubtedly ways to solve this more elegantly, but this approach is working well enough for us for the time being. It also passed a run through Test Cloud to try and smoke out any version/device incompatibilities. All that to change the color of a button...Android is fun sometimes.