StatusBarHeaderView.java revision 31ba192dd201df2cad96a8c503f730130ab0d80f
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 */ 16 17package com.android.systemui.statusbar.phone; 18 19import android.content.Context; 20import android.content.Intent; 21import android.graphics.Outline; 22import android.graphics.Rect; 23import android.graphics.drawable.Drawable; 24import android.util.AttributeSet; 25import android.view.View; 26import android.view.ViewGroup; 27import android.view.ViewOutlineProvider; 28import android.widget.ImageView; 29import android.widget.LinearLayout; 30import android.widget.RelativeLayout; 31import android.widget.Switch; 32import android.widget.TextView; 33 34import com.android.systemui.R; 35import com.android.systemui.qs.QSPanel; 36import com.android.systemui.qs.QSTile; 37import com.android.systemui.statusbar.policy.BatteryController; 38import com.android.systemui.statusbar.policy.UserInfoController; 39 40/** 41 * The view to manage the header area in the expanded status bar. 42 */ 43public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener, 44 BatteryController.BatteryStateChangeCallback { 45 46 private boolean mExpanded; 47 private boolean mListening; 48 private boolean mOverscrolled; 49 private boolean mKeyguardShowing; 50 private boolean mCharging; 51 52 private ViewGroup mSystemIconsContainer; 53 private View mSystemIconsSuperContainer; 54 private View mDateTime; 55 private View mTime; 56 private View mAmPm; 57 private View mKeyguardCarrierText; 58 private MultiUserSwitch mMultiUserSwitch; 59 private ImageView mMultiUserAvatar; 60 private View mDateCollapsed; 61 private View mDateExpanded; 62 private View mStatusIcons; 63 private View mSignalCluster; 64 private View mSettingsButton; 65 private View mQsDetailHeader; 66 private TextView mQsDetailHeaderTitle; 67 private Switch mQsDetailHeaderSwitch; 68 private View mEmergencyCallsOnly; 69 private TextView mBatteryLevel; 70 71 private boolean mShowEmergencyCallsOnly; 72 private boolean mKeyguardUserSwitcherShowing; 73 74 private int mCollapsedHeight; 75 private int mExpandedHeight; 76 private int mKeyguardHeight; 77 78 private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT; 79 private int mNormalWidth; 80 private int mPadding; 81 private int mMultiUserExpandedMargin; 82 private int mMultiUserCollapsedMargin; 83 private int mMultiUserKeyguardMargin; 84 private int mSystemIconsSwitcherHiddenExpandedMargin; 85 private int mClockMarginBottomExpanded; 86 private int mMultiUserSwitchWidthCollapsed; 87 private int mMultiUserSwitchWidthExpanded; 88 private int mBatteryPaddingEnd; 89 90 /** 91 * In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice 92 * transition. These values determine that factor. 93 */ 94 private float mClockCollapsedScaleFactor; 95 private float mAvatarCollapsedScaleFactor; 96 97 private ActivityStarter mActivityStarter; 98 private BatteryController mBatteryController; 99 private QSPanel mQSPanel; 100 101 private final Rect mClipBounds = new Rect(); 102 103 public StatusBarHeaderView(Context context, AttributeSet attrs) { 104 super(context, attrs); 105 } 106 107 @Override 108 protected void onFinishInflate() { 109 super.onFinishInflate(); 110 mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container); 111 mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container); 112 mSystemIconsSuperContainer.setOnClickListener(this); 113 mDateTime = findViewById(R.id.datetime); 114 mTime = findViewById(R.id.time_view); 115 mAmPm = findViewById(R.id.am_pm_view); 116 mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text); 117 mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); 118 mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar); 119 mDateCollapsed = findViewById(R.id.date_collapsed); 120 mDateExpanded = findViewById(R.id.date_expanded); 121 mSettingsButton = findViewById(R.id.settings_button); 122 mSettingsButton.setOnClickListener(this); 123 mQsDetailHeader = findViewById(R.id.qs_detail_header); 124 mQsDetailHeader.setAlpha(0); 125 mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title); 126 mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle); 127 mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only); 128 mBatteryLevel = (TextView) findViewById(R.id.battery_level); 129 loadDimens(); 130 updateVisibilities(); 131 updateClockScale(); 132 updateAvatarScale(); 133 addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 134 @Override 135 public void onLayoutChange(View v, int left, int top, int right, 136 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 137 if ((right - left) != (oldRight - oldLeft)) { 138 // width changed, update clipping 139 setClipping(getHeight()); 140 } 141 boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; 142 mTime.setPivotX(rtl ? mTime.getWidth() : 0); 143 mTime.setPivotY(mTime.getBaseline()); 144 mAmPm.setPivotX(rtl ? mAmPm.getWidth() : 0); 145 mAmPm.setPivotY(mAmPm.getBaseline()); 146 updateAmPmTranslation(); 147 } 148 }); 149 setOutlineProvider(new ViewOutlineProvider() { 150 @Override 151 public void getOutline(View view, Outline outline) { 152 outline.setRect(mClipBounds); 153 } 154 }); 155 } 156 157 private void loadDimens() { 158 mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height); 159 mExpandedHeight = getResources().getDimensionPixelSize( 160 R.dimen.status_bar_header_height_expanded); 161 mKeyguardHeight = getResources().getDimensionPixelSize( 162 R.dimen.status_bar_header_height_keyguard); 163 mNormalWidth = getLayoutParams().width; 164 mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding); 165 mMultiUserExpandedMargin = 166 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin); 167 mMultiUserCollapsedMargin = 168 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin); 169 mMultiUserKeyguardMargin = 170 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_keyguard_margin); 171 mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize( 172 R.dimen.system_icons_switcher_hidden_expanded_margin); 173 mClockMarginBottomExpanded = 174 getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin); 175 mMultiUserSwitchWidthCollapsed = 176 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed); 177 mMultiUserSwitchWidthExpanded = 178 getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_expanded); 179 mAvatarCollapsedScaleFactor = 180 getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size) 181 / (float) mMultiUserAvatar.getLayoutParams().width; 182 mClockCollapsedScaleFactor = 183 (float) getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size) 184 / (float) getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size); 185 mBatteryPaddingEnd = 186 getResources().getDimensionPixelSize(R.dimen.battery_level_padding_end); 187 } 188 189 public void setActivityStarter(ActivityStarter activityStarter) { 190 mActivityStarter = activityStarter; 191 } 192 193 public void setBatteryController(BatteryController batteryController) { 194 mBatteryController = batteryController; 195 } 196 197 public int getCollapsedHeight() { 198 return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight; 199 } 200 201 public int getExpandedHeight() { 202 return mExpandedHeight; 203 } 204 205 public void setListening(boolean listening) { 206 if (listening == mListening) { 207 return; 208 } 209 mListening = listening; 210 updateBatteryListening(); 211 } 212 213 public void setExpanded(boolean expanded, boolean overscrolled) { 214 boolean changed = expanded != mExpanded; 215 boolean overscrollChanged = overscrolled != mOverscrolled; 216 mExpanded = expanded; 217 mOverscrolled = overscrolled; 218 if (changed || overscrollChanged) { 219 updateHeights(); 220 updateVisibilities(); 221 updateSystemIconsLayoutParams(); 222 updateZTranslation(); 223 updateClickTargets(); 224 updateWidth(); 225 updatePadding(); 226 updateMultiUserSwitch(); 227 if (mQSPanel != null) { 228 mQSPanel.setExpanded(expanded && !overscrolled); 229 } 230 updateClockScale(); 231 updateAvatarScale(); 232 updateClockLp(); 233 updateBatteryLevelPaddingEnd(); 234 } 235 } 236 237 private void updateHeights() { 238 boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded; 239 int height; 240 if (mExpanded) { 241 height = mExpandedHeight; 242 } else if (onKeyguardAndCollapsed) { 243 height = mKeyguardHeight; 244 } else { 245 height = mCollapsedHeight; 246 } 247 ViewGroup.LayoutParams lp = getLayoutParams(); 248 if (lp.height != height) { 249 lp.height = height; 250 setLayoutParams(lp); 251 } 252 int systemIconsContainerHeight = onKeyguardAndCollapsed ? mKeyguardHeight : mCollapsedHeight; 253 lp = mSystemIconsSuperContainer.getLayoutParams(); 254 if (lp.height != systemIconsContainerHeight) { 255 lp.height = systemIconsContainerHeight; 256 mSystemIconsSuperContainer.setLayoutParams(lp); 257 } 258 lp = mMultiUserSwitch.getLayoutParams(); 259 if (lp.height != systemIconsContainerHeight) { 260 lp.height = systemIconsContainerHeight; 261 mMultiUserSwitch.setLayoutParams(lp); 262 } 263 } 264 265 private void updateWidth() { 266 int width = (mKeyguardShowing && !mExpanded) ? mKeyguardWidth : mNormalWidth; 267 ViewGroup.LayoutParams lp = getLayoutParams(); 268 if (width != lp.width) { 269 lp.width = width; 270 setLayoutParams(lp); 271 } 272 } 273 274 private void updateVisibilities() { 275 boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded; 276 if (onKeyguardAndCollapsed) { 277 setBackground(null); 278 } else { 279 setBackgroundResource(R.drawable.notification_header_bg); 280 } 281 mDateTime.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE); 282 mKeyguardCarrierText.setVisibility(onKeyguardAndCollapsed ? View.VISIBLE : View.GONE); 283 mDateCollapsed.setVisibility(mExpanded && !mOverscrolled ? View.GONE : View.VISIBLE); 284 mDateExpanded.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE); 285 mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE); 286 mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE); 287 if (mStatusIcons != null) { 288 mStatusIcons.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE); 289 } 290 if (mSignalCluster != null) { 291 mSignalCluster.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE); 292 } 293 mEmergencyCallsOnly.setVisibility(mExpanded && !mOverscrolled && mShowEmergencyCallsOnly 294 ? VISIBLE : GONE); 295 mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing 296 ? VISIBLE : GONE); 297 mBatteryLevel.setVisibility(mKeyguardShowing && mCharging || mExpanded && !mOverscrolled 298 ? View.VISIBLE : View.GONE); 299 } 300 301 private void updateSystemIconsLayoutParams() { 302 RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams(); 303 lp.addRule(RelativeLayout.START_OF, mExpanded && !mOverscrolled 304 ? mSettingsButton.getId() 305 : mMultiUserSwitch.getId()); 306 lp.removeRule(ALIGN_PARENT_START); 307 if (mMultiUserSwitch.getVisibility() == GONE) { 308 lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin); 309 } else { 310 lp.setMarginEnd(0); 311 } 312 mSystemIconsSuperContainer.setLayoutParams(lp); 313 } 314 315 private void updateBatteryListening() { 316 if (mListening) { 317 mBatteryController.addStateChangedCallback(this); 318 } else { 319 mBatteryController.removeStateChangedCallback(this); 320 } 321 } 322 323 private void updateAvatarScale() { 324 if (!mExpanded || mOverscrolled) { 325 mMultiUserSwitch.setScaleX(mAvatarCollapsedScaleFactor); 326 mMultiUserSwitch.setScaleY(mAvatarCollapsedScaleFactor); 327 } else { 328 mMultiUserSwitch.setScaleX(1f); 329 mMultiUserSwitch.setScaleY(1f); 330 } 331 } 332 333 private void updateClockScale() { 334 mAmPm.setScaleX(mClockCollapsedScaleFactor); 335 mAmPm.setScaleY(mClockCollapsedScaleFactor); 336 if (!mExpanded || mOverscrolled) { 337 mTime.setScaleX(mClockCollapsedScaleFactor); 338 mTime.setScaleY(mClockCollapsedScaleFactor); 339 } else { 340 mTime.setScaleX(1f); 341 mTime.setScaleY(1f); 342 } 343 updateAmPmTranslation(); 344 } 345 346 private void updateAmPmTranslation() { 347 boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; 348 mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX())); 349 } 350 351 private void updateBatteryLevelPaddingEnd() { 352 mBatteryLevel.setPaddingRelative(0, 0, 353 mKeyguardShowing && !mExpanded ? 0 : mBatteryPaddingEnd, 0); 354 } 355 356 @Override 357 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 358 mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level)); 359 boolean changed = mCharging != charging; 360 mCharging = charging; 361 if (changed) { 362 updateVisibilities(); 363 } 364 } 365 366 private void updateClickTargets() { 367 setClickable(!mKeyguardShowing || mExpanded); 368 mDateTime.setClickable(mExpanded); 369 mMultiUserSwitch.setClickable(mExpanded); 370 mSystemIconsSuperContainer.setClickable(mExpanded); 371 } 372 373 private void updateZTranslation() { 374 375 // If we are on the Keyguard, we need to set our z position to zero, so we don't get 376 // shadows. 377 if (mKeyguardShowing && !mExpanded) { 378 setZ(0); 379 } else { 380 setTranslationZ(0); 381 } 382 } 383 384 private void updatePadding() { 385 boolean padded = !mKeyguardShowing || mExpanded; 386 int padding = padded ? mPadding : 0; 387 setPaddingRelative(padding, 0, padding, 0); 388 } 389 390 private void updateClockLp() { 391 int marginBottom = mExpanded && !mOverscrolled ? mClockMarginBottomExpanded : 0; 392 LayoutParams lp = (LayoutParams) mDateTime.getLayoutParams(); 393 int rule = mExpanded && !mOverscrolled ? TRUE : 0; 394 if (marginBottom != lp.bottomMargin 395 || lp.getRules()[RelativeLayout.ALIGN_PARENT_BOTTOM] != rule) { 396 lp.bottomMargin = marginBottom; 397 lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rule); 398 mDateTime.setLayoutParams(lp); 399 } 400 } 401 402 private void updateMultiUserSwitch() { 403 int marginEnd; 404 if (mExpanded && !mOverscrolled) { 405 marginEnd = mMultiUserExpandedMargin; 406 } else if (mKeyguardShowing) { 407 marginEnd = mMultiUserKeyguardMargin; 408 } else { 409 marginEnd = mMultiUserCollapsedMargin; 410 } 411 int width = mExpanded && !mOverscrolled 412 ? mMultiUserSwitchWidthExpanded 413 : mMultiUserSwitchWidthCollapsed; 414 MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams(); 415 if (marginEnd != lp.getMarginEnd() || lp.width != width) { 416 lp.setMarginEnd(marginEnd); 417 lp.width = width; 418 mMultiUserSwitch.setLayoutParams(lp); 419 } 420 } 421 422 public void setExpansion(float t) { 423 float height = mCollapsedHeight + t * (mExpandedHeight - mCollapsedHeight); 424 if (height < mCollapsedHeight) { 425 height = mCollapsedHeight; 426 } 427 if (height > mExpandedHeight) { 428 height = mExpandedHeight; 429 } 430 setClipping(height); 431 } 432 433 private void setClipping(float height) { 434 mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height); 435 setClipBounds(mClipBounds); 436 invalidateOutline(); 437 } 438 439 public void attachSystemIcons(LinearLayout systemIcons) { 440 mSystemIconsContainer.addView(systemIcons); 441 mStatusIcons = systemIcons.findViewById(R.id.statusIcons); 442 mSignalCluster = systemIcons.findViewById(R.id.signal_cluster); 443 mSignalCluster.addOnLayoutChangeListener(mSignalClusterChanged); 444 } 445 446 public void onSystemIconsDetached() { 447 if (mStatusIcons != null) { 448 mStatusIcons.setVisibility(View.VISIBLE); 449 } 450 if (mSignalCluster != null) { 451 mSignalCluster.removeOnLayoutChangeListener(mSignalClusterChanged); 452 mSignalCluster.setVisibility(View.VISIBLE); 453 } 454 mStatusIcons = null; 455 mSignalCluster = null; 456 } 457 458 public void setKeyguardShowing(boolean keyguardShowing) { 459 mKeyguardShowing = keyguardShowing; 460 updateHeights(); 461 updateWidth(); 462 updateVisibilities(); 463 updateZTranslation(); 464 updatePadding(); 465 updateMultiUserSwitch(); 466 updateClickTargets(); 467 updateBatteryLevelPaddingEnd(); 468 } 469 470 public void setUserInfoController(UserInfoController userInfoController) { 471 userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { 472 @Override 473 public void onUserInfoChanged(String name, Drawable picture) { 474 mMultiUserAvatar.setImageDrawable(picture); 475 } 476 }); 477 } 478 479 @Override 480 public void onClick(View v) { 481 if (v == mSettingsButton) { 482 startSettingsActivity(); 483 } else if (v == mSystemIconsSuperContainer) { 484 startBatteryActivity(); 485 } 486 } 487 488 private void startSettingsActivity() { 489 mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS)); 490 } 491 492 private void startBatteryActivity() { 493 mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY)); 494 } 495 496 public void setQSPanel(QSPanel qsp) { 497 mQSPanel = qsp; 498 if (mQSPanel != null) { 499 mQSPanel.setCallback(mQsPanelCallback); 500 } 501 mMultiUserSwitch.setQsPanel(qsp); 502 } 503 504 @Override 505 public boolean shouldDelayChildPressedState() { 506 return true; 507 } 508 509 public void setShowEmergencyCallsOnly(boolean show) { 510 mShowEmergencyCallsOnly = show; 511 if (mExpanded) { 512 updateVisibilities(); 513 } 514 } 515 516 public void setKeyguardUserSwitcherShowing(boolean showing) { 517 // STOPSHIP: NOT CALLED PROPERLY WHEN GOING TO FULL SHADE AND RETURNING!?! 518 mKeyguardUserSwitcherShowing = showing; 519 updateVisibilities(); 520 updateSystemIconsLayoutParams(); 521 } 522 523 @Override 524 public boolean hasOverlappingRendering() { 525 return !mKeyguardShowing || mExpanded; 526 } 527 528 @Override 529 protected void dispatchSetPressed(boolean pressed) { 530 // We don't want that everything lights up when we click on the header, so block the request 531 // here. 532 } 533 534 private final OnLayoutChangeListener mSignalClusterChanged = new OnLayoutChangeListener() { 535 private final Rect mClipBounds = new Rect(); 536 537 @Override 538 public void onLayoutChange(View v, int left, int top, int right, 539 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 540 // Hide the statusIcons in the header by clipping them. Can't touch visibility since 541 // they are mirrored to the real status bar. 542 mClipBounds.set(left, 0, mSystemIconsContainer.getWidth(), 543 mSystemIconsContainer.getHeight()); 544 mSystemIconsContainer.setClipBounds(mClipBounds); 545 } 546 }; 547 548 private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() { 549 @Override 550 public void onToggleStateChanged(final boolean state) { 551 post(new Runnable() { 552 @Override 553 public void run() { 554 handleToggleStateChanged(state); 555 } 556 }); 557 } 558 559 @Override 560 public void onShowingDetail(final QSTile.DetailAdapter detail) { 561 post(new Runnable() { 562 @Override 563 public void run() { 564 handleShowingDetail(detail); 565 } 566 }); 567 } 568 569 @Override 570 public void onScanStateChanged(final boolean state) { 571 post(new Runnable() { 572 @Override 573 public void run() { 574 handleScanStateChanged(state); 575 } 576 }); 577 } 578 579 private void handleToggleStateChanged(boolean state) { 580 mQsDetailHeaderSwitch.setChecked(state); 581 } 582 583 private void handleScanStateChanged(boolean state) { 584 // TODO - waiting on framework asset 585 } 586 587 private void handleShowingDetail(final QSTile.DetailAdapter detail) { 588 final boolean showingDetail = detail != null; 589 transition(mDateTime, !showingDetail); 590 transition(mQsDetailHeader, showingDetail); 591 if (showingDetail) { 592 mQsDetailHeaderTitle.setText(detail.getTitle()); 593 final Boolean toggleState = detail.getToggleState(); 594 if (toggleState == null) { 595 mQsDetailHeaderSwitch.setVisibility(INVISIBLE); 596 mQsDetailHeader.setClickable(false); 597 } else { 598 mQsDetailHeaderSwitch.setVisibility(VISIBLE); 599 mQsDetailHeaderSwitch.setChecked(toggleState); 600 mQsDetailHeader.setClickable(true); 601 mQsDetailHeader.setOnClickListener(new OnClickListener() { 602 @Override 603 public void onClick(View v) { 604 detail.setToggleState(!mQsDetailHeaderSwitch.isChecked()); 605 } 606 }); 607 } 608 } else { 609 mQsDetailHeader.setClickable(false); 610 } 611 } 612 613 private void transition(final View v, final boolean in) { 614 if (in) { 615 v.bringToFront(); 616 } 617 v.animate().alpha(in ? 1 : 0).withLayer().start(); 618 } 619 }; 620} 621