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 */
16package android.support.v7.app;
17
18import android.app.Activity;
19import android.app.ActionBar;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.TypedArray;
23import android.graphics.drawable.Drawable;
24import android.os.Build;
25import android.support.annotation.Nullable;
26import android.support.annotation.StringRes;
27import android.support.v4.view.GravityCompat;
28import android.support.v4.view.ViewCompat;
29import android.support.v4.widget.DrawerLayout;
30import android.support.v7.widget.Toolbar;
31import android.util.Log;
32import android.view.MenuItem;
33import android.view.View;
34import android.support.v7.appcompat.R;
35
36/**
37 * This class provides a handy way to tie together the functionality of
38 * {@link android.support.v4.widget.DrawerLayout} and the framework <code>ActionBar</code> to
39 * implement the recommended design for navigation drawers.
40 *
41 * <p>To use <code>ActionBarDrawerToggle</code>, create one in your Activity and call through
42 * to the following methods corresponding to your Activity callbacks:</p>
43 *
44 * <ul>
45 * <li>{@link android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
46 * onConfigurationChanged}
47 * <li>{@link android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
48 * onOptionsItemSelected}</li>
49 * </ul>
50 *
51 * <p>Call {@link #syncState()} from your <code>Activity</code>'s
52 * {@link android.app.Activity#onPostCreate(android.os.Bundle) onPostCreate} to synchronize the
53 * indicator with the state of the linked DrawerLayout after <code>onRestoreInstanceState</code>
54 * has occurred.</p>
55 *
56 * <p><code>ActionBarDrawerToggle</code> can be used directly as a
57 * {@link android.support.v4.widget.DrawerLayout.DrawerListener}, or if you are already providing
58 * your own listener, call through to each of the listener methods from your own.</p>
59 *
60 * <p>
61 * You can customize the the animated toggle by defining the
62 * {@link android.support.v7.appcompat.R.styleable#DrawerArrowToggle drawerArrowStyle} in your
63 * ActionBar theme.
64 */
65public class ActionBarDrawerToggle implements DrawerLayout.DrawerListener {
66
67    /**
68     * Allows an implementing Activity to return an {@link ActionBarDrawerToggle.Delegate} to use
69     * with ActionBarDrawerToggle.
70     */
71    public interface DelegateProvider {
72
73        /**
74         * @return Delegate to use for ActionBarDrawableToggles, or null if the Activity
75         * does not wish to override the default behavior.
76         */
77        @Nullable
78        Delegate getDrawerToggleDelegate();
79    }
80
81    /**
82     * @deprecated Temporary class for the transition from old drawer toggle to new drawer toggle.
83     */
84    interface TmpDelegateProvider {
85
86        @Nullable
87        Delegate getV7DrawerToggleDelegate();
88    }
89
90    public interface Delegate {
91
92        /**
93         * Set the Action Bar's up indicator drawable and content description.
94         *
95         * @param upDrawable     - Drawable to set as up indicator
96         * @param contentDescRes - Content description to set
97         */
98        void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes);
99
100        /**
101         * Set the Action Bar's up indicator content description.
102         *
103         * @param contentDescRes - Content description to set
104         */
105        void setActionBarDescription(@StringRes int contentDescRes);
106
107        /**
108         * Returns the drawable to be set as up button when DrawerToggle is disabled
109         */
110        Drawable getThemeUpIndicator();
111
112        /**
113         * Returns the context of ActionBar
114         */
115        Context getActionBarThemedContext();
116
117        /**
118         * Returns whether navigation icon is visible or not.
119         * Used to print warning messages in case developer forgets to set displayHomeAsUp to true
120         */
121        boolean isNavigationVisible();
122    }
123
124    private final Delegate mActivityImpl;
125    private final DrawerLayout mDrawerLayout;
126
127    private DrawerToggle mSlider;
128    private Drawable mHomeAsUpIndicator;
129    private boolean mDrawerIndicatorEnabled = true;
130    private boolean mHasCustomUpIndicator;
131    private final int mOpenDrawerContentDescRes;
132    private final int mCloseDrawerContentDescRes;
133    // used in toolbar mode when DrawerToggle is disabled
134    private View.OnClickListener mToolbarNavigationClickListener;
135    // If developer does not set displayHomeAsUp, DrawerToggle won't show up.
136    // DrawerToggle logs a warning if this case is detected
137    private boolean mWarnedForDisplayHomeAsUp = false;
138
139    /**
140     * Construct a new ActionBarDrawerToggle.
141     *
142     * <p>The given {@link Activity} will be linked to the specified {@link DrawerLayout} and
143     * its Actionbar's Up button will be set to a custom drawable.
144     * <p>This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
145     * is open. It animates between these two states as the drawer opens.</p>
146     *
147     * <p>String resources must be provided to describe the open/close drawer actions for
148     * accessibility services.</p>
149     *
150     * @param activity                  The Activity hosting the drawer. Should have an ActionBar.
151     * @param drawerLayout              The DrawerLayout to link to the given Activity's ActionBar
152     * @param openDrawerContentDescRes  A String resource to describe the "open drawer" action
153     *                                  for accessibility
154     * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action
155     *                                  for accessibility
156     */
157    public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
158            @StringRes int openDrawerContentDescRes,
159            @StringRes int closeDrawerContentDescRes) {
160        this(activity, null, drawerLayout, null, openDrawerContentDescRes,
161                closeDrawerContentDescRes);
162    }
163
164    /**
165     * Construct a new ActionBarDrawerToggle with a Toolbar.
166     * <p>
167     * The given {@link Activity} will be linked to the specified {@link DrawerLayout} and
168     * the Toolbar's navigation icon will be set to a custom drawable. Using this constructor
169     * will set Toolbar's navigation click listener to toggle the drawer when it is clicked.
170     * <p>
171     * This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
172     * is open. It animates between these two states as the drawer opens.
173     * <p>
174     * String resources must be provided to describe the open/close drawer actions for
175     * accessibility services.
176     * <p>
177     * Please use {@link #ActionBarDrawerToggle(Activity, DrawerLayout, int, int)} if you are
178     * setting the Toolbar as the ActionBar of your activity.
179     *
180     * @param activity                  The Activity hosting the drawer.
181     * @param toolbar                   The toolbar to use if you have an independent Toolbar.
182     * @param drawerLayout              The DrawerLayout to link to the given Activity's ActionBar
183     * @param openDrawerContentDescRes  A String resource to describe the "open drawer" action
184     *                                  for accessibility
185     * @param closeDrawerContentDescRes A String resource to describe the "close drawer" action
186     *                                  for accessibility
187     */
188    public ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout,
189            Toolbar toolbar, @StringRes int openDrawerContentDescRes,
190            @StringRes int closeDrawerContentDescRes) {
191        this(activity, toolbar, drawerLayout, null, openDrawerContentDescRes,
192                closeDrawerContentDescRes);
193    }
194
195    /**
196     * In the future, we can make this constructor public if we want to let developers customize
197     * the
198     * animation.
199     */
200    <T extends Drawable & DrawerToggle> ActionBarDrawerToggle(Activity activity, Toolbar toolbar,
201            DrawerLayout drawerLayout, T slider,
202            @StringRes int openDrawerContentDescRes,
203            @StringRes int closeDrawerContentDescRes) {
204        if (toolbar != null) {
205            mActivityImpl = new ToolbarCompatDelegate(toolbar);
206            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
207                @Override
208                public void onClick(View v) {
209                    if (mDrawerIndicatorEnabled) {
210                        toggle();
211                    } else if (mToolbarNavigationClickListener != null) {
212                        mToolbarNavigationClickListener.onClick(v);
213                    }
214                }
215            });
216        } else if (activity instanceof DelegateProvider) { // Allow the Activity to provide an impl
217            mActivityImpl = ((DelegateProvider) activity).getDrawerToggleDelegate();
218        } else if (activity instanceof TmpDelegateProvider) {// tmp interface for transition
219            mActivityImpl = ((TmpDelegateProvider) activity).getV7DrawerToggleDelegate();
220        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
221            mActivityImpl = new JellybeanMr2Delegate(activity);
222        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
223            mActivityImpl = new HoneycombDelegate(activity);
224        } else {
225            mActivityImpl = new DummyDelegate(activity);
226        }
227
228        mDrawerLayout = drawerLayout;
229        mOpenDrawerContentDescRes = openDrawerContentDescRes;
230        mCloseDrawerContentDescRes = closeDrawerContentDescRes;
231        if (slider == null) {
232            mSlider = new DrawerArrowDrawableToggle(activity,
233                    mActivityImpl.getActionBarThemedContext());
234        } else {
235            mSlider = slider;
236        }
237
238        mHomeAsUpIndicator = getThemeUpIndicator();
239    }
240
241    /**
242     * Synchronize the state of the drawer indicator/affordance with the linked DrawerLayout.
243     *
244     * <p>This should be called from your <code>Activity</code>'s
245     * {@link Activity#onPostCreate(android.os.Bundle) onPostCreate} method to synchronize after
246     * the DrawerLayout's instance state has been restored, and any other time when the state
247     * may have diverged in such a way that the ActionBarDrawerToggle was not notified.
248     * (For example, if you stop forwarding appropriate drawer events for a period of time.)</p>
249     */
250    public void syncState() {
251        if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
252            mSlider.setPosition(1);
253        } else {
254            mSlider.setPosition(0);
255        }
256        if (mDrawerIndicatorEnabled) {
257            setActionBarUpIndicator((Drawable) mSlider,
258                    mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
259                            mCloseDrawerContentDescRes : mOpenDrawerContentDescRes);
260        }
261    }
262
263    /**
264     * This method should always be called by your <code>Activity</code>'s
265     * {@link Activity#onConfigurationChanged(android.content.res.Configuration)
266     * onConfigurationChanged}
267     * method.
268     *
269     * @param newConfig The new configuration
270     */
271    public void onConfigurationChanged(Configuration newConfig) {
272        // Reload drawables that can change with configuration
273        if (!mHasCustomUpIndicator) {
274            mHomeAsUpIndicator = getThemeUpIndicator();
275        }
276        syncState();
277    }
278
279    /**
280     * This method should be called by your <code>Activity</code>'s
281     * {@link Activity#onOptionsItemSelected(android.view.MenuItem) onOptionsItemSelected} method.
282     * If it returns true, your <code>onOptionsItemSelected</code> method should return true and
283     * skip further processing.
284     *
285     * @param item the MenuItem instance representing the selected menu item
286     * @return true if the event was handled and further processing should not occur
287     */
288    public boolean onOptionsItemSelected(MenuItem item) {
289        if (item != null && item.getItemId() == android.R.id.home && mDrawerIndicatorEnabled) {
290            toggle();
291            return true;
292        }
293        return false;
294    }
295
296    private void toggle() {
297        if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
298            mDrawerLayout.closeDrawer(GravityCompat.START);
299        } else {
300            mDrawerLayout.openDrawer(GravityCompat.START);
301        }
302    }
303
304    /**
305     * Set the up indicator to display when the drawer indicator is not
306     * enabled.
307     * <p>
308     * If you pass <code>null</code> to this method, the default drawable from
309     * the theme will be used.
310     *
311     * @param indicator A drawable to use for the up indicator, or null to use
312     *                  the theme's default
313     * @see #setDrawerIndicatorEnabled(boolean)
314     */
315    public void setHomeAsUpIndicator(Drawable indicator) {
316        if (indicator == null) {
317            mHomeAsUpIndicator = getThemeUpIndicator();
318            mHasCustomUpIndicator = false;
319        } else {
320            mHomeAsUpIndicator = indicator;
321            mHasCustomUpIndicator = true;
322        }
323
324        if (!mDrawerIndicatorEnabled) {
325            setActionBarUpIndicator(mHomeAsUpIndicator, 0);
326        }
327    }
328
329    /**
330     * Set the up indicator to display when the drawer indicator is not
331     * enabled.
332     * <p>
333     * If you pass 0 to this method, the default drawable from the theme will
334     * be used.
335     *
336     * @param resId Resource ID of a drawable to use for the up indicator, or 0
337     *              to use the theme's default
338     * @see #setDrawerIndicatorEnabled(boolean)
339     */
340    public void setHomeAsUpIndicator(int resId) {
341        Drawable indicator = null;
342        if (resId != 0) {
343            indicator = mDrawerLayout.getResources().getDrawable(resId);
344        }
345        setHomeAsUpIndicator(indicator);
346    }
347
348    /**
349     * @return true if the enhanced drawer indicator is enabled, false otherwise
350     * @see #setDrawerIndicatorEnabled(boolean)
351     */
352    public boolean isDrawerIndicatorEnabled() {
353        return mDrawerIndicatorEnabled;
354    }
355
356    /**
357     * Enable or disable the drawer indicator. The indicator defaults to enabled.
358     *
359     * <p>When the indicator is disabled, the <code>ActionBar</code> will revert to displaying
360     * the home-as-up indicator provided by the <code>Activity</code>'s theme in the
361     * <code>android.R.attr.homeAsUpIndicator</code> attribute instead of the animated
362     * drawer glyph.</p>
363     *
364     * @param enable true to enable, false to disable
365     */
366    public void setDrawerIndicatorEnabled(boolean enable) {
367        if (enable != mDrawerIndicatorEnabled) {
368            if (enable) {
369                setActionBarUpIndicator((Drawable) mSlider,
370                        mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
371                                mCloseDrawerContentDescRes : mOpenDrawerContentDescRes);
372            } else {
373                setActionBarUpIndicator(mHomeAsUpIndicator, 0);
374            }
375            mDrawerIndicatorEnabled = enable;
376        }
377    }
378
379
380    /**
381     * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
382     * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
383     * through to this method from your own listener object.
384     *
385     * @param drawerView  The child view that was moved
386     * @param slideOffset The new offset of this drawer within its range, from 0-1
387     */
388    @Override
389    public void onDrawerSlide(View drawerView, float slideOffset) {
390        mSlider.setPosition(Math.min(1f, Math.max(0, slideOffset)));
391    }
392
393    /**
394     * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
395     * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
396     * through to this method from your own listener object.
397     *
398     * @param drawerView Drawer view that is now open
399     */
400    @Override
401    public void onDrawerOpened(View drawerView) {
402        mSlider.setPosition(1);
403        if (mDrawerIndicatorEnabled) {
404            setActionBarDescription(mCloseDrawerContentDescRes);
405        }
406    }
407
408    /**
409     * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
410     * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
411     * through to this method from your own listener object.
412     *
413     * @param drawerView Drawer view that is now closed
414     */
415    @Override
416    public void onDrawerClosed(View drawerView) {
417        mSlider.setPosition(0);
418        if (mDrawerIndicatorEnabled) {
419            setActionBarDescription(mOpenDrawerContentDescRes);
420        }
421    }
422
423    /**
424     * {@link DrawerLayout.DrawerListener} callback method. If you do not use your
425     * ActionBarDrawerToggle instance directly as your DrawerLayout's listener, you should call
426     * through to this method from your own listener object.
427     *
428     * @param newState The new drawer motion state
429     */
430    @Override
431    public void onDrawerStateChanged(int newState) {
432    }
433
434    /**
435     * Returns the fallback listener for Navigation icon click events.
436     *
437     * @return The click listener which receives Navigation click events from Toolbar when
438     * drawer indicator is disabled.
439     * @see #setToolbarNavigationClickListener(android.view.View.OnClickListener)
440     * @see #setDrawerIndicatorEnabled(boolean)
441     * @see #isDrawerIndicatorEnabled()
442     */
443    public View.OnClickListener getToolbarNavigationClickListener() {
444        return mToolbarNavigationClickListener;
445    }
446
447    /**
448     * When DrawerToggle is constructed with a Toolbar, it sets the click listener on
449     * the Navigation icon. If you want to listen for clicks on the Navigation icon when
450     * DrawerToggle is disabled ({@link #setDrawerIndicatorEnabled(boolean)}, you should call this
451     * method with your listener and DrawerToggle will forward click events to that listener
452     * when drawer indicator is disabled.
453     *
454     * @see #setDrawerIndicatorEnabled(boolean)
455     */
456    public void setToolbarNavigationClickListener(
457            View.OnClickListener onToolbarNavigationClickListener) {
458        mToolbarNavigationClickListener = onToolbarNavigationClickListener;
459    }
460
461    void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) {
462        if (!mWarnedForDisplayHomeAsUp && !mActivityImpl.isNavigationVisible()) {
463            Log.w("ActionBarDrawerToggle", "DrawerToggle may not show up because NavigationIcon"
464                    + " is not visible. You may need to call "
465                    + "actionbar.setDisplayHomeAsUpEnabled(true);");
466            mWarnedForDisplayHomeAsUp = true;
467        }
468        mActivityImpl.setActionBarUpIndicator(upDrawable, contentDescRes);
469    }
470
471    void setActionBarDescription(int contentDescRes) {
472        mActivityImpl.setActionBarDescription(contentDescRes);
473    }
474
475    Drawable getThemeUpIndicator() {
476        return mActivityImpl.getThemeUpIndicator();
477    }
478
479    static class DrawerArrowDrawableToggle extends DrawerArrowDrawable
480            implements DrawerToggle {
481
482        private final Activity mActivity;
483
484        public DrawerArrowDrawableToggle(Activity activity, Context themedContext) {
485            super(themedContext);
486            mActivity = activity;
487        }
488
489        public void setPosition(float position) {
490            if (position == 1f) {
491                setVerticalMirror(true);
492            } else if (position == 0f) {
493                setVerticalMirror(false);
494            }
495            super.setProgress(position);
496        }
497
498        @Override
499        boolean isLayoutRtl() {
500            return ViewCompat.getLayoutDirection(mActivity.getWindow().getDecorView())
501                    == ViewCompat.LAYOUT_DIRECTION_RTL;
502        }
503
504        public float getPosition() {
505            return super.getProgress();
506        }
507    }
508
509    /**
510     * Interface for toggle drawables. Can be public in the future
511     */
512    static interface DrawerToggle {
513
514        public void setPosition(float position);
515
516        public float getPosition();
517    }
518
519    /**
520     * Delegate if SDK version is between honeycomb and JBMR2
521     */
522    private static class HoneycombDelegate implements Delegate {
523
524        final Activity mActivity;
525        ActionBarDrawerToggleHoneycomb.SetIndicatorInfo mSetIndicatorInfo;
526
527        private HoneycombDelegate(Activity activity) {
528            mActivity = activity;
529        }
530
531        @Override
532        public Drawable getThemeUpIndicator() {
533            return ActionBarDrawerToggleHoneycomb.getThemeUpIndicator(mActivity);
534        }
535
536        @Override
537        public Context getActionBarThemedContext() {
538            final ActionBar actionBar = mActivity.getActionBar();
539            final Context context;
540            if (actionBar != null) {
541                context = actionBar.getThemedContext();
542            } else {
543                context = mActivity;
544            }
545            return context;
546        }
547
548        @Override
549        public boolean isNavigationVisible() {
550            final ActionBar actionBar = mActivity.getActionBar();
551            return actionBar != null
552                    && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
553        }
554
555        @Override
556        public void setActionBarUpIndicator(Drawable themeImage, int contentDescRes) {
557            mActivity.getActionBar().setDisplayShowHomeEnabled(true);
558            mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarUpIndicator(
559                    mSetIndicatorInfo, mActivity, themeImage, contentDescRes);
560            mActivity.getActionBar().setDisplayShowHomeEnabled(false);
561        }
562
563        @Override
564        public void setActionBarDescription(int contentDescRes) {
565            mSetIndicatorInfo = ActionBarDrawerToggleHoneycomb.setActionBarDescription(
566                    mSetIndicatorInfo, mActivity, contentDescRes);
567        }
568    }
569
570    /**
571     * Delegate if SDK version is JB MR2 or newer
572     */
573    private static class JellybeanMr2Delegate implements Delegate {
574
575        final Activity mActivity;
576
577        private JellybeanMr2Delegate(Activity activity) {
578            mActivity = activity;
579        }
580
581        @Override
582        public Drawable getThemeUpIndicator() {
583            final TypedArray a = getActionBarThemedContext().obtainStyledAttributes(null,
584                    new int[]{android.R.attr.homeAsUpIndicator}, android.R.attr.actionBarStyle, 0);
585            final Drawable result = a.getDrawable(0);
586            a.recycle();
587            return result;
588        }
589
590        @Override
591        public Context getActionBarThemedContext() {
592            final ActionBar actionBar = mActivity.getActionBar();
593            final Context context;
594            if (actionBar != null) {
595                context = actionBar.getThemedContext();
596            } else {
597                context = mActivity;
598            }
599            return context;
600        }
601
602        @Override
603        public boolean isNavigationVisible() {
604            final ActionBar actionBar = mActivity.getActionBar();
605            return actionBar != null &&
606                    (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0;
607        }
608
609        @Override
610        public void setActionBarUpIndicator(Drawable drawable, int contentDescRes) {
611            final ActionBar actionBar = mActivity.getActionBar();
612            if (actionBar != null) {
613                actionBar.setHomeAsUpIndicator(drawable);
614                actionBar.setHomeActionContentDescription(contentDescRes);
615            }
616        }
617
618        @Override
619        public void setActionBarDescription(int contentDescRes) {
620            final ActionBar actionBar = mActivity.getActionBar();
621            if (actionBar != null) {
622                actionBar.setHomeActionContentDescription(contentDescRes);
623            }
624        }
625    }
626
627    /**
628     * Used when DrawerToggle is initialized with a Toolbar
629     */
630    static class ToolbarCompatDelegate implements Delegate {
631
632        final Toolbar mToolbar;
633        final Drawable mDefaultUpIndicator;
634        final CharSequence mDefaultContentDescription;
635
636        ToolbarCompatDelegate(Toolbar toolbar) {
637            mToolbar = toolbar;
638            mDefaultUpIndicator = toolbar.getNavigationIcon();
639            mDefaultContentDescription = toolbar.getNavigationContentDescription();
640        }
641
642        @Override
643        public void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes) {
644            mToolbar.setNavigationIcon(upDrawable);
645            setActionBarDescription(contentDescRes);
646        }
647
648        @Override
649        public void setActionBarDescription(@StringRes int contentDescRes) {
650            if (contentDescRes == 0) {
651                mToolbar.setNavigationContentDescription(mDefaultContentDescription);
652            } else {
653                mToolbar.setNavigationContentDescription(contentDescRes);
654            }
655        }
656
657        @Override
658        public Drawable getThemeUpIndicator() {
659            return mDefaultUpIndicator;
660        }
661
662        @Override
663        public Context getActionBarThemedContext() {
664            return mToolbar.getContext();
665        }
666
667        @Override
668        public boolean isNavigationVisible() {
669            return true;
670        }
671    }
672
673    /**
674     * Fallback delegate
675     */
676    static class DummyDelegate implements Delegate {
677        final Activity mActivity;
678
679        DummyDelegate(Activity activity) {
680            mActivity = activity;
681        }
682
683        @Override
684        public void setActionBarUpIndicator(Drawable upDrawable, @StringRes int contentDescRes) {
685
686        }
687
688        @Override
689        public void setActionBarDescription(@StringRes int contentDescRes) {
690
691        }
692
693        @Override
694        public Drawable getThemeUpIndicator() {
695            return null;
696        }
697
698        @Override
699        public Context getActionBarThemedContext() {
700            return mActivity;
701        }
702
703        @Override
704        public boolean isNavigationVisible() {
705            return true;
706        }
707    }
708}
709