1/* This file is auto-generated from PlaybackOverlayFragment.java. DO NOT MODIFY. */ 2 3/* 4 * Copyright (C) 2014 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 7 * in compliance with the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software distributed under the License 12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 13 * or implied. See the License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.support.v17.leanback.app; 17 18import android.graphics.Color; 19import android.graphics.drawable.ColorDrawable; 20import android.animation.Animator; 21import android.animation.AnimatorInflater; 22import android.animation.TimeInterpolator; 23import android.animation.ValueAnimator; 24import android.view.InputEvent; 25import android.view.animation.AccelerateInterpolator; 26import android.animation.ValueAnimator.AnimatorUpdateListener; 27import android.content.Context; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.Message; 31import android.support.v7.widget.RecyclerView; 32import android.support.v17.leanback.R; 33import android.support.v17.leanback.animation.LogAccelerateInterpolator; 34import android.support.v17.leanback.animation.LogDecelerateInterpolator; 35import android.support.v17.leanback.widget.Presenter; 36import android.support.v17.leanback.widget.ItemBridgeAdapter; 37import android.support.v17.leanback.widget.ObjectAdapter; 38import android.support.v17.leanback.widget.ObjectAdapter.DataObserver; 39import android.support.v17.leanback.widget.VerticalGridView; 40import android.support.v17.leanback.widget.PlaybackControlsRowPresenter; 41import android.util.Log; 42import android.view.KeyEvent; 43import android.view.LayoutInflater; 44import android.view.MotionEvent; 45import android.view.View; 46import android.view.ViewGroup; 47 48import java.util.ArrayList; 49 50/** 51 * A fragment for displaying playback controls and related content. 52 * The {@link android.support.v17.leanback.widget.PlaybackControlsRow} is expected to be 53 * at position 0 in the adapter. 54 */ 55public class PlaybackOverlaySupportFragment extends DetailsSupportFragment { 56 57 /** 58 * No background. 59 */ 60 public static final int BG_NONE = 0; 61 62 /** 63 * A dark translucent background. 64 */ 65 public static final int BG_DARK = 1; 66 67 /** 68 * A light translucent background. 69 */ 70 public static final int BG_LIGHT = 2; 71 72 public static class OnFadeCompleteListener { 73 public void onFadeInComplete() { 74 } 75 public void onFadeOutComplete() { 76 } 77 } 78 79 public interface InputEventHandler { 80 /** 81 * Called when an {@link InputEvent} is received. 82 * 83 * @return If the event should be consumed, return true. To allow the event to 84 * continue on to the next handler, return false. 85 */ 86 public boolean handleInputEvent(InputEvent event); 87 } 88 89 private static final String TAG = "PlaybackOverlaySupportFragment"; 90 private static final boolean DEBUG = false; 91 private static final int ANIMATION_MULTIPLIER = 1; 92 93 private static int START_FADE_OUT = 1; 94 95 // Fading status 96 private static final int IDLE = 0; 97 private static final int IN = 1; 98 private static final int OUT = 2; 99 100 private int mAlignPosition; 101 private int mPaddingBottom; 102 private View mRootView; 103 private int mBackgroundType = BG_DARK; 104 private int mBgDarkColor; 105 private int mBgLightColor; 106 private int mShowTimeMs; 107 private int mMajorFadeTranslateY, mMinorFadeTranslateY; 108 private int mAnimationTranslateY; 109 private OnFadeCompleteListener mFadeCompleteListener; 110 private InputEventHandler mInputEventHandler; 111 private boolean mFadingEnabled = true; 112 private int mFadingStatus = IDLE; 113 private int mBgAlpha; 114 private ValueAnimator mBgFadeInAnimator, mBgFadeOutAnimator; 115 private ValueAnimator mControlRowFadeInAnimator, mControlRowFadeOutAnimator; 116 private ValueAnimator mDescriptionFadeInAnimator, mDescriptionFadeOutAnimator; 117 private ValueAnimator mOtherRowFadeInAnimator, mOtherRowFadeOutAnimator; 118 private boolean mTranslateAnimationEnabled; 119 private boolean mResetControlsToPrimaryActionsPending; 120 private RecyclerView.ItemAnimator mItemAnimator; 121 122 private final Animator.AnimatorListener mFadeListener = 123 new Animator.AnimatorListener() { 124 @Override 125 public void onAnimationStart(Animator animation) { 126 enableVerticalGridAnimations(false); 127 } 128 @Override 129 public void onAnimationRepeat(Animator animation) { 130 } 131 @Override 132 public void onAnimationCancel(Animator animation) { 133 } 134 @Override 135 public void onAnimationEnd(Animator animation) { 136 if (DEBUG) Log.v(TAG, "onAnimationEnd " + mBgAlpha); 137 if (mBgAlpha > 0) { 138 enableVerticalGridAnimations(true); 139 startFadeTimer(); 140 if (mFadeCompleteListener != null) { 141 mFadeCompleteListener.onFadeInComplete(); 142 } 143 } else { 144 if (getVerticalGridView() != null) { 145 // Reset focus to the controls row 146 getVerticalGridView().setSelectedPosition(0); 147 resetControlsToPrimaryActions(null); 148 } 149 if (mFadeCompleteListener != null) { 150 mFadeCompleteListener.onFadeOutComplete(); 151 } 152 } 153 mFadingStatus = IDLE; 154 } 155 }; 156 157 private final Handler mHandler = new Handler() { 158 @Override 159 public void handleMessage(Message message) { 160 if (message.what == START_FADE_OUT && mFadingEnabled) { 161 fade(false); 162 } 163 } 164 }; 165 166 private final VerticalGridView.OnTouchInterceptListener mOnTouchInterceptListener = 167 new VerticalGridView.OnTouchInterceptListener() { 168 public boolean onInterceptTouchEvent(MotionEvent event) { 169 return onInterceptInputEvent(event); 170 } 171 }; 172 173 private final VerticalGridView.OnKeyInterceptListener mOnKeyInterceptListener = 174 new VerticalGridView.OnKeyInterceptListener() { 175 public boolean onInterceptKeyEvent(KeyEvent event) { 176 return onInterceptInputEvent(event); 177 } 178 }; 179 180 private void setBgAlpha(int alpha) { 181 mBgAlpha = alpha; 182 if (mRootView != null) { 183 mRootView.getBackground().setAlpha(alpha); 184 } 185 } 186 187 private void enableVerticalGridAnimations(boolean enable) { 188 if (getVerticalGridView() != null) { 189 getVerticalGridView().setAnimateChildLayout(enable); 190 } 191 } 192 193 private void resetControlsToPrimaryActions(ItemBridgeAdapter.ViewHolder vh) { 194 if (vh == null && getVerticalGridView() != null) { 195 vh = (ItemBridgeAdapter.ViewHolder) getVerticalGridView().findViewHolderForPosition(0); 196 } 197 if (vh == null) { 198 mResetControlsToPrimaryActionsPending = true; 199 } else if (vh.getPresenter() instanceof PlaybackControlsRowPresenter) { 200 mResetControlsToPrimaryActionsPending = false; 201 ((PlaybackControlsRowPresenter) vh.getPresenter()).showPrimaryActions( 202 (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder()); 203 } 204 } 205 206 /** 207 * Enables or disables view fading. If enabled, 208 * the view will be faded in when the fragment starts, 209 * and will fade out after a time period. The timeout 210 * period is reset each time {@link #tickle} is called. 211 * 212 */ 213 public void setFadingEnabled(boolean enabled) { 214 if (DEBUG) Log.v(TAG, "setFadingEnabled " + enabled); 215 if (enabled != mFadingEnabled) { 216 mFadingEnabled = enabled; 217 if (mFadingEnabled) { 218 if (isResumed() && mFadingStatus == IDLE 219 && !mHandler.hasMessages(START_FADE_OUT)) { 220 startFadeTimer(); 221 } 222 } else { 223 // Ensure fully opaque 224 mHandler.removeMessages(START_FADE_OUT); 225 fade(true); 226 } 227 } 228 } 229 230 /** 231 * Returns true if view fading is enabled. 232 */ 233 public boolean isFadingEnabled() { 234 return mFadingEnabled; 235 } 236 237 /** 238 * Sets the listener to be called when fade in or out has completed. 239 */ 240 public void setFadeCompleteListener(OnFadeCompleteListener listener) { 241 mFadeCompleteListener = listener; 242 } 243 244 /** 245 * Returns the listener to be called when fade in or out has completed. 246 */ 247 public OnFadeCompleteListener getFadeCompleteListener() { 248 return mFadeCompleteListener; 249 } 250 251 /** 252 * Sets the input event handler. 253 */ 254 public final void setInputEventHandler(InputEventHandler handler) { 255 mInputEventHandler = handler; 256 } 257 258 /** 259 * Returns the input event handler. 260 */ 261 public final InputEventHandler getInputEventHandler() { 262 return mInputEventHandler; 263 } 264 265 /** 266 * Tickles the playback controls. Fades in the view if it was faded out, 267 * otherwise resets the fade out timer. Tickling on input events is handled 268 * by the fragment. 269 */ 270 public void tickle() { 271 if (DEBUG) Log.v(TAG, "tickle enabled " + mFadingEnabled + " isResumed " + isResumed()); 272 if (!mFadingEnabled || !isResumed()) { 273 return; 274 } 275 if (mHandler.hasMessages(START_FADE_OUT)) { 276 // Restart the timer 277 startFadeTimer(); 278 } else { 279 fade(true); 280 } 281 } 282 283 private static boolean isConsumableKey(KeyEvent keyEvent) { 284 if (keyEvent.isSystem()) { 285 return false; 286 } 287 return true; 288 } 289 290 private boolean onInterceptInputEvent(InputEvent event) { 291 if (DEBUG) Log.v(TAG, "onInterceptInputEvent status " + mFadingStatus + 292 " mBgAlpha " + mBgAlpha + " event " + event); 293 final boolean controlsHidden = (mFadingStatus == IDLE && mBgAlpha == 0); 294 boolean consumeEvent = controlsHidden; 295 int keyCode = KeyEvent.KEYCODE_UNKNOWN; 296 297 if (event instanceof KeyEvent) { 298 if (consumeEvent) { 299 consumeEvent = isConsumableKey((KeyEvent) event); 300 } 301 keyCode = ((KeyEvent) event).getKeyCode(); 302 } 303 if (!consumeEvent && mInputEventHandler != null) { 304 consumeEvent = mInputEventHandler.handleInputEvent(event); 305 } 306 if (keyCode == KeyEvent.KEYCODE_BACK) { 307 // If fading enabled and controls are not hidden, back will be consumed to fade 308 // them out (even if the key was consumed by the handler). 309 if (mFadingEnabled && !controlsHidden) { 310 consumeEvent = true; 311 mHandler.removeMessages(START_FADE_OUT); 312 fade(false); 313 } else if (consumeEvent) { 314 tickle(); 315 } 316 } else { 317 // Any other key will show the controls 318 tickle(); 319 } 320 return consumeEvent; 321 } 322 323 @Override 324 public void onResume() { 325 super.onResume(); 326 if (mFadingEnabled) { 327 setBgAlpha(0); 328 fade(true); 329 } 330 getVerticalGridView().setOnTouchInterceptListener(mOnTouchInterceptListener); 331 getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener); 332 } 333 334 private void startFadeTimer() { 335 if (mHandler != null) { 336 mHandler.removeMessages(START_FADE_OUT); 337 mHandler.sendEmptyMessageDelayed(START_FADE_OUT, mShowTimeMs); 338 } 339 } 340 341 private static ValueAnimator loadAnimator(Context context, int resId) { 342 ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(context, resId); 343 animator.setDuration(animator.getDuration() * ANIMATION_MULTIPLIER); 344 return animator; 345 } 346 347 private void loadBgAnimator() { 348 AnimatorUpdateListener listener = new AnimatorUpdateListener() { 349 @Override 350 public void onAnimationUpdate(ValueAnimator arg0) { 351 setBgAlpha((Integer) arg0.getAnimatedValue()); 352 } 353 }; 354 355 mBgFadeInAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_in); 356 mBgFadeInAnimator.addUpdateListener(listener); 357 mBgFadeInAnimator.addListener(mFadeListener); 358 359 mBgFadeOutAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_out); 360 mBgFadeOutAnimator.addUpdateListener(listener); 361 mBgFadeOutAnimator.addListener(mFadeListener); 362 } 363 364 private TimeInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100,0); 365 private TimeInterpolator mLogAccelerateInterpolator = new LogAccelerateInterpolator(100,0); 366 367 private View getControlRowView() { 368 if (getVerticalGridView() == null) { 369 return null; 370 } 371 RecyclerView.ViewHolder vh = getVerticalGridView().findViewHolderForPosition(0); 372 if (vh == null) { 373 return null; 374 } 375 return vh.itemView; 376 } 377 378 private void loadControlRowAnimator() { 379 final AnimatorListener listener = new AnimatorListener() { 380 @Override 381 void getViews(ArrayList<View> views) { 382 View view = getControlRowView(); 383 if (view != null) { 384 views.add(view); 385 } 386 } 387 }; 388 final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { 389 @Override 390 public void onAnimationUpdate(ValueAnimator arg0) { 391 View view = getControlRowView(); 392 if (view != null) { 393 final float fraction = (Float) arg0.getAnimatedValue(); 394 if (DEBUG) Log.v(TAG, "fraction " + fraction); 395 view.setAlpha(fraction); 396 view.setTranslationY((float) mAnimationTranslateY * (1f - fraction)); 397 } 398 } 399 }; 400 401 mControlRowFadeInAnimator = loadAnimator( 402 getActivity(), R.animator.lb_playback_controls_fade_in); 403 mControlRowFadeInAnimator.addUpdateListener(updateListener); 404 mControlRowFadeInAnimator.addListener(listener); 405 mControlRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator); 406 407 mControlRowFadeOutAnimator = loadAnimator( 408 getActivity(), R.animator.lb_playback_controls_fade_out); 409 mControlRowFadeOutAnimator.addUpdateListener(updateListener); 410 mControlRowFadeOutAnimator.addListener(listener); 411 mControlRowFadeOutAnimator.setInterpolator(mLogAccelerateInterpolator); 412 } 413 414 private void loadOtherRowAnimator() { 415 final AnimatorListener listener = new AnimatorListener() { 416 @Override 417 void getViews(ArrayList<View> views) { 418 if (getVerticalGridView() == null) { 419 return; 420 } 421 final int count = getVerticalGridView().getChildCount(); 422 for (int i = 0; i < count; i++) { 423 View view = getVerticalGridView().getChildAt(i); 424 if (view != null) { 425 views.add(view); 426 } 427 } 428 } 429 }; 430 final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() { 431 @Override 432 public void onAnimationUpdate(ValueAnimator arg0) { 433 if (getVerticalGridView() == null) { 434 return; 435 } 436 final float fraction = (Float) arg0.getAnimatedValue(); 437 for (View view : listener.mViews) { 438 if (getVerticalGridView().getChildPosition(view) > 0) { 439 view.setAlpha(fraction); 440 view.setTranslationY((float) mAnimationTranslateY * (1f - fraction)); 441 } 442 } 443 } 444 }; 445 446 mOtherRowFadeInAnimator = loadAnimator( 447 getActivity(), R.animator.lb_playback_controls_fade_in); 448 mOtherRowFadeInAnimator.addListener(listener); 449 mOtherRowFadeInAnimator.addUpdateListener(updateListener); 450 mOtherRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator); 451 452 mOtherRowFadeOutAnimator = loadAnimator( 453 getActivity(), R.animator.lb_playback_controls_fade_out); 454 mOtherRowFadeOutAnimator.addListener(listener); 455 mOtherRowFadeOutAnimator.addUpdateListener(updateListener); 456 mOtherRowFadeOutAnimator.setInterpolator(new AccelerateInterpolator()); 457 } 458 459 private void loadDescriptionAnimator() { 460 AnimatorUpdateListener listener = new AnimatorUpdateListener() { 461 @Override 462 public void onAnimationUpdate(ValueAnimator arg0) { 463 if (getVerticalGridView() == null) { 464 return; 465 } 466 ItemBridgeAdapter.ViewHolder adapterVh = (ItemBridgeAdapter.ViewHolder) 467 getVerticalGridView().findViewHolderForPosition(0); 468 if (adapterVh != null && adapterVh.getViewHolder() 469 instanceof PlaybackControlsRowPresenter.ViewHolder) { 470 final Presenter.ViewHolder vh = ((PlaybackControlsRowPresenter.ViewHolder) 471 adapterVh.getViewHolder()).mDescriptionViewHolder; 472 if (vh != null) { 473 vh.view.setAlpha((Float) arg0.getAnimatedValue()); 474 } 475 } 476 } 477 }; 478 479 mDescriptionFadeInAnimator = loadAnimator( 480 getActivity(), R.animator.lb_playback_description_fade_in); 481 mDescriptionFadeInAnimator.addUpdateListener(listener); 482 mDescriptionFadeInAnimator.setInterpolator(mLogDecelerateInterpolator); 483 484 mDescriptionFadeOutAnimator = loadAnimator( 485 getActivity(), R.animator.lb_playback_description_fade_out); 486 mDescriptionFadeOutAnimator.addUpdateListener(listener); 487 } 488 489 private void fade(boolean fadeIn) { 490 if (DEBUG) Log.v(TAG, "fade " + fadeIn); 491 if (getView() == null) { 492 return; 493 } 494 if ((fadeIn && mFadingStatus == IN) || (!fadeIn && mFadingStatus == OUT)) { 495 if (DEBUG) Log.v(TAG, "requested fade in progress"); 496 return; 497 } 498 if ((fadeIn && mBgAlpha == 255) || (!fadeIn && mBgAlpha == 0)) { 499 if (DEBUG) Log.v(TAG, "fade is no-op"); 500 return; 501 } 502 503 mAnimationTranslateY = getVerticalGridView().getSelectedPosition() == 0 ? 504 mMajorFadeTranslateY : mMinorFadeTranslateY; 505 506 if (mFadingStatus == IDLE) { 507 if (fadeIn) { 508 mBgFadeInAnimator.start(); 509 mControlRowFadeInAnimator.start(); 510 mOtherRowFadeInAnimator.start(); 511 mDescriptionFadeInAnimator.start(); 512 } else { 513 mBgFadeOutAnimator.start(); 514 mControlRowFadeOutAnimator.start(); 515 mOtherRowFadeOutAnimator.start(); 516 mDescriptionFadeOutAnimator.start(); 517 } 518 } else { 519 if (fadeIn) { 520 mBgFadeOutAnimator.reverse(); 521 mControlRowFadeOutAnimator.reverse(); 522 mOtherRowFadeOutAnimator.reverse(); 523 mDescriptionFadeOutAnimator.reverse(); 524 } else { 525 mBgFadeInAnimator.reverse(); 526 mControlRowFadeInAnimator.reverse(); 527 mOtherRowFadeInAnimator.reverse(); 528 mDescriptionFadeInAnimator.reverse(); 529 } 530 } 531 532 // If fading in while control row is focused, set initial translationY so 533 // views slide in from below. 534 if (fadeIn && mFadingStatus == IDLE) { 535 final int count = getVerticalGridView().getChildCount(); 536 for (int i = 0; i < count; i++) { 537 getVerticalGridView().getChildAt(i).setTranslationY(mAnimationTranslateY); 538 } 539 } 540 541 mFadingStatus = fadeIn ? IN : OUT; 542 } 543 544 /** 545 * Sets the list of rows for the fragment. 546 */ 547 @Override 548 public void setAdapter(ObjectAdapter adapter) { 549 if (getAdapter() != null) { 550 getAdapter().unregisterObserver(mObserver); 551 } 552 super.setAdapter(adapter); 553 if (adapter != null) { 554 adapter.registerObserver(mObserver); 555 } 556 } 557 558 @Override 559 void setVerticalGridViewLayout(VerticalGridView listview) { 560 if (listview == null) { 561 return; 562 } 563 // Padding affects alignment when last row is focused 564 // (last is first when there's only one row). 565 setBottomPadding(listview, mPaddingBottom); 566 567 // Item alignment affects focused row that isn't the last. 568 listview.setItemAlignmentOffset(mAlignPosition); 569 listview.setItemAlignmentOffsetPercent(100); 570 571 // Push rows to the bottom. 572 listview.setWindowAlignmentOffset(0); 573 listview.setWindowAlignmentOffsetPercent(100); 574 listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE); 575 } 576 577 private static void setBottomPadding(View view, int padding) { 578 view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), 579 view.getPaddingRight(), padding); 580 } 581 582 @Override 583 public void onCreate(Bundle savedInstanceState) { 584 super.onCreate(savedInstanceState); 585 586 mAlignPosition = 587 getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_align_bottom); 588 mPaddingBottom = 589 getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_bottom); 590 mBgDarkColor = 591 getResources().getColor(R.color.lb_playback_controls_background_dark); 592 mBgLightColor = 593 getResources().getColor(R.color.lb_playback_controls_background_light); 594 mShowTimeMs = 595 getResources().getInteger(R.integer.lb_playback_controls_show_time_ms); 596 mMajorFadeTranslateY = 597 getResources().getDimensionPixelSize(R.dimen.lb_playback_major_fade_translate_y); 598 mMinorFadeTranslateY = 599 getResources().getDimensionPixelSize(R.dimen.lb_playback_minor_fade_translate_y); 600 601 loadBgAnimator(); 602 loadControlRowAnimator(); 603 loadOtherRowAnimator(); 604 loadDescriptionAnimator(); 605 } 606 607 /** 608 * Sets the background type. 609 * 610 * @param type One of BG_LIGHT, BG_DARK, or BG_NONE. 611 */ 612 public void setBackgroundType(int type) { 613 switch (type) { 614 case BG_LIGHT: 615 case BG_DARK: 616 case BG_NONE: 617 if (type != mBackgroundType) { 618 mBackgroundType = type; 619 updateBackground(); 620 } 621 break; 622 default: 623 throw new IllegalArgumentException("Invalid background type"); 624 } 625 } 626 627 /** 628 * Returns the background type. 629 */ 630 public int getBackgroundType() { 631 return mBackgroundType; 632 } 633 634 private void updateBackground() { 635 if (mRootView != null) { 636 int color = mBgDarkColor; 637 switch (mBackgroundType) { 638 case BG_DARK: break; 639 case BG_LIGHT: color = mBgLightColor; break; 640 case BG_NONE: color = Color.TRANSPARENT; break; 641 } 642 mRootView.setBackground(new ColorDrawable(color)); 643 } 644 } 645 646 private void updateControlsBottomSpace(ItemBridgeAdapter.ViewHolder vh) { 647 // Add extra space between rows 0 and 1 648 if (vh == null && getVerticalGridView() != null) { 649 vh = (ItemBridgeAdapter.ViewHolder) 650 getVerticalGridView().findViewHolderForPosition(0); 651 } 652 if (vh != null && vh.getPresenter() instanceof PlaybackControlsRowPresenter) { 653 final int adapterSize = getAdapter() == null ? 0 : getAdapter().size(); 654 ((PlaybackControlsRowPresenter) vh.getPresenter()).showBottomSpace( 655 (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder(), 656 adapterSize > 1); 657 } 658 } 659 660 private final ItemBridgeAdapter.AdapterListener mAdapterListener = 661 new ItemBridgeAdapter.AdapterListener() { 662 @Override 663 public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) { 664 if (DEBUG) Log.v(TAG, "onAttachedToWindow " + vh.getViewHolder().view); 665 if ((mFadingStatus == IDLE && mBgAlpha == 0) || mFadingStatus == OUT) { 666 if (DEBUG) Log.v(TAG, "setting alpha to 0"); 667 vh.getViewHolder().view.setAlpha(0); 668 } 669 if (vh.getPosition() == 0 && mResetControlsToPrimaryActionsPending) { 670 resetControlsToPrimaryActions(vh); 671 } 672 } 673 @Override 674 public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) { 675 if (DEBUG) Log.v(TAG, "onDetachedFromWindow " + vh.getViewHolder().view); 676 // Reset animation state 677 vh.getViewHolder().view.setAlpha(1f); 678 vh.getViewHolder().view.setTranslationY(0); 679 if (vh.getViewHolder() instanceof PlaybackControlsRowPresenter.ViewHolder) { 680 Presenter.ViewHolder descriptionVh = ((PlaybackControlsRowPresenter.ViewHolder) 681 vh.getViewHolder()).mDescriptionViewHolder; 682 if (descriptionVh != null) { 683 descriptionVh.view.setAlpha(1f); 684 } 685 } 686 } 687 @Override 688 public void onBind(ItemBridgeAdapter.ViewHolder vh) { 689 if (vh.getPosition() == 0) { 690 updateControlsBottomSpace(vh); 691 } 692 } 693 }; 694 695 @Override 696 public View onCreateView(LayoutInflater inflater, ViewGroup container, 697 Bundle savedInstanceState) { 698 mRootView = super.onCreateView(inflater, container, savedInstanceState); 699 mBgAlpha = 255; 700 updateBackground(); 701 getRowsSupportFragment().setExternalAdapterListener(mAdapterListener); 702 return mRootView; 703 } 704 705 @Override 706 public void onDestroyView() { 707 mRootView = null; 708 super.onDestroyView(); 709 } 710 711 private final DataObserver mObserver = new DataObserver() { 712 public void onChanged() { 713 updateControlsBottomSpace(null); 714 } 715 }; 716 717 static abstract class AnimatorListener implements Animator.AnimatorListener { 718 ArrayList<View> mViews = new ArrayList<View>(); 719 ArrayList<Integer> mLayerType = new ArrayList<Integer>(); 720 721 public void onAnimationCancel(Animator animation) { 722 } 723 public void onAnimationRepeat(Animator animation) { 724 } 725 public void onAnimationStart(Animator animation) { 726 getViews(mViews); 727 for (View view : mViews) { 728 mLayerType.add(view.getLayerType()); 729 view.setLayerType(View.LAYER_TYPE_HARDWARE, null); 730 } 731 } 732 public void onAnimationEnd(Animator animation) { 733 for (int i = 0; i < mViews.size(); i++) { 734 mViews.get(i).setLayerType(mLayerType.get(i), null); 735 } 736 mLayerType.clear(); 737 mViews.clear(); 738 } 739 abstract void getViews(ArrayList<View> views); 740 }; 741} 742