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