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