ActionBarDrawerToggleHoneycomb.java revision 7b74aa144a22b74896be5f28af2c4f257f76d71f
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.util.Log; 26import android.view.View; 27import android.view.ViewGroup; 28import android.widget.ImageView; 29 30import java.lang.reflect.Method; 31 32/** 33 * This class encapsulates some awful hacks. 34 * 35 * Before JB-MR2 (API 18) it was not possible to change the home-as-up indicator glyph 36 * in an action bar without some really gross hacks. Since the MR2 SDK is not published as of 37 * this writing, the new API is accessed via reflection here if available. 38 */ 39class ActionBarDrawerToggleHoneycomb { 40 private static final String TAG = "ActionBarDrawerToggleHoneycomb"; 41 42 private static final int[] THEME_ATTRS = new int[] { 43 R.attr.homeAsUpIndicator 44 }; 45 46 public static Object setActionBarUpIndicator(Object info, Activity activity, 47 Drawable drawable, int contentDescRes) { 48 if (info == null) { 49 info = new SetIndicatorInfo(activity); 50 } 51 final SetIndicatorInfo sii = (SetIndicatorInfo) info; 52 if (sii.setHomeAsUpIndicator != null) { 53 try { 54 final ActionBar actionBar = activity.getActionBar(); 55 sii.setHomeAsUpIndicator.invoke(actionBar, drawable); 56 sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 57 } catch (Exception e) { 58 Log.w(TAG, "Couldn't set home-as-up indicator via JB-MR2 API", e); 59 } 60 } else if (sii.upIndicatorView != null) { 61 sii.upIndicatorView.setImageDrawable(drawable); 62 } else { 63 Log.w(TAG, "Couldn't set home-as-up indicator"); 64 } 65 return info; 66 } 67 68 public static Object setActionBarDescription(Object info, Activity activity, 69 int contentDescRes) { 70 if (info == null) { 71 info = new SetIndicatorInfo(activity); 72 } 73 final SetIndicatorInfo sii = (SetIndicatorInfo) info; 74 if (sii.setHomeAsUpIndicator != null) { 75 try { 76 final ActionBar actionBar = activity.getActionBar(); 77 sii.setHomeActionContentDescription.invoke(actionBar, contentDescRes); 78 } catch (Exception e) { 79 Log.w(TAG, "Couldn't set content description via JB-MR2 API", e); 80 } 81 } 82 return info; 83 } 84 85 public static Drawable getThemeUpIndicator(Activity activity) { 86 final TypedArray a = activity.obtainStyledAttributes(THEME_ATTRS); 87 final Drawable result = a.getDrawable(0); 88 a.recycle(); 89 return result; 90 } 91 92 private static class SetIndicatorInfo { 93 public Method setHomeAsUpIndicator; 94 public Method setHomeActionContentDescription; 95 public ImageView upIndicatorView; 96 97 SetIndicatorInfo(Activity activity) { 98 try { 99 setHomeAsUpIndicator = ActionBar.class.getDeclaredMethod("setHomeAsUpIndicator", 100 Drawable.class); 101 setHomeActionContentDescription = ActionBar.class.getDeclaredMethod( 102 "setHomeActionContentDescription", Integer.TYPE); 103 104 // If we got the method we won't need the stuff below. 105 return; 106 } catch (NoSuchMethodException e) { 107 // Oh well. We'll use the other mechanism below instead. 108 } 109 110 final View home = activity.findViewById(android.R.id.home); 111 if (home == null) { 112 // Action bar doesn't have a known configuration, an OEM messed with things. 113 return; 114 } 115 116 final ViewGroup parent = (ViewGroup) home.getParent(); 117 final int childCount = parent.getChildCount(); 118 if (childCount != 2) { 119 // No idea which one will be the right one, an OEM messed with things. 120 return; 121 } 122 123 final View first = parent.getChildAt(0); 124 final View second = parent.getChildAt(1); 125 final View up = first.getId() == android.R.id.home ? second : first; 126 127 if (up instanceof ImageView) { 128 // Jackpot! (Probably...) 129 upIndicatorView = (ImageView) up; 130 } 131 } 132 } 133} 134