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