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.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 *
40 * Moved from Support-v4
41 */
42class ActionBarDrawerToggleHoneycomb {
43    private static final String TAG = "ActionBarDrawerToggleHoneycomb";
44
45    private static final int[] THEME_ATTRS = new int[] {
46            R.attr.homeAsUpIndicator
47    };
48
49    public static SetIndicatorInfo setActionBarUpIndicator(SetIndicatorInfo info, Activity activity,
50            Drawable drawable, int contentDescRes) {
51        if (true || info == null) {
52            info = new SetIndicatorInfo(activity);
53        }
54        if (info.setHomeAsUpIndicator != null) {
55            try {
56                final ActionBar actionBar = activity.getActionBar();
57                info.setHomeAsUpIndicator.invoke(actionBar, drawable);
58                info.setHomeActionContentDescription.invoke(actionBar, contentDescRes);
59            } catch (Exception e) {
60                Log.w(TAG, "Couldn't set home-as-up indicator via JB-MR2 API", e);
61            }
62        } else if (info.upIndicatorView != null) {
63            info.upIndicatorView.setImageDrawable(drawable);
64        } else {
65            Log.w(TAG, "Couldn't set home-as-up indicator");
66        }
67        return info;
68    }
69
70    public static SetIndicatorInfo setActionBarDescription(SetIndicatorInfo info, Activity activity,
71            int contentDescRes) {
72        if (info == null) {
73            info = new SetIndicatorInfo(activity);
74        }
75        if (info.setHomeAsUpIndicator != null) {
76            try {
77                final ActionBar actionBar = activity.getActionBar();
78                info.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    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