PlaybackOverlayFragment.java revision cbfc318baee2fc054af4c723bfac0fd3c28a1667
17ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/*
27ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Copyright (C) 2014 The Android Open Source Project
37ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
47ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
57ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * in compliance with the License. You may obtain a copy of the License at
67ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
77ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * http://www.apache.org/licenses/LICENSE-2.0
87ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout *
97ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License
107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * or implied. See the License for the specific language governing permissions and limitations under
127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * the License.
137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpackage android.support.v17.leanback.app;
157ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
167709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.graphics.Color;
177709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.graphics.drawable.ColorDrawable;
18372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.animation.Animator;
19d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.AnimatorInflater;
20d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.TimeInterpolator;
21d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.ValueAnimator;
22cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stoutimport android.view.InputEvent;
236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.view.animation.AccelerateInterpolator;
24d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.ValueAnimator.AnimatorUpdateListener;
25d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.content.Context;
267ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.os.Bundle;
27372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Handler;
28372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Message;
29d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v7.widget.RecyclerView;
307ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.R;
31d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogAccelerateInterpolator;
32d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogDecelerateInterpolator;
336b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.support.v17.leanback.widget.Presenter;
34d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.widget.ItemBridgeAdapter;
357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.widget.ObjectAdapter;
366dca725412977bb56b933bdec120e31909233cdbCraig Stoutimport android.support.v17.leanback.widget.ObjectAdapter.DataObserver;
377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.widget.VerticalGridView;
386b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
39372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.util.Log;
40372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.KeyEvent;
417709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.LayoutInflater;
42372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.MotionEvent;
437709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.View;
447709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.ViewGroup;
457ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
462d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stoutimport java.util.ArrayList;
477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/**
497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * A fragment for displaying playback controls and related content.
506dca725412977bb56b933bdec120e31909233cdbCraig Stout * The {@link android.support.v17.leanback.widget.PlaybackControlsRow} is expected to be
516dca725412977bb56b933bdec120e31909233cdbCraig Stout * at position 0 in the adapter.
527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
537ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpublic class PlaybackOverlayFragment extends DetailsFragment {
547ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
557709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
567709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * No background.
577709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
587709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_NONE = 0;
597709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
607709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
617709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A dark translucent background.
627709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
637709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_DARK = 1;
647709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
657709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
667709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A light translucent background.
677709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
687709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_LIGHT = 2;
697709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
70372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public static class OnFadeCompleteListener {
71372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeInComplete() {
72372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
73372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeOutComplete() {
74372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
75372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
76372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
77372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final String TAG = "PlaybackOverlayFragment";
78372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final boolean DEBUG = false;
79d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static final int ANIMATION_MULTIPLIER = 1;
80372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
81372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static int START_FADE_OUT = 1;
82372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
83372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    // Fading status
84372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int IDLE = 0;
85372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int IN = 1;
86372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int OUT = 2;
87372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
887ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private int mAlignPosition;
89d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private int mPaddingBottom;
907709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private View mRootView;
917709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBackgroundType = BG_DARK;
927709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgDarkColor;
937709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgLightColor;
94372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private int mShowTimeMs;
956b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private int mMajorFadeTranslateY, mMinorFadeTranslateY;
966b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private int mAnimationTranslateY;
97372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private OnFadeCompleteListener mFadeCompleteListener;
98372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private boolean mFadingEnabled = true;
99372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private int mFadingStatus = IDLE;
100d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private int mBgAlpha;
101d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mBgFadeInAnimator, mBgFadeOutAnimator;
102d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mControlRowFadeInAnimator, mControlRowFadeOutAnimator;
1036b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private ValueAnimator mDescriptionFadeInAnimator, mDescriptionFadeOutAnimator;
104d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mOtherRowFadeInAnimator, mOtherRowFadeOutAnimator;
105d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private boolean mTranslateAnimationEnabled;
106aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    private boolean mResetControlsToPrimaryActionsPending;
107d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private RecyclerView.ItemAnimator mItemAnimator;
108372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
109372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final Animator.AnimatorListener mFadeListener =
110372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new Animator.AnimatorListener() {
111372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
112372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationStart(Animator animation) {
113d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            enableVerticalGridAnimations(false);
114372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
115372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
116372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationRepeat(Animator animation) {
117372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
118372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
119372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationCancel(Animator animation) {
120372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
121372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
122372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationEnd(Animator animation) {
123d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAnimationEnd " + mBgAlpha);
124d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (mBgAlpha > 0) {
125d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                enableVerticalGridAnimations(true);
126372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                startFadeTimer();
127372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                if (mFadeCompleteListener != null) {
128372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    mFadeCompleteListener.onFadeInComplete();
129372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
130d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
1311e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                if (getVerticalGridView() != null) {
1321e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    // Reset focus to the controls row
1331e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    getVerticalGridView().setSelectedPosition(0);
134aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    resetControlsToPrimaryActions(null);
1351e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
136d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (mFadeCompleteListener != null) {
137d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    mFadeCompleteListener.onFadeOutComplete();
138d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
139372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
140372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingStatus = IDLE;
141372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
142372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
143372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
144372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final Handler mHandler = new Handler() {
145372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
146372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void handleMessage(Message message) {
147372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (message.what == START_FADE_OUT && mFadingEnabled) {
148372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                fade(false);
149372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
150372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
151372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
152372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
153372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnTouchInterceptListener mOnTouchInterceptListener =
154372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnTouchInterceptListener() {
155372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptTouchEvent(MotionEvent event) {
156cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
157372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
158372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
159372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
160372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnMotionInterceptListener mOnMotionInterceptListener =
161372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnMotionInterceptListener() {
162372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptMotionEvent(MotionEvent event) {
163cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
164372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
165372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
166372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
167372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnKeyInterceptListener mOnKeyInterceptListener =
168372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnKeyInterceptListener() {
169372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptKeyEvent(KeyEvent event) {
170cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
171372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
172372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
173372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
174d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void setBgAlpha(int alpha) {
175d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = alpha;
1761e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        if (mRootView != null) {
1771e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mRootView.getBackground().setAlpha(alpha);
1781e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
179d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
180d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
181d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void enableVerticalGridAnimations(boolean enable) {
182aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (getVerticalGridView() != null) {
183aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            getVerticalGridView().setAnimateChildLayout(enable);
184aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        }
185aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    }
186aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout
187aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    private void resetControlsToPrimaryActions(ItemBridgeAdapter.ViewHolder vh) {
188aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null && getVerticalGridView() != null) {
189aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            vh = (ItemBridgeAdapter.ViewHolder) getVerticalGridView().findViewHolderForPosition(0);
1901e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
191aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null) {
192aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = true;
193aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        } else if (vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
194aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = false;
195aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showPrimaryActions(
196aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder());
197d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
198d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
199d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
200372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
201372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Enables or disables view fading.  If enabled,
202372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * the view will be faded in when the fragment starts,
203372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * and will fade out after a time period.  The timeout
204372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * period is reset each time {@link #tickle} is called.
205372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     *
206372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
207372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadingEnabled(boolean enabled) {
208372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "setFadingEnabled " + enabled);
209372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (enabled != mFadingEnabled) {
210372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingEnabled = enabled;
211372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (isResumed()) {
212372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                if (mFadingEnabled) {
213372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    if (mFadingStatus == IDLE && !mHandler.hasMessages(START_FADE_OUT)) {
214372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                        startFadeTimer();
215372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    }
216372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                } else {
217372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    // Ensure fully opaque
218372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    mHandler.removeMessages(START_FADE_OUT);
219372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    fade(true);
220372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
221372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
222372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
223372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
224372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
225372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
226372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns true if view fading is enabled.
227372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
228372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public boolean isFadingEnabled() {
229372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadingEnabled;
230372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
231372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
232372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
233372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Sets the listener to be called when fade in or out has completed.
234372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
235372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadeCompleteListener(OnFadeCompleteListener listener) {
236372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadeCompleteListener = listener;
237372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
238372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
239372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
240372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns the listener to be called when fade in or out has completed.
241372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
242372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public OnFadeCompleteListener getFadeCompleteListener() {
243372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadeCompleteListener;
244372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
245372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
246372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
247372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Tickles the playback controls.  Fades in the view if it was faded out,
248372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * otherwise resets the fade out timer.  Tickling on input events is handled
249372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * by the fragment.
250372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
251372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void tickle() {
252372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "tickle enabled " + mFadingEnabled + " isResumed " + isResumed());
253372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (!mFadingEnabled || !isResumed()) {
254372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
255372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
256372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (mHandler.hasMessages(START_FADE_OUT)) {
257372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            // Restart the timer
258372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            startFadeTimer();
259372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        } else {
260372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
261372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
262372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
263372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
264cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    private static boolean isConsumableKey(KeyEvent keyEvent) {
265cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (keyEvent.isSystem()) {
266cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return false;
267cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        }
268cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        return true;
269cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    }
270cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout
271cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    private boolean onInterceptInputEvent(InputEvent event) {
272cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (DEBUG) Log.v(TAG, "onInterceptInputEvent status " + mFadingStatus + " event " + event);
273d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        boolean consumeEvent = (mFadingStatus == IDLE && mBgAlpha == 0);
274cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (event instanceof KeyEvent) {
275cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            if (consumeEvent) {
276cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout                consumeEvent = isConsumableKey((KeyEvent) event);
277cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            }
278cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            int keyCode = ((KeyEvent) event).getKeyCode();
279cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            // Back key typically means we're leaving the fragment
280cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            if (keyCode != KeyEvent.KEYCODE_BACK) {
281cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout                tickle();
282cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            }
283cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        } else {
284cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            tickle();
285cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        }
286372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return consumeEvent;
287372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
288372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
289372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    @Override
290372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void onResume() {
291372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        super.onResume();
292372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (mFadingEnabled) {
293d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            setBgAlpha(0);
294372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
295372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
296372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnTouchInterceptListener(mOnTouchInterceptListener);
297372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnMotionInterceptListener(mOnMotionInterceptListener);
298372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener);
299372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
300372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
301372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private void startFadeTimer() {
3021e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        if (mHandler != null) {
3031e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mHandler.removeMessages(START_FADE_OUT);
3041e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mHandler.sendEmptyMessageDelayed(START_FADE_OUT, mShowTimeMs);
3051e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
306372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
307372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
308d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static ValueAnimator loadAnimator(Context context, int resId) {
309d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(context, resId);
310d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        animator.setDuration(animator.getDuration() * ANIMATION_MULTIPLIER);
311d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        return animator;
312d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
313d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
314d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadBgAnimator() {
315d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
316d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
317d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
318d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                setBgAlpha((Integer) arg0.getAnimatedValue());
319d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
320d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
321d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
322d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_in);
323d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addUpdateListener(listener);
324d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addListener(mFadeListener);
325d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
326d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_out);
327d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addUpdateListener(listener);
328d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addListener(mFadeListener);
329d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
330d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
331d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100,0);
332d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogAccelerateInterpolator = new LogAccelerateInterpolator(100,0);
333d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
3342d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    private View getControlRowView() {
3352d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (getVerticalGridView() == null) {
3362d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
3372d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
3382d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        RecyclerView.ViewHolder vh = getVerticalGridView().findViewHolderForPosition(0);
3392d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (vh == null) {
3402d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
3412d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
3422d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        return vh.itemView;
3432d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    }
3442d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
345d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadControlRowAnimator() {
3462d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
347d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
3482d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
3492d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
3502d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
3512d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    views.add(view);
3521e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
3532d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
3542d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
3552d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
3562d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
3572d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
3582d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
3592d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
360d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    final float fraction = (Float) arg0.getAnimatedValue();
361d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (DEBUG) Log.v(TAG, "fraction " + fraction);
3622d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setAlpha(fraction);
3632d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
364d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
365d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
366d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
367d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
368d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator = loadAnimator(
369d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
3702d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addUpdateListener(updateListener);
3712d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addListener(listener);
372d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
373d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
374d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator = loadAnimator(
375d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
3762d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addUpdateListener(updateListener);
3772d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addListener(listener);
378d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator.setInterpolator(mLogAccelerateInterpolator);
379d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
380d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
381d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadOtherRowAnimator() {
3822d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
383d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
3842d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
3851e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                if (getVerticalGridView() == null) {
3861e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    return;
3871e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
388d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                final int count = getVerticalGridView().getChildCount();
389d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                for (int i = 0; i < count; i++) {
390d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    View view = getVerticalGridView().getChildAt(i);
3912d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    if (view != null) {
3922d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                        views.add(view);
3932d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    }
3942d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                }
3952d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
3962d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
3972d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
3982d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
3992d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4002d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                final float fraction = (Float) arg0.getAnimatedValue();
4012d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                for (View view : listener.mViews) {
402d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (getVerticalGridView().getChildPosition(view) > 0) {
403d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                        view.setAlpha(fraction);
4046b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
405d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    }
406d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
407d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
408d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
409d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
410d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator = loadAnimator(
411d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
4122d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addListener(listener);
4132d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addUpdateListener(updateListener);
414d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
415d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
416d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeOutAnimator = loadAnimator(
417d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
4182d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addListener(listener);
4192d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addUpdateListener(updateListener);
4206b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mOtherRowFadeOutAnimator.setInterpolator(new AccelerateInterpolator());
4216b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    }
4226b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
4236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private void loadDescriptionAnimator() {
4246b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
4256b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            @Override
4266b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4276b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (getVerticalGridView() == null) {
4286b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    return;
4296b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
4306b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                ItemBridgeAdapter.ViewHolder adapterVh = (ItemBridgeAdapter.ViewHolder)
4316b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        getVerticalGridView().findViewHolderForPosition(0);
4326b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (adapterVh != null && adapterVh.getViewHolder()
4336b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        instanceof PlaybackControlsRowPresenter.ViewHolder) {
4346b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    final Presenter.ViewHolder vh = ((PlaybackControlsRowPresenter.ViewHolder)
4356b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                            adapterVh.getViewHolder()).mDescriptionViewHolder;
4368f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    if (vh != null) {
4378f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.view.setAlpha((Float) arg0.getAnimatedValue());
4388f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    }
4396b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
4406b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
4416b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        };
4426b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
4436b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator = loadAnimator(
4446b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_in);
4456b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.addUpdateListener(listener);
4466b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
4476b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
4486b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator = loadAnimator(
4496b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_out);
4506b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator.addUpdateListener(listener);
451d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
452d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
453372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private void fade(boolean fadeIn) {
454372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "fade " + fadeIn);
455372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (getView() == null) {
456372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
457372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
458372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if ((fadeIn && mFadingStatus == IN) || (!fadeIn && mFadingStatus == OUT)) {
459d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "requested fade in progress");
460d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            return;
461d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
462d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if ((fadeIn && mBgAlpha == 255) || (!fadeIn && mBgAlpha == 0)) {
463d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "fade is no-op");
464372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
465372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
466372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
4676b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mAnimationTranslateY = getVerticalGridView().getSelectedPosition() == 0 ?
4686b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mMajorFadeTranslateY : mMinorFadeTranslateY;
469d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
470d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if (mFadingStatus == IDLE) {
471d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
472d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.start();
473d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.start();
474d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.start();
4756b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.start();
476d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
477d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.start();
478d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.start();
479d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.start();
4806b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.start();
481d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
482d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        } else {
483d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
484d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.reverse();
485d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.reverse();
486d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.reverse();
4876b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.reverse();
488d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
489d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.reverse();
490d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.reverse();
491d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.reverse();
4926b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.reverse();
493d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
494d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
495d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
496d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // If fading in while control row is focused, set initial translationY so
497d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // views slide in from below.
4986b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        if (fadeIn && mFadingStatus == IDLE) {
499d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            final int count = getVerticalGridView().getChildCount();
500d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            for (int i = 0; i < count; i++) {
5016b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getVerticalGridView().getChildAt(i).setTranslationY(mAnimationTranslateY);
502d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
503d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
504d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
505372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadingStatus = fadeIn ? IN : OUT;
506372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
5077ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5087ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
5097ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Sets the list of rows for the fragment.
5107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
5117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
5127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void setAdapter(ObjectAdapter adapter) {
5136dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (getAdapter() != null) {
5146dca725412977bb56b933bdec120e31909233cdbCraig Stout            getAdapter().unregisterObserver(mObserver);
5156dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
5167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.setAdapter(adapter);
5176dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (adapter != null) {
5186dca725412977bb56b933bdec120e31909233cdbCraig Stout            adapter.registerObserver(mObserver);
5196dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
5207ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
5217ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
5237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    void setVerticalGridViewLayout(VerticalGridView listview) {
524d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (listview == null) {
5257ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            return;
5267ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
527d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Padding affects alignment when last row is focused
528d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // (last is first when there's only one row).
529d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        setBottomPadding(listview, mPaddingBottom);
530d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
531d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Item alignment affects focused row that isn't the last.
532d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        listview.setItemAlignmentOffset(mAlignPosition);
5337ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setItemAlignmentOffsetPercent(100);
534d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
535d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Push rows to the bottom.
5367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignmentOffset(0);
5377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignmentOffsetPercent(100);
5387ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE);
5397ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
5407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
541d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private static void setBottomPadding(View view, int padding) {
542d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        view.setPadding(view.getPaddingLeft(), view.getPaddingTop(),
543d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                view.getPaddingRight(), padding);
544d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
545d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
5467ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
5477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onCreate(Bundle savedInstanceState) {
5487ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.onCreate(savedInstanceState);
5497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        mAlignPosition =
551d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_align_bottom);
552d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        mPaddingBottom =
553d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_bottom);
5547709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgDarkColor =
5557709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_dark);
5567709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgLightColor =
5577709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_light);
558372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mShowTimeMs =
559372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                getResources().getInteger(R.integer.lb_playback_controls_show_time_ms);
5606b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMajorFadeTranslateY =
5616b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_major_fade_translate_y);
5626b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMinorFadeTranslateY =
5636b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_minor_fade_translate_y);
564d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
565d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadBgAnimator();
566d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadControlRowAnimator();
567d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadOtherRowAnimator();
5686b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        loadDescriptionAnimator();
5697709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
5707709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
5717709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
5727709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Sets the background type.
5737709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     *
5747709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * @param type One of BG_LIGHT, BG_DARK, or BG_NONE.
5757709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
5767709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public void setBackgroundType(int type) {
577372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        switch (type) {
578372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_LIGHT:
579372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_DARK:
580372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_NONE:
581372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (type != mBackgroundType) {
582372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                mBackgroundType = type;
583372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                updateBackground();
584372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
585372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            break;
586372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        default:
5877709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            throw new IllegalArgumentException("Invalid background type");
5887709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
5897709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
5907709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
5917709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
5927709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Returns the background type.
5937709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
5947709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public int getBackgroundType() {
5957709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mBackgroundType;
5967709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
5977709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
5987709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private void updateBackground() {
5997709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        if (mRootView != null) {
6007709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            int color = mBgDarkColor;
6017709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            switch (mBackgroundType) {
6027709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_DARK: break;
6037709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_LIGHT: color = mBgLightColor; break;
6047709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_NONE: color = Color.TRANSPARENT; break;
6057709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            }
6067709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            mRootView.setBackground(new ColorDrawable(color));
6077709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
6087709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6097709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
610d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private void updateControlsBottomSpace(ItemBridgeAdapter.ViewHolder vh) {
611d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Add extra space between rows 0 and 1
612d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh == null && getVerticalGridView() != null) {
613d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            vh = (ItemBridgeAdapter.ViewHolder)
614d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    getVerticalGridView().findViewHolderForPosition(0);
615d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
616d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh != null && vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
617d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            final int adapterSize = getAdapter() == null ? 0 : getAdapter().size();
618d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showBottomSpace(
619d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder(),
620d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    adapterSize > 1);
621d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
622d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
623d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
624d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private final ItemBridgeAdapter.AdapterListener mAdapterListener =
625d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            new ItemBridgeAdapter.AdapterListener() {
626d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
627d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) {
628d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAttachedToWindow " + vh.getViewHolder().view);
629d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if ((mFadingStatus == IDLE && mBgAlpha == 0) || mFadingStatus == OUT) {
630d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (DEBUG) Log.v(TAG, "setting alpha to 0");
631d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                vh.getViewHolder().view.setAlpha(0);
632d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
633aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            if (vh.getPosition() == 0 && mResetControlsToPrimaryActionsPending) {
634aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                resetControlsToPrimaryActions(vh);
635aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            }
636d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
637d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
638d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) {
639d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onDetachedFromWindow " + vh.getViewHolder().view);
640d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            // Reset animation state
641d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setAlpha(1f);
642d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setTranslationY(0);
6436b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            if (vh.getViewHolder() instanceof PlaybackControlsRowPresenter.ViewHolder) {
6448f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                Presenter.ViewHolder descriptionVh = ((PlaybackControlsRowPresenter.ViewHolder)
6458f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.getViewHolder()).mDescriptionViewHolder;
6468f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                if (descriptionVh != null) {
6478f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    descriptionVh.view.setAlpha(1f);
6488f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                }
6496b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
650d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
651d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        @Override
652d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        public void onBind(ItemBridgeAdapter.ViewHolder vh) {
653d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            if (vh.getPosition() == 0) {
654d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                updateControlsBottomSpace(vh);
655d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            }
656d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
657d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    };
658d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
6597709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    @Override
6607709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public View onCreateView(LayoutInflater inflater, ViewGroup container,
6617709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            Bundle savedInstanceState) {
6627709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mRootView = super.onCreateView(inflater, container, savedInstanceState);
663d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = 255;
6647709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        updateBackground();
665d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        getRowsFragment().setExternalAdapterListener(mAdapterListener);
6667709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mRootView;
6677ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
6686dca725412977bb56b933bdec120e31909233cdbCraig Stout
6691e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    @Override
6701e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    public void onDestroyView() {
6711e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        mRootView = null;
6721e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        super.onDestroyView();
6731e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    }
6741e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout
6756dca725412977bb56b933bdec120e31909233cdbCraig Stout    private final DataObserver mObserver = new DataObserver() {
6766dca725412977bb56b933bdec120e31909233cdbCraig Stout        public void onChanged() {
677d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            updateControlsBottomSpace(null);
6786dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
6796dca725412977bb56b933bdec120e31909233cdbCraig Stout    };
6802d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
6812d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    static abstract class AnimatorListener implements Animator.AnimatorListener {
6822d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<View> mViews = new ArrayList<View>();
6832d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<Integer> mLayerType = new ArrayList<Integer>();
6842d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
6852d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationCancel(Animator animation) {
6862d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
6872d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationRepeat(Animator animation) {
6882d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
6892d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationStart(Animator animation) {
6902d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            getViews(mViews);
6912d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (View view : mViews) {
6922d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mLayerType.add(view.getLayerType());
6932d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
6942d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
6952d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
6962d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationEnd(Animator animation) {
6972d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (int i = 0; i < mViews.size(); i++) {
6982d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mViews.get(i).setLayerType(mLayerType.get(i), null);
6992d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
7002d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mLayerType.clear();
7012d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mViews.clear();
7022d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
7032d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        abstract void getViews(ArrayList<View> views);
7042d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    };
7057ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout}
706