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