PlaybackOverlayFragment.java revision b655650666d7bd317c41c7a5be229e3a80dd2692
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
16372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.animation.Animator;
17d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.AnimatorInflater;
18d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.TimeInterpolator;
19d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.ValueAnimator;
20d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.animation.ValueAnimator.AnimatorUpdateListener;
21d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.content.Context;
223103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.graphics.Color;
233103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.graphics.drawable.ColorDrawable;
247ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.os.Bundle;
25372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Handler;
26372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.os.Message;
277ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.R;
28d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogAccelerateInterpolator;
29d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.animation.LogDecelerateInterpolator;
30d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stoutimport android.support.v17.leanback.widget.ItemBridgeAdapter;
317ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutimport android.support.v17.leanback.widget.ObjectAdapter;
326dca725412977bb56b933bdec120e31909233cdbCraig Stoutimport android.support.v17.leanback.widget.ObjectAdapter.DataObserver;
336b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stoutimport android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
3422eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.Presenter;
3522eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
3622eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.RowPresenter;
3722eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
383103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.support.v7.widget.RecyclerView;
39372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.util.Log;
403103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.view.InputEvent;
41372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.KeyEvent;
427709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.LayoutInflater;
43372d07bb41510d91a6a662a1906aceb0ee759481Craig Stoutimport android.view.MotionEvent;
447709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.View;
457709709c2c78490a21311e9950d5dca7e89a6aedCraig Stoutimport android.view.ViewGroup;
463103f63e99d47573823957f7aa34308555873221Aurimas Liutikasimport android.view.animation.AccelerateInterpolator;
477ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
48b655650666d7bd317c41c7a5be229e3a80dd2692Dake Guimport java.lang.ref.WeakReference;
492d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stoutimport java.util.ArrayList;
507ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
517ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout/**
527ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout * A fragment for displaying playback controls and related content.
53a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
54a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * A PlaybackOverlayFragment renders the elements of its {@link ObjectAdapter} as a set
5522eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of rows in a vertical list.  The Adapter's {@link PresenterSelector} must maintain subclasses
5622eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of {@link RowPresenter}.
57a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
58a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
59a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * An instance of {@link android.support.v17.leanback.widget.PlaybackControlsRow} is expected to be
606dca725412977bb56b933bdec120e31909233cdbCraig Stout * at position 0 in the adapter.
61a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
62afd999aba1b74d876ea2620775ba9157e6df7102susnata * <p>
63afd999aba1b74d876ea2620775ba9157e6df7102susnata *  This class is now deprecated, please us
64afd999aba1b74d876ea2620775ba9157e6df7102susnata * </p>
65afd999aba1b74d876ea2620775ba9157e6df7102susnata * @deprecated Use {@link PlaybackFragment}.
667ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout */
67afd999aba1b74d876ea2620775ba9157e6df7102susnata@Deprecated
687ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stoutpublic class PlaybackOverlayFragment extends DetailsFragment {
697ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
707709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
717709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * No background.
727709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
737709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_NONE = 0;
747709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
757709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
767709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A dark translucent background.
777709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
787709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_DARK = 1;
797709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
807709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
817709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * A light translucent background.
827709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
837709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public static final int BG_LIGHT = 2;
847709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
85a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
86a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Listener allowing the application to receive notification of fade in and/or fade out
87a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * completion events.
88a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
89372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public static class OnFadeCompleteListener {
90372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeInComplete() {
91372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
92372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onFadeOutComplete() {
93372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
94372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
95372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
9699ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static final String TAG = "PlaybackOverlayFragment";
9799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static final boolean DEBUG = false;
98d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static final int ANIMATION_MULTIPLIER = 1;
99372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
10099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static int START_FADE_OUT = 1;
101372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
102372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    // Fading status
10399ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static final int IDLE = 0;
104372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private static final int IN = 1;
10599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    static final int OUT = 2;
106372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
1074fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri    private int mPaddingTop;
108d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    private int mPaddingBottom;
1097709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private View mRootView;
1107709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBackgroundType = BG_DARK;
1117709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgDarkColor;
1127709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private int mBgLightColor;
113372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private int mShowTimeMs;
1146b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private int mMajorFadeTranslateY, mMinorFadeTranslateY;
11599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    int mAnimationTranslateY;
11699ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    OnFadeCompleteListener mFadeCompleteListener;
117afd999aba1b74d876ea2620775ba9157e6df7102susnata    private PlaybackControlGlue.InputEventHandler mInputEventHandler;
11899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    boolean mFadingEnabled = true;
11999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    int mFadingStatus = IDLE;
12099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    int mBgAlpha;
121d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mBgFadeInAnimator, mBgFadeOutAnimator;
122d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mControlRowFadeInAnimator, mControlRowFadeOutAnimator;
1236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private ValueAnimator mDescriptionFadeInAnimator, mDescriptionFadeOutAnimator;
124d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private ValueAnimator mOtherRowFadeInAnimator, mOtherRowFadeOutAnimator;
12599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    boolean mResetControlsToPrimaryActionsPending;
126372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
127372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final Animator.AnimatorListener mFadeListener =
128372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new Animator.AnimatorListener() {
129372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
130372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationStart(Animator animation) {
131d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            enableVerticalGridAnimations(false);
132372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
133372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
134372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationRepeat(Animator animation) {
135372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
136372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
137372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationCancel(Animator animation) {
138372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
139372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
140372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void onAnimationEnd(Animator animation) {
141d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAnimationEnd " + mBgAlpha);
142d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (mBgAlpha > 0) {
143d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                enableVerticalGridAnimations(true);
144372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                startFadeTimer();
145372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                if (mFadeCompleteListener != null) {
146372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                    mFadeCompleteListener.onFadeInComplete();
147372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
148d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
149794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                VerticalGridView verticalView = getVerticalGridView();
150794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                // reset focus to the primary actions only if the selected row was the controls row
151794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                if (verticalView != null && verticalView.getSelectedPosition() == 0) {
152aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    resetControlsToPrimaryActions(null);
1531e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
154d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (mFadeCompleteListener != null) {
155d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    mFadeCompleteListener.onFadeOutComplete();
156d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
157372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
158372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingStatus = IDLE;
159372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
160372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
161372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
162b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu    static class FadeHandler extends Handler {
163372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        @Override
164372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public void handleMessage(Message message) {
165b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu            PlaybackOverlayFragment fragment;
166b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu            if (message.what == START_FADE_OUT) {
167b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                fragment = ((WeakReference<PlaybackOverlayFragment>) message.obj).get();
168b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                if (fragment != null && fragment.mFadingEnabled) {
169b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                    fragment.fade(false);
170b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                }
171372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
172372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
173b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu    }
174b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu
175b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu    static final Handler sHandler = new FadeHandler();
176b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu
177b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu    final WeakReference<PlaybackOverlayFragment> mFragmentReference =  new WeakReference(this);
178372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
179372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnTouchInterceptListener mOnTouchInterceptListener =
180372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnTouchInterceptListener() {
18115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
182372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptTouchEvent(MotionEvent event) {
183cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
184372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
185372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
186372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
187372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    private final VerticalGridView.OnKeyInterceptListener mOnKeyInterceptListener =
188372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            new VerticalGridView.OnKeyInterceptListener() {
18915375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
190372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        public boolean onInterceptKeyEvent(KeyEvent event) {
191cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
192372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
193372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    };
194372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
19599ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void setBgAlpha(int alpha) {
196d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = alpha;
1971e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        if (mRootView != null) {
1981e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout            mRootView.getBackground().setAlpha(alpha);
1991e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
200d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
201d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
20299ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void enableVerticalGridAnimations(boolean enable) {
203aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (getVerticalGridView() != null) {
204aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            getVerticalGridView().setAnimateChildLayout(enable);
205aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        }
206aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout    }
207aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout
20899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void resetControlsToPrimaryActions(ItemBridgeAdapter.ViewHolder vh) {
209aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null && getVerticalGridView() != null) {
210aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            vh = (ItemBridgeAdapter.ViewHolder) getVerticalGridView().findViewHolderForPosition(0);
2111e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        }
212aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        if (vh == null) {
213aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = true;
214aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout        } else if (vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
215aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            mResetControlsToPrimaryActionsPending = false;
216aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showPrimaryActions(
217aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder());
218d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
219d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
220d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
221372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
222372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Enables or disables view fading.  If enabled,
223372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * the view will be faded in when the fragment starts,
224372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * and will fade out after a time period.  The timeout
225372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * period is reset each time {@link #tickle} is called.
226372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     *
227372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
228372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadingEnabled(boolean enabled) {
229372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "setFadingEnabled " + enabled);
230372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (enabled != mFadingEnabled) {
231372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            mFadingEnabled = enabled;
232f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            if (mFadingEnabled) {
233f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                if (isResumed() && mFadingStatus == IDLE
234b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                        && !sHandler.hasMessages(START_FADE_OUT, mFragmentReference)) {
235f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                    startFadeTimer();
236372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                }
237f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            } else {
238f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                // Ensure fully opaque
239b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                sHandler.removeMessages(START_FADE_OUT, mFragmentReference);
240f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                fade(true);
241372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
242372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
243372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
244372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
245372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
246372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns true if view fading is enabled.
247372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
248372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public boolean isFadingEnabled() {
249372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadingEnabled;
250372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
251372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
252372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
253372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Sets the listener to be called when fade in or out has completed.
254372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
255372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void setFadeCompleteListener(OnFadeCompleteListener listener) {
256372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadeCompleteListener = listener;
257372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
258372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
259372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
260372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Returns the listener to be called when fade in or out has completed.
261372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
262372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public OnFadeCompleteListener getFadeCompleteListener() {
263372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return mFadeCompleteListener;
264372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
265372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
266afd999aba1b74d876ea2620775ba9157e6df7102susnata    @Deprecated
267afd999aba1b74d876ea2620775ba9157e6df7102susnata    public interface InputEventHandler extends PlaybackControlGlue.InputEventHandler {
268afd999aba1b74d876ea2620775ba9157e6df7102susnata    }
269afd999aba1b74d876ea2620775ba9157e6df7102susnata
270372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    /**
271eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Sets the input event handler.
272eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
273afd999aba1b74d876ea2620775ba9157e6df7102susnata    @Deprecated
274eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    public final void setInputEventHandler(InputEventHandler handler) {
275eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        mInputEventHandler = handler;
276eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
277eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
278eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
279eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Returns the input event handler.
280eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
281afd999aba1b74d876ea2620775ba9157e6df7102susnata    @Deprecated
2822dfed05c8ab53ca7c28424c9c03b1a87b9b7ca0dCraig Stout    public final InputEventHandler getInputEventHandler() {
283afd999aba1b74d876ea2620775ba9157e6df7102susnata        return (InputEventHandler)mInputEventHandler;
284afd999aba1b74d876ea2620775ba9157e6df7102susnata    }
285afd999aba1b74d876ea2620775ba9157e6df7102susnata
286afd999aba1b74d876ea2620775ba9157e6df7102susnata    /**
287afd999aba1b74d876ea2620775ba9157e6df7102susnata     * Sets the input event handler.
288afd999aba1b74d876ea2620775ba9157e6df7102susnata     */
289afd999aba1b74d876ea2620775ba9157e6df7102susnata    public final void setEventHandler(PlaybackControlGlue.InputEventHandler handler) {
290afd999aba1b74d876ea2620775ba9157e6df7102susnata        mInputEventHandler = handler;
291afd999aba1b74d876ea2620775ba9157e6df7102susnata    }
292afd999aba1b74d876ea2620775ba9157e6df7102susnata
293afd999aba1b74d876ea2620775ba9157e6df7102susnata    /**
294afd999aba1b74d876ea2620775ba9157e6df7102susnata     * Returns the input event handler.
295afd999aba1b74d876ea2620775ba9157e6df7102susnata     */
296afd999aba1b74d876ea2620775ba9157e6df7102susnata    public final PlaybackControlGlue.InputEventHandler getEventHandler() {
297eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        return mInputEventHandler;
298eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
299eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
300eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
301372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * Tickles the playback controls.  Fades in the view if it was faded out,
302372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * otherwise resets the fade out timer.  Tickling on input events is handled
303372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     * by the fragment.
304372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout     */
305372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void tickle() {
306372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "tickle enabled " + mFadingEnabled + " isResumed " + isResumed());
307372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (!mFadingEnabled || !isResumed()) {
308372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
309372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
310b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu        if (sHandler.hasMessages(START_FADE_OUT, mFragmentReference)) {
311372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            // Restart the timer
312372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            startFadeTimer();
313372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        } else {
314372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
315372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
316372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
317372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
31891e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    /**
31991e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     * Fades out the playback overlay immediately.
32091e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     */
32191e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    public void fadeOut() {
322b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu        sHandler.removeMessages(START_FADE_OUT, mFragmentReference);
32391e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        fade(false);
32491e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    }
32591e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang
32660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout    private boolean areControlsHidden() {
32760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        return mFadingStatus == IDLE && mBgAlpha == 0;
328cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    }
329cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout
33099ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    boolean onInterceptInputEvent(InputEvent event) {
33160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        final boolean controlsHidden = areControlsHidden();
33260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (DEBUG) Log.v(TAG, "onInterceptInputEvent hidden " + controlsHidden + " " + event);
33360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        boolean consumeEvent = false;
334c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        int keyCode = KeyEvent.KEYCODE_UNKNOWN;
335c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout
33660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (mInputEventHandler != null) {
33760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            consumeEvent = mInputEventHandler.handleInputEvent(event);
33860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        }
339cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (event instanceof KeyEvent) {
340c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout            keyCode = ((KeyEvent) event).getKeyCode();
341c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        }
34260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout
34360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        switch (keyCode) {
34460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_CENTER:
34560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_DOWN:
34660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_UP:
34760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_LEFT:
34860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_RIGHT:
34960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // Event may be consumed; regardless, if controls are hidden then these keys will
35060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // bring up the controls.
35160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (controlsHidden) {
35260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
35360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
354cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout                tickle();
35560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
35660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_BACK:
357c89266e21f0269aecd5df2dc2a39f6f0cf11a58eCraig Stout            case KeyEvent.KEYCODE_ESCAPE:
35860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // If fading enabled and controls are not hidden, back will be consumed to fade
35960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // them out (even if the key was consumed by the handler).
36060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (mFadingEnabled && !controlsHidden) {
36160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
362b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                    sHandler.removeMessages(START_FADE_OUT, mFragmentReference);
36360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    fade(false);
36460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                } else if (consumeEvent) {
36560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
36660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
36760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
36860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            default:
36960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (consumeEvent) {
37060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
37160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
372eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        }
373372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        return consumeEvent;
374372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
375372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
376372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    @Override
377372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    public void onResume() {
378372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        super.onResume();
379372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (mFadingEnabled) {
380d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            setBgAlpha(0);
381372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            fade(true);
382372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
383372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnTouchInterceptListener(mOnTouchInterceptListener);
384372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener);
385372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
386372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
38799ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void startFadeTimer() {
388b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu        sHandler.removeMessages(START_FADE_OUT, mFragmentReference);
389b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu        sHandler.sendMessageDelayed(sHandler.obtainMessage(START_FADE_OUT, mFragmentReference),
390b655650666d7bd317c41c7a5be229e3a80dd2692Dake Gu                mShowTimeMs);
391372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
392372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
393d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private static ValueAnimator loadAnimator(Context context, int resId) {
394d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(context, resId);
395d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        animator.setDuration(animator.getDuration() * ANIMATION_MULTIPLIER);
396d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        return animator;
397d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
398d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
399d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadBgAnimator() {
400d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
401d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
402d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
403d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                setBgAlpha((Integer) arg0.getAnimatedValue());
404d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
405d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
406d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
407d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_in);
408d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addUpdateListener(listener);
409d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeInAnimator.addListener(mFadeListener);
410d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
411d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_out);
412d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addUpdateListener(listener);
413d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgFadeOutAnimator.addListener(mFadeListener);
414d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
415d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
416d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100,0);
417d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private TimeInterpolator mLogAccelerateInterpolator = new LogAccelerateInterpolator(100,0);
418d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
41999ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    View getControlRowView() {
4202d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (getVerticalGridView() == null) {
4212d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
4222d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
4232d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        RecyclerView.ViewHolder vh = getVerticalGridView().findViewHolderForPosition(0);
4242d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        if (vh == null) {
4252d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            return null;
4262d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
4272d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        return vh.itemView;
4282d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    }
4292d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
430d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadControlRowAnimator() {
4312d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
432d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
4332d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
4342d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
4352d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
4362d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    views.add(view);
4371e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
4382d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
4392d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
4402d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
4412d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
4422d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4432d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                View view = getControlRowView();
4442d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                if (view != null) {
445d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    final float fraction = (Float) arg0.getAnimatedValue();
446d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (DEBUG) Log.v(TAG, "fraction " + fraction);
4472d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setAlpha(fraction);
4482d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
449d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
450d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
451d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
452d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
453d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator = loadAnimator(
454d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
4552d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addUpdateListener(updateListener);
4562d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeInAnimator.addListener(listener);
457d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
458d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
459d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator = loadAnimator(
460d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
4612d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addUpdateListener(updateListener);
4622d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mControlRowFadeOutAnimator.addListener(listener);
463d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mControlRowFadeOutAnimator.setInterpolator(mLogAccelerateInterpolator);
464d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
465d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
466d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private void loadOtherRowAnimator() {
4672d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorListener listener = new AnimatorListener() {
468d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            @Override
4692d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            void getViews(ArrayList<View> views) {
4701e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                if (getVerticalGridView() == null) {
4711e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                    return;
4721e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout                }
473d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                final int count = getVerticalGridView().getChildCount();
474d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                for (int i = 0; i < count; i++) {
475d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    View view = getVerticalGridView().getChildAt(i);
4762d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    if (view != null) {
4772d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                        views.add(view);
4782d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                    }
4792d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                }
4802d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
4812d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        };
4822d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
4832d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            @Override
4842d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
4851df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                if (getVerticalGridView() == null) {
4861df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                    return;
4871df1f18de496764a0c922053e601d1b6d6d3f31cCraig Stout                }
4882d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                final float fraction = (Float) arg0.getAnimatedValue();
4892d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                for (View view : listener.mViews) {
490d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    if (getVerticalGridView().getChildPosition(view) > 0) {
491d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                        view.setAlpha(fraction);
4926b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
493d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                    }
494d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                }
495d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
496d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        };
497d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
498d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator = loadAnimator(
499d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_in);
5002d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addListener(listener);
5012d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeInAnimator.addUpdateListener(updateListener);
502d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
503d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
504d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mOtherRowFadeOutAnimator = loadAnimator(
505d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                getActivity(), R.animator.lb_playback_controls_fade_out);
5062d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addListener(listener);
5072d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        mOtherRowFadeOutAnimator.addUpdateListener(updateListener);
5086b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mOtherRowFadeOutAnimator.setInterpolator(new AccelerateInterpolator());
5096b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    }
5106b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
5116b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout    private void loadDescriptionAnimator() {
5126b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
5136b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            @Override
5146b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            public void onAnimationUpdate(ValueAnimator arg0) {
5156b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (getVerticalGridView() == null) {
5166b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    return;
5176b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
5186b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                ItemBridgeAdapter.ViewHolder adapterVh = (ItemBridgeAdapter.ViewHolder)
5196b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        getVerticalGridView().findViewHolderForPosition(0);
5206b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                if (adapterVh != null && adapterVh.getViewHolder()
5216b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                        instanceof PlaybackControlsRowPresenter.ViewHolder) {
5226b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                    final Presenter.ViewHolder vh = ((PlaybackControlsRowPresenter.ViewHolder)
5236b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                            adapterVh.getViewHolder()).mDescriptionViewHolder;
5248f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    if (vh != null) {
5258f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.view.setAlpha((Float) arg0.getAnimatedValue());
5268f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    }
5276b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                }
5286b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
5296b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        };
5306b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
5316b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator = loadAnimator(
5326b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_in);
5336b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.addUpdateListener(listener);
5346b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
5356b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout
5366b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator = loadAnimator(
5376b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getActivity(), R.animator.lb_playback_description_fade_out);
5386b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mDescriptionFadeOutAnimator.addUpdateListener(listener);
539d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    }
540d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
54199ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void fade(boolean fadeIn) {
542372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (DEBUG) Log.v(TAG, "fade " + fadeIn);
543372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if (getView() == null) {
544372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
545372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
546372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        if ((fadeIn && mFadingStatus == IN) || (!fadeIn && mFadingStatus == OUT)) {
547d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "requested fade in progress");
548d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            return;
549d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
550d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if ((fadeIn && mBgAlpha == 255) || (!fadeIn && mBgAlpha == 0)) {
551d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "fade is no-op");
552372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            return;
553372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        }
554372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout
5553103f63e99d47573823957f7aa34308555873221Aurimas Liutikas        mAnimationTranslateY = getVerticalGridView().getSelectedPosition() == 0
5563103f63e99d47573823957f7aa34308555873221Aurimas Liutikas                ? mMajorFadeTranslateY : mMinorFadeTranslateY;
557d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
558d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        if (mFadingStatus == IDLE) {
559d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
560d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.start();
561d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.start();
562d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.start();
5636b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.start();
564d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
565d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.start();
566d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.start();
567d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.start();
5686b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.start();
569d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
570d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        } else {
571d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (fadeIn) {
572d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeOutAnimator.reverse();
573d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeOutAnimator.reverse();
574d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeOutAnimator.reverse();
5756b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeOutAnimator.reverse();
576d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            } else {
577d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mBgFadeInAnimator.reverse();
578d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mControlRowFadeInAnimator.reverse();
579d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                mOtherRowFadeInAnimator.reverse();
5806b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                mDescriptionFadeInAnimator.reverse();
581d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
582d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
583d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
584d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // If fading in while control row is focused, set initial translationY so
585d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        // views slide in from below.
5866b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        if (fadeIn && mFadingStatus == IDLE) {
587d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            final int count = getVerticalGridView().getChildCount();
588d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            for (int i = 0; i < count; i++) {
5896b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getVerticalGridView().getChildAt(i).setTranslationY(mAnimationTranslateY);
590d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
591d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
592d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
593372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mFadingStatus = fadeIn ? IN : OUT;
594372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout    }
5957ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
5967ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    /**
5977ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     * Sets the list of rows for the fragment.
5987ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout     */
5997ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
6007ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void setAdapter(ObjectAdapter adapter) {
6016dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (getAdapter() != null) {
6026dca725412977bb56b933bdec120e31909233cdbCraig Stout            getAdapter().unregisterObserver(mObserver);
6036dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
6047ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.setAdapter(adapter);
6056dca725412977bb56b933bdec120e31909233cdbCraig Stout        if (adapter != null) {
6066dca725412977bb56b933bdec120e31909233cdbCraig Stout            adapter.registerObserver(mObserver);
6076dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
6087ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
6097ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
6107ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
6117ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    void setVerticalGridViewLayout(VerticalGridView listview) {
612d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (listview == null) {
6137ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout            return;
6147ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        }
615d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Padding affects alignment when last row is focused
616d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // (last is first when there's only one row).
6174fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        setPadding(listview, mPaddingTop, mPaddingBottom);
618d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
619d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Item alignment affects focused row that isn't the last.
6204fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setItemAlignmentOffset(0);
6214fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setItemAlignmentOffsetPercent(50);
622d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
623d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Push rows to the bottom.
6247ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        listview.setWindowAlignmentOffset(0);
6254fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setWindowAlignmentOffsetPercent(50);
6264fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE);
6277ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
6287ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
6294fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri    private static void setPadding(View view, int paddingTop, int paddingBottom) {
6304fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        view.setPadding(view.getPaddingLeft(), paddingTop,
6314fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri                view.getPaddingRight(), paddingBottom);
632d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
633d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
6347ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    @Override
6357ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    public void onCreate(Bundle savedInstanceState) {
6367ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout        super.onCreate(savedInstanceState);
6377ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout
6384fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        mPaddingTop =
6394fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_top);
640d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        mPaddingBottom =
641d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_bottom);
6427709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgDarkColor =
6437709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_dark);
6447709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mBgLightColor =
6457709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                getResources().getColor(R.color.lb_playback_controls_background_light);
646372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        mShowTimeMs =
647372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                getResources().getInteger(R.integer.lb_playback_controls_show_time_ms);
6486b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMajorFadeTranslateY =
6496b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_major_fade_translate_y);
6506b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        mMinorFadeTranslateY =
6516b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout                getResources().getDimensionPixelSize(R.dimen.lb_playback_minor_fade_translate_y);
652d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
653d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadBgAnimator();
654d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadControlRowAnimator();
655d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        loadOtherRowAnimator();
6566b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout        loadDescriptionAnimator();
6577709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6587709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6597709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
6607709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Sets the background type.
6617709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     *
6627709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * @param type One of BG_LIGHT, BG_DARK, or BG_NONE.
6637709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
6647709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public void setBackgroundType(int type) {
665372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        switch (type) {
666372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_LIGHT:
667372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_DARK:
668372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        case BG_NONE:
669372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            if (type != mBackgroundType) {
670372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                mBackgroundType = type;
671372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout                updateBackground();
672372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            }
673372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout            break;
674372d07bb41510d91a6a662a1906aceb0ee759481Craig Stout        default:
6757709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            throw new IllegalArgumentException("Invalid background type");
6767709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
6777709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6787709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6797709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    /**
6807709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     * Returns the background type.
6817709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout     */
6827709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public int getBackgroundType() {
6837709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mBackgroundType;
6847709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6857709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
6867709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    private void updateBackground() {
6877709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        if (mRootView != null) {
6887709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            int color = mBgDarkColor;
6897709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            switch (mBackgroundType) {
6907709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_DARK: break;
6917709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_LIGHT: color = mBgLightColor; break;
6927709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout                case BG_NONE: color = Color.TRANSPARENT; break;
6937709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            }
6947709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            mRootView.setBackground(new ColorDrawable(color));
6957709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        }
6967709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    }
6977709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout
69899ec8b0cb375f7e5577ea3ec9f09e6ff7a95de0dAurimas Liutikas    void updateControlsBottomSpace(ItemBridgeAdapter.ViewHolder vh) {
699d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        // Add extra space between rows 0 and 1
700d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh == null && getVerticalGridView() != null) {
701d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            vh = (ItemBridgeAdapter.ViewHolder)
702d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    getVerticalGridView().findViewHolderForPosition(0);
703d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
704d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        if (vh != null && vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
705d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            final int adapterSize = getAdapter() == null ? 0 : getAdapter().size();
706d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            ((PlaybackControlsRowPresenter) vh.getPresenter()).showBottomSpace(
707d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder(),
708d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                    adapterSize > 1);
709d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
710d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout    }
711d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout
712d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    private final ItemBridgeAdapter.AdapterListener mAdapterListener =
713d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            new ItemBridgeAdapter.AdapterListener() {
714d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
715d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) {
716d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onAttachedToWindow " + vh.getViewHolder().view);
717d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if ((mFadingStatus == IDLE && mBgAlpha == 0) || mFadingStatus == OUT) {
718d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                if (DEBUG) Log.v(TAG, "setting alpha to 0");
719d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout                vh.getViewHolder().view.setAlpha(0);
720d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            }
721aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            if (vh.getPosition() == 0 && mResetControlsToPrimaryActionsPending) {
722aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout                resetControlsToPrimaryActions(vh);
723aa67105babce5fb14e1f39b57d4c84ce634afa62Craig Stout            }
724d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
725d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        @Override
726d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) {
727d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            if (DEBUG) Log.v(TAG, "onDetachedFromWindow " + vh.getViewHolder().view);
728d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            // Reset animation state
729d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setAlpha(1f);
730d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout            vh.getViewHolder().view.setTranslationY(0);
7316b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            if (vh.getViewHolder() instanceof PlaybackControlsRowPresenter.ViewHolder) {
7328f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                Presenter.ViewHolder descriptionVh = ((PlaybackControlsRowPresenter.ViewHolder)
7338f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                        vh.getViewHolder()).mDescriptionViewHolder;
7348f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                if (descriptionVh != null) {
7358f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                    descriptionVh.view.setAlpha(1f);
7368f5c183ba7b9df6b5339586f51219b4d5e6305f3Craig Stout                }
7376b2e5b5117f1b8dfafbd81b995bb423ab0297564Craig Stout            }
738d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        }
739d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        @Override
740d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        public void onBind(ItemBridgeAdapter.ViewHolder vh) {
741d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            if (vh.getPosition() == 0) {
742d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout                updateControlsBottomSpace(vh);
743d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            }
744d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout        }
745d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout    };
746d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout
7477709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    @Override
7487709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout    public View onCreateView(LayoutInflater inflater, ViewGroup container,
7497709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout            Bundle savedInstanceState) {
7507709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        mRootView = super.onCreateView(inflater, container, savedInstanceState);
751d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        mBgAlpha = 255;
7527709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        updateBackground();
753d1adbdcb44a48e142d28a93189c57edfe62d93ceCraig Stout        getRowsFragment().setExternalAdapterListener(mAdapterListener);
7547709709c2c78490a21311e9950d5dca7e89a6aedCraig Stout        return mRootView;
7557ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout    }
7566dca725412977bb56b933bdec120e31909233cdbCraig Stout
7571e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    @Override
7581e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    public void onDestroyView() {
7591e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        mRootView = null;
7601e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout        super.onDestroyView();
7611e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout    }
7621e5725d52c7ec12b184dcfce6bfafa80aed35230Craig Stout
763fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu    @Override
764fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu    public void onStart() {
765fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu        super.onStart();
766fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu        // Workaround problem VideoView forcing itself to focused, let controls take focus.
767fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu        getRowsFragment().getView().requestFocus();
768fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu    }
769fd62284fa44d88adf06deee44f4d0114ba5dec45Dake Gu
7706dca725412977bb56b933bdec120e31909233cdbCraig Stout    private final DataObserver mObserver = new DataObserver() {
77115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
7726dca725412977bb56b933bdec120e31909233cdbCraig Stout        public void onChanged() {
773d20507e0f5ac7ad021f42ca87c294787246f0591Craig Stout            updateControlsBottomSpace(null);
7746dca725412977bb56b933bdec120e31909233cdbCraig Stout        }
7756dca725412977bb56b933bdec120e31909233cdbCraig Stout    };
7762d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
7772d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    static abstract class AnimatorListener implements Animator.AnimatorListener {
7782d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<View> mViews = new ArrayList<View>();
7792d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        ArrayList<Integer> mLayerType = new ArrayList<Integer>();
7802d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout
78115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
7822d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationCancel(Animator animation) {
7832d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
78415375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
7852d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationRepeat(Animator animation) {
7862d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
78715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
7882d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationStart(Animator animation) {
7892d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            getViews(mViews);
7902d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (View view : mViews) {
7912d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mLayerType.add(view.getLayerType());
7922d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
7932d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
7942d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
79515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas        @Override
7962d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        public void onAnimationEnd(Animator animation) {
7972d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            for (int i = 0; i < mViews.size(); i++) {
7982d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout                mViews.get(i).setLayerType(mLayerType.get(i), null);
7992d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            }
8002d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mLayerType.clear();
8012d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout            mViews.clear();
8022d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        }
8032d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout        abstract void getViews(ArrayList<View> views);
8044fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri
8052d33e3cfedc56adc2d4e5ac6279ec683d041fe21Craig Stout    };
8067ab1edf2b49f3cdcb9db7a1c60d0dc1e17a9aef7Craig Stout}
807