PlaybackOverlayFragment.java revision 22eaa9441bf3a521bfafb160674ff2da421eded8
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;
2260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.support.v17.leanback.widget.Action;
2360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.support.v17.leanback.widget.PlaybackControlsRow;
24cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stoutimport android.view.InputEvent;
256b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.view.animation.AccelerateInterpolator;
26d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.ValueAnimator.AnimatorUpdateListener;
27d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.content.Context;
287ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.os.Bundle;
29372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Handler;
30372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Message;
31d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v7.widget.RecyclerView;
327ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.R;
33d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogAccelerateInterpolator;
34d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogDecelerateInterpolator;
35d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.widget.ItemBridgeAdapter;
367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.widget.ObjectAdapter;
376dca725412977bb56b933bdec120e31909233cdbCraig Stoutimport android.support.v17.leanback.widget.ObjectAdapter.DataObserver;
386b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
3922eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.Presenter;
4022eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
4122eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.RowPresenter;
4222eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
43372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.util.Log;
44372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.KeyEvent;
457709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.LayoutInflater;
46372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.MotionEvent;
477709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.View;
487709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.ViewGroup;
497ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
502d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stoutimport java.util.ArrayList;
517ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/**
537ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * A fragment for displaying playback controls and related content.
54a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
55a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * A PlaybackOverlayFragment renders the elements of its {@link ObjectAdapter} as a set
5622eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of rows in a vertical list.  The Adapter's {@link PresenterSelector} must maintain subclasses
5722eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of {@link RowPresenter}.
58a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
59a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
60a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * An instance of {@link android.support.v17.leanback.widget.PlaybackControlsRow} is expected to be
616dca725412977bb56b933bdec120e31909233cdbCraig Stout * at position 0 in the adapter.
62a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
637ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
647ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpublic class PlaybackOverlayFragment extends DetailsFragment {
657ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
667709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
677709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * No background.
687709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
697709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_NONE = 0;
707709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
717709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
727709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A dark translucent background.
737709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
747709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_DARK = 1;
757709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
767709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
777709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A light translucent background.
787709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
797709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_LIGHT = 2;
807709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
81a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
82a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Listener allowing the application to receive notification of fade in and/or fade out
83a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * completion events.
84a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
85372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public static class OnFadeCompleteListener {
86372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeInComplete() {
87372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
88372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeOutComplete() {
89372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
90372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
91372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
92a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
93a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Interface allowing the application to handle input events.
94a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
95eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    public interface InputEventHandler {
96eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        /**
97eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * Called when an {@link InputEvent} is received.
98eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         *
99eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * @return If the event should be consumed, return true. To allow the event to
100eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * continue on to the next handler, return false.
101eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         */
102eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        public boolean handleInputEvent(InputEvent event);
103eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
104eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
105372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final String TAG = "PlaybackOverlayFragment";
106372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final boolean DEBUG = false;
107d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static final int ANIMATION_MULTIPLIER = 1;
108372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
109372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static int START_FADE_OUT = 1;
110372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
111372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    // Fading status
112372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int IDLE = 0;
113372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int IN = 1;
114372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int OUT = 2;
115372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
1167ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    private int mAlignPosition;
117d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private int mPaddingBottom;
1187709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private View mRootView;
1197709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBackgroundType = BG_DARK;
1207709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgDarkColor;
1217709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgLightColor;
122372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private int mShowTimeMs;
1236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private int mMajorFadeTranslateY, mMinorFadeTranslateY;
1246b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private int mAnimationTranslateY;
125372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private OnFadeCompleteListener mFadeCompleteListener;
126eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    private InputEventHandler mInputEventHandler;
127372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private boolean mFadingEnabled = true;
128372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private int mFadingStatus = IDLE;
129d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private int mBgAlpha;
130d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mBgFadeInAnimator, mBgFadeOutAnimator;
131d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mControlRowFadeInAnimator, mControlRowFadeOutAnimator;
1326b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private ValueAnimator mDescriptionFadeInAnimator, mDescriptionFadeOutAnimator;
133d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mOtherRowFadeInAnimator, mOtherRowFadeOutAnimator;
134d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private boolean mTranslateAnimationEnabled;
135aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    private boolean mResetControlsToPrimaryActionsPending;
136d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private RecyclerView.ItemAnimator mItemAnimator;
137372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
138372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final Animator.AnimatorListener mFadeListener =
139372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new Animator.AnimatorListener() {
140372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
141372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationStart(Animator animation) {
142d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            enableVerticalGridAnimations(false);
143372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
144372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
145372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationRepeat(Animator animation) {
146372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
147372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
148372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationCancel(Animator animation) {
149372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
150372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
151372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationEnd(Animator animation) {
152d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAnimationEnd " + mBgAlpha);
153d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (mBgAlpha > 0) {
154d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                enableVerticalGridAnimations(true);
155372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                startFadeTimer();
156372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                if (mFadeCompleteListener != null) {
157372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    mFadeCompleteListener.onFadeInComplete();
158372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
159d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
1601e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                if (getVerticalGridView() != null) {
1611e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    // Reset focus to the controls row
1621e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    getVerticalGridView().setSelectedPosition(0);
163aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    resetControlsToPrimaryActions(null);
1641e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
165d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (mFadeCompleteListener != null) {
166d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    mFadeCompleteListener.onFadeOutComplete();
167d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
168372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
169372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingStatus = IDLE;
170372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
171372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
172372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
173372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final Handler mHandler = new Handler() {
174372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
175372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void handleMessage(Message message) {
176372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (message.what == START_FADE_OUT && mFadingEnabled) {
177372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                fade(false);
178372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
179372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
180372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
181372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
182372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnTouchInterceptListener mOnTouchInterceptListener =
183372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnTouchInterceptListener() {
184372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptTouchEvent(MotionEvent event) {
185cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
186372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
187372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
188372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
189372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnKeyInterceptListener mOnKeyInterceptListener =
190372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnKeyInterceptListener() {
191372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptKeyEvent(KeyEvent event) {
192cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
193372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
194372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
195372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
196d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void setBgAlpha(int alpha) {
197d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = alpha;
1981e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        if (mRootView != null) {
1991e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mRootView.getBackground().setAlpha(alpha);
2001e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
201d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
202d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
203d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void enableVerticalGridAnimations(boolean enable) {
204aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (getVerticalGridView() != null) {
205aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            getVerticalGridView().setAnimateChildLayout(enable);
206aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        }
207aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    }
208aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout
209aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    private void resetControlsToPrimaryActions(ItemBridgeAdapter.ViewHolder vh) {
210aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null && getVerticalGridView() != null) {
211aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            vh = (ItemBridgeAdapter.ViewHolder) getVerticalGridView().findViewHolderForPosition(0);
2121e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
213aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null) {
214aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = true;
215aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        } else if (vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
216aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = false;
217aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showPrimaryActions(
218aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder());
219d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
220d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
221d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
222372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
223372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Enables or disables view fading.  If enabled,
224372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * the view will be faded in when the fragment starts,
225372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * and will fade out after a time period.  The timeout
226372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * period is reset each time {@link #tickle} is called.
227372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     *
228372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
229372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadingEnabled(boolean enabled) {
230372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "setFadingEnabled " + enabled);
231372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (enabled != mFadingEnabled) {
232372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingEnabled = enabled;
233f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            if (mFadingEnabled) {
234f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                if (isResumed() && mFadingStatus == IDLE
235f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                        && !mHandler.hasMessages(START_FADE_OUT)) {
236f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                    startFadeTimer();
237372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
238f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            } else {
239f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                // Ensure fully opaque
240f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                mHandler.removeMessages(START_FADE_OUT);
241f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                fade(true);
242372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
243372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
244372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
245372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
246372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
247372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns true if view fading is enabled.
248372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
249372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public boolean isFadingEnabled() {
250372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadingEnabled;
251372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
252372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
253372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
254372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Sets the listener to be called when fade in or out has completed.
255372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
256372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadeCompleteListener(OnFadeCompleteListener listener) {
257372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadeCompleteListener = listener;
258372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
259372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
260372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
261372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns the listener to be called when fade in or out has completed.
262372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
263372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public OnFadeCompleteListener getFadeCompleteListener() {
264372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadeCompleteListener;
265372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
266372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
267372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
268eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Sets the input event handler.
269eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
270eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    public final void setInputEventHandler(InputEventHandler handler) {
271eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        mInputEventHandler = handler;
272eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
273eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
274eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
275eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Returns the input event handler.
276eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
2772dfed05c8ab53ca7c28424c9c03b1a87b9b7ca0dCraig Stout    public final InputEventHandler getInputEventHandler() {
278eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        return mInputEventHandler;
279eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
280eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
281eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
282372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Tickles the playback controls.  Fades in the view if it was faded out,
283372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * otherwise resets the fade out timer.  Tickling on input events is handled
284372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * by the fragment.
285372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
286372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void tickle() {
287372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "tickle enabled " + mFadingEnabled + " isResumed " + isResumed());
288372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (!mFadingEnabled || !isResumed()) {
289372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
290372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
291372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (mHandler.hasMessages(START_FADE_OUT)) {
292372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            // Restart the timer
293372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            startFadeTimer();
294372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        } else {
295372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
296372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
297372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
298372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
29991e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    /**
30091e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     * Fades out the playback overlay immediately.
30191e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     */
30291e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    public void fadeOut() {
30391e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        if (!mFadingEnabled) {
30491e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang            return;
30591e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        }
30691e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        mHandler.removeMessages(START_FADE_OUT);
30791e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        fade(false);
30891e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    }
30991e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang
31060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout    private boolean areControlsHidden() {
31160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        return mFadingStatus == IDLE && mBgAlpha == 0;
312cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    }
313cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout
314cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    private boolean onInterceptInputEvent(InputEvent event) {
31560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        final boolean controlsHidden = areControlsHidden();
31660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (DEBUG) Log.v(TAG, "onInterceptInputEvent hidden " + controlsHidden + " " + event);
31760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        boolean consumeEvent = false;
318c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        int keyCode = KeyEvent.KEYCODE_UNKNOWN;
319c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout
32060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (mInputEventHandler != null) {
32160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            consumeEvent = mInputEventHandler.handleInputEvent(event);
32260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        }
323cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (event instanceof KeyEvent) {
324c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout            keyCode = ((KeyEvent) event).getKeyCode();
325c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        }
32660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout
32760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        switch (keyCode) {
32860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_CENTER:
32960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_DOWN:
33060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_UP:
33160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_LEFT:
33260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_RIGHT:
33360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // Event may be consumed; regardless, if controls are hidden then these keys will
33460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // bring up the controls.
33560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (controlsHidden) {
33660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
33760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
338cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout                tickle();
33960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
34060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_BACK:
341c89266e21f0269aecd5df2dc2a39f6f0cf11a58eCraig Stout            case KeyEvent.KEYCODE_ESCAPE:
34260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // If fading enabled and controls are not hidden, back will be consumed to fade
34360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // them out (even if the key was consumed by the handler).
34460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (mFadingEnabled && !controlsHidden) {
34560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
34660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    mHandler.removeMessages(START_FADE_OUT);
34760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    fade(false);
34860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                } else if (consumeEvent) {
34960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
35060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
35160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
35260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            default:
35360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (consumeEvent) {
35460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
35560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
356eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        }
357372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return consumeEvent;
358372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
359372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
360372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    @Override
361372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void onResume() {
362372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        super.onResume();
363372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (mFadingEnabled) {
364d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            setBgAlpha(0);
365372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
366372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
367372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnTouchInterceptListener(mOnTouchInterceptListener);
368372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener);
369372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
370372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
371372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private void startFadeTimer() {
3721e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        if (mHandler != null) {
3731e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mHandler.removeMessages(START_FADE_OUT);
3741e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mHandler.sendEmptyMessageDelayed(START_FADE_OUT, mShowTimeMs);
3751e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
376372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
377372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
378d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static ValueAnimator loadAnimator(Context context, int resId) {
379d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(context, resId);
380d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        animator.setDuration(animator.getDuration() * ANIMATION_MULTIPLIER);
381d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        return animator;
382d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
383d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
384d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadBgAnimator() {
385d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
386d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
387d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
388d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                setBgAlpha((Integer) arg0.getAnimatedValue());
389d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
390d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
391d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
392d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_in);
393d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addUpdateListener(listener);
394d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addListener(mFadeListener);
395d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
396d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_out);
397d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addUpdateListener(listener);
398d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addListener(mFadeListener);
399d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
400d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
401d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100,0);
402d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogAccelerateInterpolator = new LogAccelerateInterpolator(100,0);
403d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
4042d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    private View getControlRowView() {
4052d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (getVerticalGridView() == null) {
4062d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
4072d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
4082d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        RecyclerView.ViewHolder vh = getVerticalGridView().findViewHolderForPosition(0);
4092d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (vh == null) {
4102d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
4112d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
4122d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        return vh.itemView;
4132d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    }
4142d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
415d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadControlRowAnimator() {
4162d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
417d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
4182d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
4192d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
4202d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
4212d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    views.add(view);
4221e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
4232d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
4242d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
4252d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
4262d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
4272d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4282d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
4292d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
430d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    final float fraction = (Float) arg0.getAnimatedValue();
431d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (DEBUG) Log.v(TAG, "fraction " + fraction);
4322d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setAlpha(fraction);
4332d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
434d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
435d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
436d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
437d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
438d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator = loadAnimator(
439d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
4402d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addUpdateListener(updateListener);
4412d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addListener(listener);
442d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
443d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
444d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator = loadAnimator(
445d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
4462d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addUpdateListener(updateListener);
4472d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addListener(listener);
448d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator.setInterpolator(mLogAccelerateInterpolator);
449d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
450d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
451d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadOtherRowAnimator() {
4522d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
453d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
4542d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
4551e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                if (getVerticalGridView() == null) {
4561e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    return;
4571e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
458d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                final int count = getVerticalGridView().getChildCount();
459d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                for (int i = 0; i < count; i++) {
460d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    View view = getVerticalGridView().getChildAt(i);
4612d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    if (view != null) {
4622d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                        views.add(view);
4632d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    }
4642d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                }
4652d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
4662d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
4672d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
4682d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
4692d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4701df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                if (getVerticalGridView() == null) {
4711df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                    return;
4721df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                }
4732d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                final float fraction = (Float) arg0.getAnimatedValue();
4742d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                for (View view : listener.mViews) {
475d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (getVerticalGridView().getChildPosition(view) > 0) {
476d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                        view.setAlpha(fraction);
4776b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
478d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    }
479d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
480d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
481d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
482d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
483d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator = loadAnimator(
484d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
4852d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addListener(listener);
4862d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addUpdateListener(updateListener);
487d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
488d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
489d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeOutAnimator = loadAnimator(
490d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
4912d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addListener(listener);
4922d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addUpdateListener(updateListener);
4936b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mOtherRowFadeOutAnimator.setInterpolator(new AccelerateInterpolator());
4946b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    }
4956b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
4966b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private void loadDescriptionAnimator() {
4976b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
4986b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            @Override
4996b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
5006b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (getVerticalGridView() == null) {
5016b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    return;
5026b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
5036b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                ItemBridgeAdapter.ViewHolder adapterVh = (ItemBridgeAdapter.ViewHolder)
5046b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        getVerticalGridView().findViewHolderForPosition(0);
5056b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (adapterVh != null && adapterVh.getViewHolder()
5066b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        instanceof PlaybackControlsRowPresenter.ViewHolder) {
5076b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    final Presenter.ViewHolder vh = ((PlaybackControlsRowPresenter.ViewHolder)
5086b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                            adapterVh.getViewHolder()).mDescriptionViewHolder;
5098f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    if (vh != null) {
5108f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.view.setAlpha((Float) arg0.getAnimatedValue());
5118f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    }
5126b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
5136b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
5146b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        };
5156b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
5166b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator = loadAnimator(
5176b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_in);
5186b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.addUpdateListener(listener);
5196b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
5206b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
5216b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator = loadAnimator(
5226b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_out);
5236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator.addUpdateListener(listener);
524d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
525d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
526372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private void fade(boolean fadeIn) {
527372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "fade " + fadeIn);
528372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (getView() == null) {
529372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
530372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
531372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if ((fadeIn && mFadingStatus == IN) || (!fadeIn && mFadingStatus == OUT)) {
532d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "requested fade in progress");
533d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            return;
534d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
535d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if ((fadeIn && mBgAlpha == 255) || (!fadeIn && mBgAlpha == 0)) {
536d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "fade is no-op");
537372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
538372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
539372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
5406b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mAnimationTranslateY = getVerticalGridView().getSelectedPosition() == 0 ?
5416b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mMajorFadeTranslateY : mMinorFadeTranslateY;
542d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
543d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if (mFadingStatus == IDLE) {
544d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
545d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.start();
546d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.start();
547d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.start();
5486b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.start();
549d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
550d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.start();
551d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.start();
552d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.start();
5536b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.start();
554d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
555d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        } else {
556d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
557d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.reverse();
558d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.reverse();
559d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.reverse();
5606b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.reverse();
561d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
562d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.reverse();
563d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.reverse();
564d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.reverse();
5656b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.reverse();
566d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
567d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
568d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
569d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // If fading in while control row is focused, set initial translationY so
570d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // views slide in from below.
5716b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        if (fadeIn && mFadingStatus == IDLE) {
572d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            final int count = getVerticalGridView().getChildCount();
573d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            for (int i = 0; i < count; i++) {
5746b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getVerticalGridView().getChildAt(i).setTranslationY(mAnimationTranslateY);
575d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
576d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
577d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
578372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadingStatus = fadeIn ? IN : OUT;
579372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
5807ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5817ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
5827ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Sets the list of rows for the fragment.
5837ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
5847ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
5857ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void setAdapter(ObjectAdapter adapter) {
5866dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (getAdapter() != null) {
5876dca725412977bb56b933bdec120e31909233cdbCraig Stout            getAdapter().unregisterObserver(mObserver);
5886dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
5897ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.setAdapter(adapter);
5906dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (adapter != null) {
5916dca725412977bb56b933bdec120e31909233cdbCraig Stout            adapter.registerObserver(mObserver);
5926dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
5937ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
5947ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5957ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
5967ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    void setVerticalGridViewLayout(VerticalGridView listview) {
597d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (listview == null) {
5987ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            return;
5997ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
600d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Padding affects alignment when last row is focused
601d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // (last is first when there's only one row).
602d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        setBottomPadding(listview, mPaddingBottom);
603d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
604d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Item alignment affects focused row that isn't the last.
605d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        listview.setItemAlignmentOffset(mAlignPosition);
6067ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setItemAlignmentOffsetPercent(100);
607d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
608d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Push rows to the bottom.
6097ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignmentOffset(0);
6107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignmentOffsetPercent(100);
6117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_HIGH_EDGE);
6127ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
6137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
614d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private static void setBottomPadding(View view, int padding) {
615d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        view.setPadding(view.getPaddingLeft(), view.getPaddingTop(),
616d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                view.getPaddingRight(), padding);
617d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
618d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
6197ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
6207ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onCreate(Bundle savedInstanceState) {
6217ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.onCreate(savedInstanceState);
6227ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
6237ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        mAlignPosition =
624d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_align_bottom);
625d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        mPaddingBottom =
626d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_bottom);
6277709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgDarkColor =
6287709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_dark);
6297709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgLightColor =
6307709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_light);
631372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mShowTimeMs =
632372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                getResources().getInteger(R.integer.lb_playback_controls_show_time_ms);
6336b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMajorFadeTranslateY =
6346b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_major_fade_translate_y);
6356b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMinorFadeTranslateY =
6366b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_minor_fade_translate_y);
637d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
638d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadBgAnimator();
639d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadControlRowAnimator();
640d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadOtherRowAnimator();
6416b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        loadDescriptionAnimator();
6427709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6437709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6447709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
6457709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Sets the background type.
6467709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     *
6477709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * @param type One of BG_LIGHT, BG_DARK, or BG_NONE.
6487709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
6497709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public void setBackgroundType(int type) {
650372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        switch (type) {
651372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_LIGHT:
652372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_DARK:
653372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_NONE:
654372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (type != mBackgroundType) {
655372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                mBackgroundType = type;
656372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                updateBackground();
657372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
658372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            break;
659372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        default:
6607709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            throw new IllegalArgumentException("Invalid background type");
6617709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
6627709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6637709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6647709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
6657709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Returns the background type.
6667709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
6677709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public int getBackgroundType() {
6687709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mBackgroundType;
6697709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6707709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6717709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private void updateBackground() {
6727709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        if (mRootView != null) {
6737709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            int color = mBgDarkColor;
6747709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            switch (mBackgroundType) {
6757709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_DARK: break;
6767709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_LIGHT: color = mBgLightColor; break;
6777709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_NONE: color = Color.TRANSPARENT; break;
6787709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            }
6797709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            mRootView.setBackground(new ColorDrawable(color));
6807709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
6817709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6827709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
683d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private void updateControlsBottomSpace(ItemBridgeAdapter.ViewHolder vh) {
684d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Add extra space between rows 0 and 1
685d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh == null && getVerticalGridView() != null) {
686d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            vh = (ItemBridgeAdapter.ViewHolder)
687d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    getVerticalGridView().findViewHolderForPosition(0);
688d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
689d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh != null && vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
690d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            final int adapterSize = getAdapter() == null ? 0 : getAdapter().size();
691d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showBottomSpace(
692d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder(),
693d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    adapterSize > 1);
694d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
695d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
696d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
697d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private final ItemBridgeAdapter.AdapterListener mAdapterListener =
698d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            new ItemBridgeAdapter.AdapterListener() {
699d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
700d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) {
701d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAttachedToWindow " + vh.getViewHolder().view);
702d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if ((mFadingStatus == IDLE && mBgAlpha == 0) || mFadingStatus == OUT) {
703d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (DEBUG) Log.v(TAG, "setting alpha to 0");
704d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                vh.getViewHolder().view.setAlpha(0);
705d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
706aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            if (vh.getPosition() == 0 && mResetControlsToPrimaryActionsPending) {
707aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                resetControlsToPrimaryActions(vh);
708aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            }
709d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
710d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
711d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) {
712d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onDetachedFromWindow " + vh.getViewHolder().view);
713d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            // Reset animation state
714d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setAlpha(1f);
715d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setTranslationY(0);
7166b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            if (vh.getViewHolder() instanceof PlaybackControlsRowPresenter.ViewHolder) {
7178f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                Presenter.ViewHolder descriptionVh = ((PlaybackControlsRowPresenter.ViewHolder)
7188f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.getViewHolder()).mDescriptionViewHolder;
7198f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                if (descriptionVh != null) {
7208f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    descriptionVh.view.setAlpha(1f);
7218f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                }
7226b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
723d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
724d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        @Override
725d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        public void onBind(ItemBridgeAdapter.ViewHolder vh) {
726d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            if (vh.getPosition() == 0) {
727d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                updateControlsBottomSpace(vh);
728d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            }
729d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
730d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    };
731d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
7327709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    @Override
7337709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public View onCreateView(LayoutInflater inflater, ViewGroup container,
7347709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            Bundle savedInstanceState) {
7357709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mRootView = super.onCreateView(inflater, container, savedInstanceState);
736d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = 255;
7377709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        updateBackground();
738d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        getRowsFragment().setExternalAdapterListener(mAdapterListener);
7397709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mRootView;
7407ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
7416dca725412977bb56b933bdec120e31909233cdbCraig Stout
7421e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    @Override
7431e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    public void onDestroyView() {
7441e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        mRootView = null;
7451e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        super.onDestroyView();
7461e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    }
7471e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout
7486dca725412977bb56b933bdec120e31909233cdbCraig Stout    private final DataObserver mObserver = new DataObserver() {
7496dca725412977bb56b933bdec120e31909233cdbCraig Stout        public void onChanged() {
750d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            updateControlsBottomSpace(null);
7516dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
7526dca725412977bb56b933bdec120e31909233cdbCraig Stout    };
7532d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
7542d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    static abstract class AnimatorListener implements Animator.AnimatorListener {
7552d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<View> mViews = new ArrayList<View>();
7562d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<Integer> mLayerType = new ArrayList<Integer>();
7572d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
7582d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationCancel(Animator animation) {
7592d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
7602d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationRepeat(Animator animation) {
7612d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
7622d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationStart(Animator animation) {
7632d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            getViews(mViews);
7642d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (View view : mViews) {
7652d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mLayerType.add(view.getLayerType());
7662d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
7672d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
7682d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
7692d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationEnd(Animator animation) {
7702d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (int i = 0; i < mViews.size(); i++) {
7712d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mViews.get(i).setLayerType(mLayerType.get(i), null);
7722d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
7732d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mLayerType.clear();
7742d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mViews.clear();
7752d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
7762d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        abstract void getViews(ArrayList<View> views);
7772d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    };
7787ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout}
779