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