ActionBarDrawerToggleHoneycomb.java revision f41660112132e90d4a127051bf2772fa2347e42c
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18package android.support.v4.app; 19 20import android.R; 21import android.app.ActionBar; 22import android.app.Activity; 23import android.content.res.TypedArray; 24import android.graphics.drawable.Drawable; 25import android.os.Build; 26import android.util.Log; 27import android.view.View; 28import android.view.ViewGroup; 29import android.widget.ImageView; 30 31import java.lang.reflect.Method; 32 33/** 34 * This class encapsulates some awful hacks. 35 * 36 * Before JB-MR2 (API 18) it was not possible to change the home-as-up indicator glyph 37 * in an action bar without some really gross hacks. Since the MR2 SDK is not published as of 38 * this writing, the new API is accessed via reflection here if available. 39 */ 40class ActionBarDrawerToggleHoneycomb { 41 private static final String TAG = "ActionBarDrawerToggleHoneycomb"; 42 43 private static final int[] THEME_ATTRS = new int[] { 44 R.attr.homeAsUpIndicator 45 }; 46 47 public static Object setActionBarUpIndicator(Object info, Activity activity, 48 Drawable drawable, int contentDescRes) { 49 if (info == null) { 50 info = new SetIndicatorInfo(activity); 51 } 52 final SetIndicatorInfo sii = (SetIndicatorInfo) info; 53 if (sii.setHomeAsUpIndicator != null) { 54 try { 55 final ActionBar actionBar = activity.getActionBar(); 56 sii.setHomeAsUpIndicator.invoke(actionBar, drawable); 57 sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 58 } catch (Exception e) { 59 Log.w(TAG, "Couldn't set home-as-up indicator via JB-MR2 API", e); 60 } 61 } else if (sii.upIndicatorView != null) { 62 sii.upIndicatorView.setImageDrawable(drawable); 63 } else { 64 Log.w(TAG, "Couldn't set home-as-up indicator"); 65 } 66 return info; 67 } 68 69 public static Object setActionBarDescription(Object info, Activity activity, 70 int contentDescRes) { 71 if (info == null) { 72 info = new SetIndicatorInfo(activity); 73 } 74 final SetIndicatorInfo sii = (SetIndicatorInfo) info; 75 if (sii.setHomeAsUpIndicator != null) { 76 try { 77 final ActionBar actionBar = activity.getActionBar(); 78 sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 79 if (Build.VERSION.SDK_INT <= 19) { 80 // For API 19 and earlier, we need to manually force the 81 // action bar to generate a new content description. 82 actionBar.setSubtitle(actionBar.getSubtitle()); 83 } 84 } catch (Exception e) { 85 Log.w(TAG, "Couldn't set content description via JB-MR2 API", e); 86 } 87 } 88 return info; 89 } 90 91 public static Drawable getThemeUpIndicator(Activity activity) { 92 final TypedArray a = activity.obtainStyledAttributes(THEME_ATTRS); 93 final Drawable result = a.getDrawable(0); 94 a.recycle(); 95 return result; 96 } 97 98 private static class SetIndicatorInfo { 99 public Method setHomeAsUpIndicator; 100 public Method setHomeActionContentDescription; 101 public ImageView upIndicatorView; 102 103 SetIndicatorInfo(Activity activity) { 104 try { 105 setHomeAsUpIndicator = ActionBar.class.getDeclaredMethod("setHomeAsUpIndicator", 106 Drawable.class); 107 setHomeActionContentDescription = ActionBar.class.getDeclaredMethod( 108 "setHomeActionContentDescription", Integer.TYPE); 109 110 // If we got the method we won't need the stuff below. 111 return; 112 } catch (NoSuchMethodException e) { 113 // Oh well. We'll use the other mechanism below instead. 114 } 115 116 final View home = activity.findViewById(android.R.id.home); 117 if (home == null) { 118 // Action bar doesn't have a known configuration, an OEM messed with things. 119 return; 120 } 121 122 final ViewGroup parent = (ViewGroup) home.getParent(); 123 final int childCount = parent.getChildCount(); 124 if (childCount != 2) { 125 // No idea which one will be the right one, an OEM messed with things. 126 return; 127 } 128 129 final View first = parent.getChildAt(0); 130 final View second = parent.getChildAt(1); 131 final View up = first.getId() == android.R.id.home ? second : first; 132 133 if (up instanceof ImageView) { 134 // Jackpot! (Probably...) 135 upIndicatorView = (ImageView) up; 136 } 137 } 138 } 139} 140