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