1 /* 2 * Copyright (C) 2012 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 17 package androidx.appcompat.widget; 18 19 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21 import android.animation.Animator; 22 import android.animation.AnimatorListenerAdapter; 23 import android.content.Context; 24 import android.content.res.Configuration; 25 import android.content.res.TypedArray; 26 import android.graphics.Canvas; 27 import android.graphics.Rect; 28 import android.graphics.drawable.Drawable; 29 import android.os.Build; 30 import android.os.Parcelable; 31 import android.util.AttributeSet; 32 import android.util.SparseArray; 33 import android.view.Menu; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.view.ViewPropertyAnimator; 37 import android.view.Window; 38 import android.widget.OverScroller; 39 40 import androidx.annotation.RestrictTo; 41 import androidx.appcompat.R; 42 import androidx.appcompat.app.AppCompatDelegate; 43 import androidx.appcompat.view.menu.MenuPresenter; 44 import androidx.core.view.NestedScrollingParent; 45 import androidx.core.view.NestedScrollingParentHelper; 46 import androidx.core.view.ViewCompat; 47 48 /** 49 * Special layout for the containing of an overlay action bar (and its content) to correctly handle 50 * fitting system windows when the content has request that its layout ignore them. 51 * 52 * @hide 53 */ 54 @RestrictTo(LIBRARY_GROUP) 55 public class ActionBarOverlayLayout extends ViewGroup implements DecorContentParent, 56 NestedScrollingParent { 57 private static final String TAG = "ActionBarOverlayLayout"; 58 59 private int mActionBarHeight; 60 //private WindowDecorActionBar mActionBar; 61 private int mWindowVisibility = View.VISIBLE; 62 63 // The main UI elements that we handle the layout of. 64 private ContentFrameLayout mContent; 65 ActionBarContainer mActionBarTop; 66 67 // Some interior UI elements. 68 private DecorToolbar mDecorToolbar; 69 70 // Content overlay drawable - generally the action bar's shadow 71 private Drawable mWindowContentOverlay; 72 private boolean mIgnoreWindowContentOverlay; 73 74 private boolean mOverlayMode; 75 private boolean mHasNonEmbeddedTabs; 76 private boolean mHideOnContentScroll; 77 boolean mAnimatingForFling; 78 private int mHideOnContentScrollReference; 79 private int mLastSystemUiVisibility; 80 private final Rect mBaseContentInsets = new Rect(); 81 private final Rect mLastBaseContentInsets = new Rect(); 82 private final Rect mContentInsets = new Rect(); 83 private final Rect mBaseInnerInsets = new Rect(); 84 private final Rect mLastBaseInnerInsets = new Rect(); 85 private final Rect mInnerInsets = new Rect(); 86 private final Rect mLastInnerInsets = new Rect(); 87 88 private ActionBarVisibilityCallback mActionBarVisibilityCallback; 89 90 private static final int ACTION_BAR_ANIMATE_DELAY = 600; // ms 91 92 private OverScroller mFlingEstimator; 93 94 ViewPropertyAnimator mCurrentActionBarTopAnimator; 95 96 final AnimatorListenerAdapter mTopAnimatorListener = new AnimatorListenerAdapter() { 97 @Override 98 public void onAnimationEnd(Animator animator) { 99 mCurrentActionBarTopAnimator = null; 100 mAnimatingForFling = false; 101 } 102 103 @Override 104 public void onAnimationCancel(Animator animator) { 105 mCurrentActionBarTopAnimator = null; 106 mAnimatingForFling = false; 107 } 108 }; 109 110 private final Runnable mRemoveActionBarHideOffset = new Runnable() { 111 @Override 112 public void run() { 113 haltActionBarHideOffsetAnimations(); 114 mCurrentActionBarTopAnimator = mActionBarTop.animate().translationY(0) 115 .setListener(mTopAnimatorListener); 116 } 117 }; 118 119 private final Runnable mAddActionBarHideOffset = new Runnable() { 120 @Override 121 public void run() { 122 haltActionBarHideOffsetAnimations(); 123 mCurrentActionBarTopAnimator = mActionBarTop.animate() 124 .translationY(-mActionBarTop.getHeight()) 125 .setListener(mTopAnimatorListener); 126 } 127 }; 128 129 static final int[] ATTRS = new int [] { 130 R.attr.actionBarSize, 131 android.R.attr.windowContentOverlay 132 }; 133 134 private final NestedScrollingParentHelper mParentHelper; 135 ActionBarOverlayLayout(Context context)136 public ActionBarOverlayLayout(Context context) { 137 this(context, null); 138 } 139 ActionBarOverlayLayout(Context context, AttributeSet attrs)140 public ActionBarOverlayLayout(Context context, AttributeSet attrs) { 141 super(context, attrs); 142 init(context); 143 144 mParentHelper = new NestedScrollingParentHelper(this); 145 } 146 init(Context context)147 private void init(Context context) { 148 TypedArray ta = getContext().getTheme().obtainStyledAttributes(ATTRS); 149 mActionBarHeight = ta.getDimensionPixelSize(0, 0); 150 mWindowContentOverlay = ta.getDrawable(1); 151 setWillNotDraw(mWindowContentOverlay == null); 152 ta.recycle(); 153 154 mIgnoreWindowContentOverlay = context.getApplicationInfo().targetSdkVersion < 155 Build.VERSION_CODES.KITKAT; 156 157 mFlingEstimator = new OverScroller(context); 158 } 159 160 @Override 161 protected void onDetachedFromWindow() { 162 super.onDetachedFromWindow(); 163 haltActionBarHideOffsetAnimations(); 164 } 165 166 public void setActionBarVisibilityCallback(ActionBarVisibilityCallback cb) { 167 mActionBarVisibilityCallback = cb; 168 if (getWindowToken() != null) { 169 // This is being initialized after being added to a window; 170 // make sure to update all state now. 171 mActionBarVisibilityCallback.onWindowVisibilityChanged(mWindowVisibility); 172 if (mLastSystemUiVisibility != 0) { 173 int newVis = mLastSystemUiVisibility; 174 onWindowSystemUiVisibilityChanged(newVis); 175 ViewCompat.requestApplyInsets(this); 176 } 177 } 178 } 179 180 public void setOverlayMode(boolean overlayMode) { 181 mOverlayMode = overlayMode; 182 183 /* 184 * Drawing the window content overlay was broken before K so starting to draw it 185 * again unexpectedly will cause artifacts in some apps. They should fix it. 186 */ 187 mIgnoreWindowContentOverlay = overlayMode && 188 getContext().getApplicationInfo().targetSdkVersion < 189 Build.VERSION_CODES.KITKAT; 190 } 191 192 public boolean isInOverlayMode() { 193 return mOverlayMode; 194 } 195 196 public void setHasNonEmbeddedTabs(boolean hasNonEmbeddedTabs) { 197 mHasNonEmbeddedTabs = hasNonEmbeddedTabs; 198 } 199 200 public void setShowingForActionMode(boolean showing) { 201 // TODO: Add workaround for this 202 // if (showing) { 203 // // Here's a fun hack: if the status bar is currently being hidden, 204 // // and the application has asked for stable content insets, then 205 // // we will end up with the action mode action bar being shown 206 // // without the status bar, but moved below where the status bar 207 // // would be. Not nice. Trying to have this be positioned 208 // // correctly is not easy (basically we need yet *another* content 209 // // inset from the window manager to know where to put it), so 210 // // instead we will just temporarily force the status bar to be shown. 211 // if ((getWindowSystemUiVisibility() & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 212 // | SYSTEM_UI_FLAG_LAYOUT_STABLE)) 213 // == (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE)) { 214 // setDisabledSystemUiVisibility(SYSTEM_UI_FLAG_FULLSCREEN); 215 // } 216 // } else { 217 // setDisabledSystemUiVisibility(0); 218 // } 219 } 220 221 @Override 222 protected void onConfigurationChanged(Configuration newConfig) { 223 super.onConfigurationChanged(newConfig); 224 init(getContext()); 225 ViewCompat.requestApplyInsets(this); 226 } 227 228 @Override 229 public void onWindowSystemUiVisibilityChanged(int visible) { 230 if (Build.VERSION.SDK_INT >= 16) { 231 super.onWindowSystemUiVisibilityChanged(visible); 232 } 233 pullChildren(); 234 final int diff = mLastSystemUiVisibility ^ visible; 235 mLastSystemUiVisibility = visible; 236 final boolean barVisible = (visible & SYSTEM_UI_FLAG_FULLSCREEN) == 0; 237 final boolean stable = (visible & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0; 238 if (mActionBarVisibilityCallback != null) { 239 // We want the bar to be visible if it is not being hidden, 240 // or the app has not turned on a stable UI mode (meaning they 241 // are performing explicit layout around the action bar). 242 mActionBarVisibilityCallback.enableContentAnimations(!stable); 243 if (barVisible || !stable) mActionBarVisibilityCallback.showForSystem(); 244 else mActionBarVisibilityCallback.hideForSystem(); 245 } 246 if ((diff & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 247 if (mActionBarVisibilityCallback != null) { 248 ViewCompat.requestApplyInsets(this); 249 } 250 } 251 } 252 253 @Override 254 protected void onWindowVisibilityChanged(int visibility) { 255 super.onWindowVisibilityChanged(visibility); 256 mWindowVisibility = visibility; 257 if (mActionBarVisibilityCallback != null) { 258 mActionBarVisibilityCallback.onWindowVisibilityChanged(visibility); 259 } 260 } 261 262 private boolean applyInsets(View view, Rect insets, boolean left, boolean top, 263 boolean bottom, boolean right) { 264 boolean changed = false; 265 LayoutParams lp = (LayoutParams)view.getLayoutParams(); 266 if (left && lp.leftMargin != insets.left) { 267 changed = true; 268 lp.leftMargin = insets.left; 269 } 270 if (top && lp.topMargin != insets.top) { 271 changed = true; 272 lp.topMargin = insets.top; 273 } 274 if (right && lp.rightMargin != insets.right) { 275 changed = true; 276 lp.rightMargin = insets.right; 277 } 278 if (bottom && lp.bottomMargin != insets.bottom) { 279 changed = true; 280 lp.bottomMargin = insets.bottom; 281 } 282 return changed; 283 } 284 285 @Override 286 protected boolean fitSystemWindows(Rect insets) { 287 pullChildren(); 288 289 final int vis = ViewCompat.getWindowSystemUiVisibility(this); 290 final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0; 291 final Rect systemInsets = insets; 292 293 // The top action bar is always within the content area. 294 boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true); 295 296 mBaseInnerInsets.set(systemInsets); 297 ViewUtils.computeFitSystemWindows(this, mBaseInnerInsets, mBaseContentInsets); 298 if (!mLastBaseInnerInsets.equals(mBaseInnerInsets)) { 299 changed = true; 300 mLastBaseInnerInsets.set(mBaseInnerInsets); 301 } 302 if (!mLastBaseContentInsets.equals(mBaseContentInsets)) { 303 changed = true; 304 mLastBaseContentInsets.set(mBaseContentInsets); 305 } 306 307 if (changed) { 308 requestLayout(); 309 } 310 311 // We don't do any more at this point. To correctly compute the content/inner 312 // insets in all cases, we need to know the measured size of the various action 313 // bar elements. fitSystemWindows() happens before the measure pass, so we can't 314 // do that here. Instead we will take this up in onMeasure(). 315 return true; 316 } 317 318 @Override 319 protected LayoutParams generateDefaultLayoutParams() { 320 return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 321 } 322 323 @Override 324 public LayoutParams generateLayoutParams(AttributeSet attrs) { 325 return new LayoutParams(getContext(), attrs); 326 } 327 328 @Override 329 protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 330 return new LayoutParams(p); 331 } 332 333 @Override 334 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 335 return p instanceof LayoutParams; 336 } 337 338 @Override 339 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 340 pullChildren(); 341 342 int maxHeight = 0; 343 int maxWidth = 0; 344 int childState = 0; 345 346 int topInset = 0; 347 int bottomInset = 0; 348 349 measureChildWithMargins(mActionBarTop, widthMeasureSpec, 0, heightMeasureSpec, 0); 350 LayoutParams lp = (LayoutParams) mActionBarTop.getLayoutParams(); 351 maxWidth = Math.max(maxWidth, 352 mActionBarTop.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); 353 maxHeight = Math.max(maxHeight, 354 mActionBarTop.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); 355 childState = View.combineMeasuredStates(childState, mActionBarTop.getMeasuredState()); 356 357 final int vis = ViewCompat.getWindowSystemUiVisibility(this); 358 final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0; 359 360 if (stable) { 361 // This is the standard space needed for the action bar. For stable measurement, 362 // we can't depend on the size currently reported by it -- this must remain constant. 363 topInset = mActionBarHeight; 364 if (mHasNonEmbeddedTabs) { 365 final View tabs = mActionBarTop.getTabContainer(); 366 if (tabs != null) { 367 // If tabs are not embedded, increase space on top to account for them. 368 topInset += mActionBarHeight; 369 } 370 } 371 } else if (mActionBarTop.getVisibility() != GONE) { 372 // This is the space needed on top of the window for all of the action bar 373 // and tabs. 374 topInset = mActionBarTop.getMeasuredHeight(); 375 } 376 377 // If the window has not requested system UI layout flags, we need to 378 // make sure its content is not being covered by system UI... though it 379 // will still be covered by the action bar if they have requested it to 380 // overlay. 381 mContentInsets.set(mBaseContentInsets); 382 mInnerInsets.set(mBaseInnerInsets); 383 if (!mOverlayMode && !stable) { 384 mContentInsets.top += topInset; 385 mContentInsets.bottom += bottomInset; 386 } else { 387 mInnerInsets.top += topInset; 388 mInnerInsets.bottom += bottomInset; 389 } 390 applyInsets(mContent, mContentInsets, true, true, true, true); 391 392 if (!mLastInnerInsets.equals(mInnerInsets)) { 393 // If the inner insets have changed, we need to dispatch this down to 394 // the app's fitSystemWindows(). We do this before measuring the content 395 // view to keep the same semantics as the normal fitSystemWindows() call. 396 mLastInnerInsets.set(mInnerInsets); 397 398 mContent.dispatchFitSystemWindows(mInnerInsets); 399 } 400 401 measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec, 0); 402 lp = (LayoutParams) mContent.getLayoutParams(); 403 maxWidth = Math.max(maxWidth, 404 mContent.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); 405 maxHeight = Math.max(maxHeight, 406 mContent.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); 407 childState = View.combineMeasuredStates(childState, mContent.getMeasuredState()); 408 409 // Account for padding too 410 maxWidth += getPaddingLeft() + getPaddingRight(); 411 maxHeight += getPaddingTop() + getPaddingBottom(); 412 413 // Check against our minimum height and width 414 maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 415 maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 416 417 setMeasuredDimension( 418 View.resolveSizeAndState(maxWidth, widthMeasureSpec, childState), 419 View.resolveSizeAndState(maxHeight, heightMeasureSpec, 420 childState << MEASURED_HEIGHT_STATE_SHIFT)); 421 } 422 423 @Override 424 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 425 final int count = getChildCount(); 426 427 final int parentLeft = getPaddingLeft(); 428 final int parentRight = right - left - getPaddingRight(); 429 430 final int parentTop = getPaddingTop(); 431 final int parentBottom = bottom - top - getPaddingBottom(); 432 433 for (int i = 0; i < count; i++) { 434 final View child = getChildAt(i); 435 if (child.getVisibility() != GONE) { 436 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 437 438 final int width = child.getMeasuredWidth(); 439 final int height = child.getMeasuredHeight(); 440 441 int childLeft = parentLeft + lp.leftMargin; 442 int childTop = parentTop + lp.topMargin; 443 444 child.layout(childLeft, childTop, childLeft + width, childTop + height); 445 } 446 } 447 } 448 449 @Override 450 public void draw(Canvas c) { 451 super.draw(c); 452 if (mWindowContentOverlay != null && !mIgnoreWindowContentOverlay) { 453 final int top = mActionBarTop.getVisibility() == VISIBLE ? 454 (int) (mActionBarTop.getBottom() + mActionBarTop.getTranslationY() + 0.5f) 455 : 0; 456 mWindowContentOverlay.setBounds(0, top, getWidth(), 457 top + mWindowContentOverlay.getIntrinsicHeight()); 458 mWindowContentOverlay.draw(c); 459 } 460 } 461 462 @Override 463 public boolean shouldDelayChildPressedState() { 464 return false; 465 } 466 467 @Override 468 public boolean onStartNestedScroll(View child, View target, int axes) { 469 if ((axes & SCROLL_AXIS_VERTICAL) == 0 || mActionBarTop.getVisibility() != VISIBLE) { 470 return false; 471 } 472 return mHideOnContentScroll; 473 } 474 475 @Override 476 public void onNestedScrollAccepted(View child, View target, int axes) { 477 mParentHelper.onNestedScrollAccepted(child, target, axes); 478 mHideOnContentScrollReference = getActionBarHideOffset(); 479 haltActionBarHideOffsetAnimations(); 480 if (mActionBarVisibilityCallback != null) { 481 mActionBarVisibilityCallback.onContentScrollStarted(); 482 } 483 } 484 485 @Override 486 public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 487 int dxUnconsumed, int dyUnconsumed) { 488 mHideOnContentScrollReference += dyConsumed; 489 setActionBarHideOffset(mHideOnContentScrollReference); 490 } 491 492 @Override 493 public void onStopNestedScroll(View target) { 494 if (mHideOnContentScroll && !mAnimatingForFling) { 495 if (mHideOnContentScrollReference <= mActionBarTop.getHeight()) { 496 postRemoveActionBarHideOffset(); 497 } else { 498 postAddActionBarHideOffset(); 499 } 500 } 501 if (mActionBarVisibilityCallback != null) { 502 mActionBarVisibilityCallback.onContentScrollStopped(); 503 } 504 } 505 506 @Override 507 public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 508 if (!mHideOnContentScroll || !consumed) { 509 return false; 510 } 511 if (shouldHideActionBarOnFling(velocityX, velocityY)) { 512 addActionBarHideOffset(); 513 } else { 514 removeActionBarHideOffset(); 515 } 516 mAnimatingForFling = true; 517 return true; 518 } 519 520 @Override 521 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 522 // no-op 523 } 524 525 @Override 526 public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 527 return false; 528 } 529 530 @Override 531 public int getNestedScrollAxes() { 532 return mParentHelper.getNestedScrollAxes(); 533 } 534 535 void pullChildren() { 536 if (mContent == null) { 537 mContent = findViewById(R.id.action_bar_activity_content); 538 mActionBarTop = findViewById(R.id.action_bar_container); 539 mDecorToolbar = getDecorToolbar(findViewById(R.id.action_bar)); 540 } 541 } 542 543 private DecorToolbar getDecorToolbar(View view) { 544 if (view instanceof DecorToolbar) { 545 return (DecorToolbar) view; 546 } else if (view instanceof Toolbar) { 547 return ((Toolbar) view).getWrapper(); 548 } else { 549 throw new IllegalStateException("Can't make a decor toolbar out of " + 550 view.getClass().getSimpleName()); 551 } 552 } 553 554 public void setHideOnContentScrollEnabled(boolean hideOnContentScroll) { 555 if (hideOnContentScroll != mHideOnContentScroll) { 556 mHideOnContentScroll = hideOnContentScroll; 557 if (!hideOnContentScroll) { 558 haltActionBarHideOffsetAnimations(); 559 setActionBarHideOffset(0); 560 } 561 } 562 } 563 564 public boolean isHideOnContentScrollEnabled() { 565 return mHideOnContentScroll; 566 } 567 568 public int getActionBarHideOffset() { 569 return mActionBarTop != null ? -((int) mActionBarTop.getTranslationY()) : 0; 570 } 571 572 public void setActionBarHideOffset(int offset) { 573 haltActionBarHideOffsetAnimations(); 574 final int topHeight = mActionBarTop.getHeight(); 575 offset = Math.max(0, Math.min(offset, topHeight)); 576 mActionBarTop.setTranslationY(-offset); 577 } 578 579 void haltActionBarHideOffsetAnimations() { 580 removeCallbacks(mRemoveActionBarHideOffset); 581 removeCallbacks(mAddActionBarHideOffset); 582 if (mCurrentActionBarTopAnimator != null) { 583 mCurrentActionBarTopAnimator.cancel(); 584 } 585 } 586 587 private void postRemoveActionBarHideOffset() { 588 haltActionBarHideOffsetAnimations(); 589 postDelayed(mRemoveActionBarHideOffset, ACTION_BAR_ANIMATE_DELAY); 590 } 591 592 private void postAddActionBarHideOffset() { 593 haltActionBarHideOffsetAnimations(); 594 postDelayed(mAddActionBarHideOffset, ACTION_BAR_ANIMATE_DELAY); 595 } 596 597 private void removeActionBarHideOffset() { 598 haltActionBarHideOffsetAnimations(); 599 mRemoveActionBarHideOffset.run(); 600 } 601 602 private void addActionBarHideOffset() { 603 haltActionBarHideOffsetAnimations(); 604 mAddActionBarHideOffset.run(); 605 } 606 607 private boolean shouldHideActionBarOnFling(float velocityX, float velocityY) { 608 mFlingEstimator.fling(0, 0, 0, (int) velocityY, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE); 609 final int finalY = mFlingEstimator.getFinalY(); 610 return finalY > mActionBarTop.getHeight(); 611 } 612 613 @Override 614 public void setWindowCallback(Window.Callback cb) { 615 pullChildren(); 616 mDecorToolbar.setWindowCallback(cb); 617 } 618 619 @Override 620 public void setWindowTitle(CharSequence title) { 621 pullChildren(); 622 mDecorToolbar.setWindowTitle(title); 623 } 624 625 @Override 626 public CharSequence getTitle() { 627 pullChildren(); 628 return mDecorToolbar.getTitle(); 629 } 630 631 @Override 632 public void initFeature(int windowFeature) { 633 pullChildren(); 634 switch (windowFeature) { 635 case Window.FEATURE_PROGRESS: 636 mDecorToolbar.initProgress(); 637 break; 638 case Window.FEATURE_INDETERMINATE_PROGRESS: 639 mDecorToolbar.initIndeterminateProgress(); 640 break; 641 case AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR_OVERLAY: 642 setOverlayMode(true); 643 break; 644 } 645 } 646 647 @Override 648 public void setUiOptions(int uiOptions) { 649 // Split Action Bar not included. 650 } 651 652 @Override 653 public boolean hasIcon() { 654 pullChildren(); 655 return mDecorToolbar.hasIcon(); 656 } 657 658 @Override 659 public boolean hasLogo() { 660 pullChildren(); 661 return mDecorToolbar.hasLogo(); 662 } 663 664 @Override 665 public void setIcon(int resId) { 666 pullChildren(); 667 mDecorToolbar.setIcon(resId); 668 } 669 670 @Override 671 public void setIcon(Drawable d) { 672 pullChildren(); 673 mDecorToolbar.setIcon(d); 674 } 675 676 @Override 677 public void setLogo(int resId) { 678 pullChildren(); 679 mDecorToolbar.setLogo(resId); 680 } 681 682 @Override 683 public boolean canShowOverflowMenu() { 684 pullChildren(); 685 return mDecorToolbar.canShowOverflowMenu(); 686 } 687 688 @Override 689 public boolean isOverflowMenuShowing() { 690 pullChildren(); 691 return mDecorToolbar.isOverflowMenuShowing(); 692 } 693 694 @Override 695 public boolean isOverflowMenuShowPending() { 696 pullChildren(); 697 return mDecorToolbar.isOverflowMenuShowPending(); 698 } 699 700 @Override 701 public boolean showOverflowMenu() { 702 pullChildren(); 703 return mDecorToolbar.showOverflowMenu(); 704 } 705 706 @Override 707 public boolean hideOverflowMenu() { 708 pullChildren(); 709 return mDecorToolbar.hideOverflowMenu(); 710 } 711 712 @Override 713 public void setMenuPrepared() { 714 pullChildren(); 715 mDecorToolbar.setMenuPrepared(); 716 } 717 718 @Override 719 public void setMenu(Menu menu, MenuPresenter.Callback cb) { 720 pullChildren(); 721 mDecorToolbar.setMenu(menu, cb); 722 } 723 724 @Override 725 public void saveToolbarHierarchyState(SparseArray<Parcelable> toolbarStates) { 726 pullChildren(); 727 mDecorToolbar.saveHierarchyState(toolbarStates); 728 } 729 730 @Override 731 public void restoreToolbarHierarchyState(SparseArray<Parcelable> toolbarStates) { 732 pullChildren(); 733 mDecorToolbar.restoreHierarchyState(toolbarStates); 734 } 735 736 @Override 737 public void dismissPopups() { 738 pullChildren(); 739 mDecorToolbar.dismissPopupMenus(); 740 } 741 742 public static class LayoutParams extends MarginLayoutParams { 743 public LayoutParams(Context c, AttributeSet attrs) { 744 super(c, attrs); 745 } 746 747 public LayoutParams(int width, int height) { 748 super(width, height); 749 } 750 751 public LayoutParams(ViewGroup.LayoutParams source) { 752 super(source); 753 } 754 755 public LayoutParams(ViewGroup.MarginLayoutParams source) { 756 super(source); 757 } 758 } 759 760 public interface ActionBarVisibilityCallback { 761 void onWindowVisibilityChanged(int visibility); 762 void showForSystem(); 763 void hideForSystem(); 764 void enableContentAnimations(boolean enable); 765 void onContentScrollStarted(); 766 void onContentScrollStopped(); 767 } 768 } 769