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