179f95ce3e660d267831067e514ff455156c4381fAdam Powell/* 279f95ce3e660d267831067e514ff455156c4381fAdam Powell * Copyright (C) 2013 The Android Open Source Project 379f95ce3e660d267831067e514ff455156c4381fAdam Powell * 479f95ce3e660d267831067e514ff455156c4381fAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 579f95ce3e660d267831067e514ff455156c4381fAdam Powell * you may not use this file except in compliance with the License. 679f95ce3e660d267831067e514ff455156c4381fAdam Powell * You may obtain a copy of the License at 779f95ce3e660d267831067e514ff455156c4381fAdam Powell * 879f95ce3e660d267831067e514ff455156c4381fAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 979f95ce3e660d267831067e514ff455156c4381fAdam Powell * 1079f95ce3e660d267831067e514ff455156c4381fAdam Powell * Unless required by applicable law or agreed to in writing, software 1179f95ce3e660d267831067e514ff455156c4381fAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 1279f95ce3e660d267831067e514ff455156c4381fAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1379f95ce3e660d267831067e514ff455156c4381fAdam Powell * See the License for the specific language governing permissions and 1479f95ce3e660d267831067e514ff455156c4381fAdam Powell * limitations under the License. 1579f95ce3e660d267831067e514ff455156c4381fAdam Powell */ 1679f95ce3e660d267831067e514ff455156c4381fAdam Powell 1779f95ce3e660d267831067e514ff455156c4381fAdam Powell 1879f95ce3e660d267831067e514ff455156c4381fAdam Powellpackage android.support.v4.app; 1979f95ce3e660d267831067e514ff455156c4381fAdam Powell 2079f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.R; 2179f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.app.ActionBar; 2279f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.app.Activity; 23d95b307eb0b135c6c1da464fcbab96802506f929Alan Viveretteimport android.content.Context; 2479f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.content.res.TypedArray; 2579f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.graphics.drawable.Drawable; 26f41660112132e90d4a127051bf2772fa2347e42cAlan Viveretteimport android.os.Build; 2779f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.util.Log; 2879f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.view.View; 2979f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.view.ViewGroup; 3079f95ce3e660d267831067e514ff455156c4381fAdam Powellimport android.widget.ImageView; 3179f95ce3e660d267831067e514ff455156c4381fAdam Powell 3279f95ce3e660d267831067e514ff455156c4381fAdam Powellimport java.lang.reflect.Method; 3379f95ce3e660d267831067e514ff455156c4381fAdam Powell 3479f95ce3e660d267831067e514ff455156c4381fAdam Powell/** 3579f95ce3e660d267831067e514ff455156c4381fAdam Powell * This class encapsulates some awful hacks. 3679f95ce3e660d267831067e514ff455156c4381fAdam Powell * 3779f95ce3e660d267831067e514ff455156c4381fAdam Powell * Before JB-MR2 (API 18) it was not possible to change the home-as-up indicator glyph 3879f95ce3e660d267831067e514ff455156c4381fAdam Powell * in an action bar without some really gross hacks. Since the MR2 SDK is not published as of 3979f95ce3e660d267831067e514ff455156c4381fAdam Powell * this writing, the new API is accessed via reflection here if available. 4079f95ce3e660d267831067e514ff455156c4381fAdam Powell */ 4179f95ce3e660d267831067e514ff455156c4381fAdam Powellclass ActionBarDrawerToggleHoneycomb { 4279f95ce3e660d267831067e514ff455156c4381fAdam Powell private static final String TAG = "ActionBarDrawerToggleHoneycomb"; 4379f95ce3e660d267831067e514ff455156c4381fAdam Powell 4479f95ce3e660d267831067e514ff455156c4381fAdam Powell private static final int[] THEME_ATTRS = new int[] { 4579f95ce3e660d267831067e514ff455156c4381fAdam Powell R.attr.homeAsUpIndicator 4679f95ce3e660d267831067e514ff455156c4381fAdam Powell }; 4779f95ce3e660d267831067e514ff455156c4381fAdam Powell 4879f95ce3e660d267831067e514ff455156c4381fAdam Powell public static Object setActionBarUpIndicator(Object info, Activity activity, 4979f95ce3e660d267831067e514ff455156c4381fAdam Powell Drawable drawable, int contentDescRes) { 5079f95ce3e660d267831067e514ff455156c4381fAdam Powell if (info == null) { 5179f95ce3e660d267831067e514ff455156c4381fAdam Powell info = new SetIndicatorInfo(activity); 5279f95ce3e660d267831067e514ff455156c4381fAdam Powell } 5379f95ce3e660d267831067e514ff455156c4381fAdam Powell final SetIndicatorInfo sii = (SetIndicatorInfo) info; 5479f95ce3e660d267831067e514ff455156c4381fAdam Powell if (sii.setHomeAsUpIndicator != null) { 5579f95ce3e660d267831067e514ff455156c4381fAdam Powell try { 5679f95ce3e660d267831067e514ff455156c4381fAdam Powell final ActionBar actionBar = activity.getActionBar(); 5779f95ce3e660d267831067e514ff455156c4381fAdam Powell sii.setHomeAsUpIndicator.invoke(actionBar, drawable); 5879f95ce3e660d267831067e514ff455156c4381fAdam Powell sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 5979f95ce3e660d267831067e514ff455156c4381fAdam Powell } catch (Exception e) { 6079f95ce3e660d267831067e514ff455156c4381fAdam Powell Log.w(TAG, "Couldn't set home-as-up indicator via JB-MR2 API", e); 6179f95ce3e660d267831067e514ff455156c4381fAdam Powell } 6279f95ce3e660d267831067e514ff455156c4381fAdam Powell } else if (sii.upIndicatorView != null) { 6379f95ce3e660d267831067e514ff455156c4381fAdam Powell sii.upIndicatorView.setImageDrawable(drawable); 6479f95ce3e660d267831067e514ff455156c4381fAdam Powell } else { 6579f95ce3e660d267831067e514ff455156c4381fAdam Powell Log.w(TAG, "Couldn't set home-as-up indicator"); 6679f95ce3e660d267831067e514ff455156c4381fAdam Powell } 6779f95ce3e660d267831067e514ff455156c4381fAdam Powell return info; 6879f95ce3e660d267831067e514ff455156c4381fAdam Powell } 6979f95ce3e660d267831067e514ff455156c4381fAdam Powell 7079f95ce3e660d267831067e514ff455156c4381fAdam Powell public static Object setActionBarDescription(Object info, Activity activity, 7179f95ce3e660d267831067e514ff455156c4381fAdam Powell int contentDescRes) { 7279f95ce3e660d267831067e514ff455156c4381fAdam Powell if (info == null) { 7379f95ce3e660d267831067e514ff455156c4381fAdam Powell info = new SetIndicatorInfo(activity); 7479f95ce3e660d267831067e514ff455156c4381fAdam Powell } 7579f95ce3e660d267831067e514ff455156c4381fAdam Powell final SetIndicatorInfo sii = (SetIndicatorInfo) info; 7679f95ce3e660d267831067e514ff455156c4381fAdam Powell if (sii.setHomeAsUpIndicator != null) { 7779f95ce3e660d267831067e514ff455156c4381fAdam Powell try { 7879f95ce3e660d267831067e514ff455156c4381fAdam Powell final ActionBar actionBar = activity.getActionBar(); 7979f95ce3e660d267831067e514ff455156c4381fAdam Powell sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 80f41660112132e90d4a127051bf2772fa2347e42cAlan Viverette if (Build.VERSION.SDK_INT <= 19) { 81f41660112132e90d4a127051bf2772fa2347e42cAlan Viverette // For API 19 and earlier, we need to manually force the 82f41660112132e90d4a127051bf2772fa2347e42cAlan Viverette // action bar to generate a new content description. 83f41660112132e90d4a127051bf2772fa2347e42cAlan Viverette actionBar.setSubtitle(actionBar.getSubtitle()); 84f41660112132e90d4a127051bf2772fa2347e42cAlan Viverette } 8579f95ce3e660d267831067e514ff455156c4381fAdam Powell } catch (Exception e) { 8679f95ce3e660d267831067e514ff455156c4381fAdam Powell Log.w(TAG, "Couldn't set content description via JB-MR2 API", e); 8779f95ce3e660d267831067e514ff455156c4381fAdam Powell } 8879f95ce3e660d267831067e514ff455156c4381fAdam Powell } 8979f95ce3e660d267831067e514ff455156c4381fAdam Powell return info; 9079f95ce3e660d267831067e514ff455156c4381fAdam Powell } 9179f95ce3e660d267831067e514ff455156c4381fAdam Powell 9279f95ce3e660d267831067e514ff455156c4381fAdam Powell public static Drawable getThemeUpIndicator(Activity activity) { 93b966b785a7e81697f88861b98d2ae2a9acb2cfbfAlan Viverette final TypedArray a = activity.obtainStyledAttributes(THEME_ATTRS); 9479f95ce3e660d267831067e514ff455156c4381fAdam Powell final Drawable result = a.getDrawable(0); 9579f95ce3e660d267831067e514ff455156c4381fAdam Powell a.recycle(); 9679f95ce3e660d267831067e514ff455156c4381fAdam Powell return result; 9779f95ce3e660d267831067e514ff455156c4381fAdam Powell } 9879f95ce3e660d267831067e514ff455156c4381fAdam Powell 9979f95ce3e660d267831067e514ff455156c4381fAdam Powell private static class SetIndicatorInfo { 10079f95ce3e660d267831067e514ff455156c4381fAdam Powell public Method setHomeAsUpIndicator; 10179f95ce3e660d267831067e514ff455156c4381fAdam Powell public Method setHomeActionContentDescription; 10279f95ce3e660d267831067e514ff455156c4381fAdam Powell public ImageView upIndicatorView; 10379f95ce3e660d267831067e514ff455156c4381fAdam Powell 10479f95ce3e660d267831067e514ff455156c4381fAdam Powell SetIndicatorInfo(Activity activity) { 10579f95ce3e660d267831067e514ff455156c4381fAdam Powell try { 10679f95ce3e660d267831067e514ff455156c4381fAdam Powell setHomeAsUpIndicator = ActionBar.class.getDeclaredMethod("setHomeAsUpIndicator", 10779f95ce3e660d267831067e514ff455156c4381fAdam Powell Drawable.class); 10879f95ce3e660d267831067e514ff455156c4381fAdam Powell setHomeActionContentDescription = ActionBar.class.getDeclaredMethod( 10979f95ce3e660d267831067e514ff455156c4381fAdam Powell "setHomeActionContentDescription", Integer.TYPE); 11079f95ce3e660d267831067e514ff455156c4381fAdam Powell 11179f95ce3e660d267831067e514ff455156c4381fAdam Powell // If we got the method we won't need the stuff below. 11279f95ce3e660d267831067e514ff455156c4381fAdam Powell return; 11379f95ce3e660d267831067e514ff455156c4381fAdam Powell } catch (NoSuchMethodException e) { 11479f95ce3e660d267831067e514ff455156c4381fAdam Powell // Oh well. We'll use the other mechanism below instead. 11579f95ce3e660d267831067e514ff455156c4381fAdam Powell } 11679f95ce3e660d267831067e514ff455156c4381fAdam Powell 11779f95ce3e660d267831067e514ff455156c4381fAdam Powell final View home = activity.findViewById(android.R.id.home); 11879f95ce3e660d267831067e514ff455156c4381fAdam Powell if (home == null) { 11979f95ce3e660d267831067e514ff455156c4381fAdam Powell // Action bar doesn't have a known configuration, an OEM messed with things. 12079f95ce3e660d267831067e514ff455156c4381fAdam Powell return; 12179f95ce3e660d267831067e514ff455156c4381fAdam Powell } 12279f95ce3e660d267831067e514ff455156c4381fAdam Powell 12379f95ce3e660d267831067e514ff455156c4381fAdam Powell final ViewGroup parent = (ViewGroup) home.getParent(); 12479f95ce3e660d267831067e514ff455156c4381fAdam Powell final int childCount = parent.getChildCount(); 12579f95ce3e660d267831067e514ff455156c4381fAdam Powell if (childCount != 2) { 12679f95ce3e660d267831067e514ff455156c4381fAdam Powell // No idea which one will be the right one, an OEM messed with things. 12779f95ce3e660d267831067e514ff455156c4381fAdam Powell return; 12879f95ce3e660d267831067e514ff455156c4381fAdam Powell } 12979f95ce3e660d267831067e514ff455156c4381fAdam Powell 13079f95ce3e660d267831067e514ff455156c4381fAdam Powell final View first = parent.getChildAt(0); 13179f95ce3e660d267831067e514ff455156c4381fAdam Powell final View second = parent.getChildAt(1); 13279f95ce3e660d267831067e514ff455156c4381fAdam Powell final View up = first.getId() == android.R.id.home ? second : first; 13379f95ce3e660d267831067e514ff455156c4381fAdam Powell 13479f95ce3e660d267831067e514ff455156c4381fAdam Powell if (up instanceof ImageView) { 13579f95ce3e660d267831067e514ff455156c4381fAdam Powell // Jackpot! (Probably...) 13679f95ce3e660d267831067e514ff455156c4381fAdam Powell upIndicatorView = (ImageView) up; 13779f95ce3e660d267831067e514ff455156c4381fAdam Powell } 13879f95ce3e660d267831067e514ff455156c4381fAdam Powell } 13979f95ce3e660d267831067e514ff455156c4381fAdam Powell } 14079f95ce3e660d267831067e514ff455156c4381fAdam Powell} 141