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