16193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu/* This file is auto-generated from PlaybackOverlayFragment.java.  DO NOT MODIFY. */
26193c12a1897723c87b41f4e304a8cd04deef2dcDake Gu
361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/*
461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Copyright (C) 2014 The Android Open Source Project
561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * in compliance with the License. You may obtain a copy of the License at
861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * http://www.apache.org/licenses/LICENSE-2.0
1061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu *
1161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * Unless required by applicable law or agreed to in writing, software distributed under the License
1261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
1361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * or implied. See the License for the specific language governing permissions and limitations under
1461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * the License.
1561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
1661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupackage android.support.v17.leanback.app;
1761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.Color;
1961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.graphics.drawable.ColorDrawable;
2061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.Animator;
2161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.AnimatorInflater;
2261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.TimeInterpolator;
2361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.ValueAnimator;
2460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.support.v17.leanback.widget.Action;
2560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stoutimport android.support.v17.leanback.widget.PlaybackControlsRow;
26cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stoutimport android.view.InputEvent;
2761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.animation.AccelerateInterpolator;
2861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.animation.ValueAnimator.AnimatorUpdateListener;
2961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.content.Context;
3061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Bundle;
3161905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Handler;
3261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.os.Message;
3361905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v7.widget.RecyclerView;
3461905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.R;
3561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.animation.LogAccelerateInterpolator;
3661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.animation.LogDecelerateInterpolator;
3761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ItemBridgeAdapter;
3861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ObjectAdapter;
3961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.ObjectAdapter.DataObserver;
4061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
4122eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.Presenter;
4222eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.PresenterSelector;
4322eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.RowPresenter;
4422eaa9441bf3a521bfafb160674ff2da421eded8Dake Guimport android.support.v17.leanback.widget.VerticalGridView;
4561905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.util.Log;
4661905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.KeyEvent;
4761905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.LayoutInflater;
4861905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.MotionEvent;
4961905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.View;
5061905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport android.view.ViewGroup;
5161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5261905b0b52c50018dcaebcd79699c39b8f28d622Dake Guimport java.util.ArrayList;
5361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
5461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu/**
5561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * A fragment for displaying playback controls and related content.
56a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
57a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * A PlaybackOverlaySupportFragment renders the elements of its {@link ObjectAdapter} as a set
5822eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of rows in a vertical list.  The Adapter's {@link PresenterSelector} must maintain subclasses
5922eaa9441bf3a521bfafb160674ff2da421eded8Dake Gu * of {@link RowPresenter}.
60a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
61a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * <p>
62a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * An instance of {@link android.support.v17.leanback.widget.PlaybackControlsRow} is expected to be
6361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu * at position 0 in the adapter.
64a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * </p>
6561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu */
6661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gupublic class PlaybackOverlaySupportFragment extends DetailsSupportFragment {
6761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
6961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * No background.
7061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
7161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int BG_NONE = 0;
7261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
7461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * A dark translucent background.
7561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
7661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int BG_DARK = 1;
7761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
7861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
7961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * A light translucent background.
8061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
8161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static final int BG_LIGHT = 2;
8261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
83a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
84a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Listener allowing the application to receive notification of fade in and/or fade out
85a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * completion events.
86a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
8761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public static class OnFadeCompleteListener {
8861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onFadeInComplete() {
8961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onFadeOutComplete() {
9161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
9261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
9361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
94a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout    /**
95a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     * Interface allowing the application to handle input events.
96a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout     */
97eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    public interface InputEventHandler {
98eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        /**
99eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * Called when an {@link InputEvent} is received.
100eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         *
101eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * @return If the event should be consumed, return true. To allow the event to
102eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         * continue on to the next handler, return false.
103eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout         */
104eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        public boolean handleInputEvent(InputEvent event);
105eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
106eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
10761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final String TAG = "PlaybackOverlaySupportFragment";
10861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final boolean DEBUG = false;
10961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final int ANIMATION_MULTIPLIER = 1;
11061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static int START_FADE_OUT = 1;
11261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
11361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    // Fading status
11461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final int IDLE = 0;
11561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final int IN = 1;
11661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static final int OUT = 2;
11761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
1184fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri    private int mPaddingTop;
11961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mPaddingBottom;
12061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private View mRootView;
12161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBackgroundType = BG_DARK;
12261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBgDarkColor;
12361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBgLightColor;
12461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mShowTimeMs;
12561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mMajorFadeTranslateY, mMinorFadeTranslateY;
12661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mAnimationTranslateY;
12761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private OnFadeCompleteListener mFadeCompleteListener;
128eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    private InputEventHandler mInputEventHandler;
12961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mFadingEnabled = true;
13061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mFadingStatus = IDLE;
13161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private int mBgAlpha;
13261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ValueAnimator mBgFadeInAnimator, mBgFadeOutAnimator;
13361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ValueAnimator mControlRowFadeInAnimator, mControlRowFadeOutAnimator;
13461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ValueAnimator mDescriptionFadeInAnimator, mDescriptionFadeOutAnimator;
13561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private ValueAnimator mOtherRowFadeInAnimator, mOtherRowFadeOutAnimator;
13661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mTranslateAnimationEnabled;
13761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private boolean mResetControlsToPrimaryActionsPending;
13861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private RecyclerView.ItemAnimator mItemAnimator;
13961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
14061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final Animator.AnimatorListener mFadeListener =
14161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new Animator.AnimatorListener() {
14261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
14361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationStart(Animator animation) {
14461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            enableVerticalGridAnimations(false);
14561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
14661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
14761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationRepeat(Animator animation) {
14861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
14961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
15061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationCancel(Animator animation) {
15161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
15261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
15361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationEnd(Animator animation) {
15461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onAnimationEnd " + mBgAlpha);
15561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (mBgAlpha > 0) {
15661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                enableVerticalGridAnimations(true);
15761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                startFadeTimer();
15861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mFadeCompleteListener != null) {
15961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mFadeCompleteListener.onFadeInComplete();
16061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
16161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
162794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                VerticalGridView verticalView = getVerticalGridView();
163794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                // reset focus to the primary actions only if the selected row was the controls row
164794711994b16b276a7d952303a90fd4da2288362Keyvan Amiri                if (verticalView != null && verticalView.getSelectedPosition() == 0) {
16561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    resetControlsToPrimaryActions(null);
16661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
16761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (mFadeCompleteListener != null) {
16861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    mFadeCompleteListener.onFadeOutComplete();
16961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
17061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
17161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mFadingStatus = IDLE;
17261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
17361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
17461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
17561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final Handler mHandler = new Handler() {
17661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
17761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void handleMessage(Message message) {
17861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (message.what == START_FADE_OUT && mFadingEnabled) {
17961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                fade(false);
18061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
18161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
18261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
18361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
18461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final VerticalGridView.OnTouchInterceptListener mOnTouchInterceptListener =
18561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new VerticalGridView.OnTouchInterceptListener() {
18661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onInterceptTouchEvent(MotionEvent event) {
187cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
18861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
18961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
19061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
19161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final VerticalGridView.OnKeyInterceptListener mOnKeyInterceptListener =
19261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new VerticalGridView.OnKeyInterceptListener() {
19361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public boolean onInterceptKeyEvent(KeyEvent event) {
194cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout            return onInterceptInputEvent(event);
19561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
19661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
19761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
19861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void setBgAlpha(int alpha) {
19961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgAlpha = alpha;
20061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRootView != null) {
20161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRootView.getBackground().setAlpha(alpha);
20261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
20361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
20461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
20561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void enableVerticalGridAnimations(boolean enable) {
20661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getVerticalGridView() != null) {
20761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getVerticalGridView().setAnimateChildLayout(enable);
20861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
20961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
21061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
21161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void resetControlsToPrimaryActions(ItemBridgeAdapter.ViewHolder vh) {
21261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (vh == null && getVerticalGridView() != null) {
21361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            vh = (ItemBridgeAdapter.ViewHolder) getVerticalGridView().findViewHolderForPosition(0);
21461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
21561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (vh == null) {
21661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mResetControlsToPrimaryActionsPending = true;
21761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else if (vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
21861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mResetControlsToPrimaryActionsPending = false;
21961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            ((PlaybackControlsRowPresenter) vh.getPresenter()).showPrimaryActions(
22061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder());
22161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
22261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
22361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
22461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
22561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Enables or disables view fading.  If enabled,
22661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * the view will be faded in when the fragment starts,
22761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * and will fade out after a time period.  The timeout
22861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * period is reset each time {@link #tickle} is called.
22961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
23061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
23161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setFadingEnabled(boolean enabled) {
23261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "setFadingEnabled " + enabled);
23361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (enabled != mFadingEnabled) {
23461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mFadingEnabled = enabled;
235f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            if (mFadingEnabled) {
236f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                if (isResumed() && mFadingStatus == IDLE
237f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                        && !mHandler.hasMessages(START_FADE_OUT)) {
238f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                    startFadeTimer();
23961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
240f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout            } else {
241f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                // Ensure fully opaque
242f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                mHandler.removeMessages(START_FADE_OUT);
243f47fb1e34efd538c322f7539893272ba847cdbdcCraig Stout                fade(true);
24461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
24561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
24661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
24761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
24861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
24961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns true if view fading is enabled.
25061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
25161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public boolean isFadingEnabled() {
25261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mFadingEnabled;
25361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
25461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
25561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
25661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the listener to be called when fade in or out has completed.
25761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
25861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setFadeCompleteListener(OnFadeCompleteListener listener) {
25961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mFadeCompleteListener = listener;
26061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
26161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
26261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
26361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the listener to be called when fade in or out has completed.
26461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
26561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public OnFadeCompleteListener getFadeCompleteListener() {
26661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mFadeCompleteListener;
26761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
26861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
26961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
270eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Sets the input event handler.
271eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
272eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    public final void setInputEventHandler(InputEventHandler handler) {
273eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        mInputEventHandler = handler;
274eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
275eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
276eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
277eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     * Returns the input event handler.
278eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout     */
2792dfed05c8ab53ca7c28424c9c03b1a87b9b7ca0dCraig Stout    public final InputEventHandler getInputEventHandler() {
280eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout        return mInputEventHandler;
281eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    }
282eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout
283eb66dab544c4c1eabe4d469b7cea348d4b01e664Craig Stout    /**
28461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Tickles the playback controls.  Fades in the view if it was faded out,
28561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * otherwise resets the fade out timer.  Tickling on input events is handled
28661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * by the fragment.
28761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
28861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void tickle() {
28961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "tickle enabled " + mFadingEnabled + " isResumed " + isResumed());
29061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (!mFadingEnabled || !isResumed()) {
29161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
29261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
29361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHandler.hasMessages(START_FADE_OUT)) {
29461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Restart the timer
29561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            startFadeTimer();
29661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
29761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            fade(true);
29861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
29961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
30061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
30191e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    /**
30291e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     * Fades out the playback overlay immediately.
30391e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang     */
30491e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    public void fadeOut() {
30591e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        mHandler.removeMessages(START_FADE_OUT);
30691e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang        fade(false);
30791e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang    }
30891e100e4450b6101a674d8a3ab15e426fc5294bcDongwon Kang
30960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout    private boolean areControlsHidden() {
31060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        return mFadingStatus == IDLE && mBgAlpha == 0;
311cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    }
312cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout
313cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout    private boolean onInterceptInputEvent(InputEvent event) {
31460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        final boolean controlsHidden = areControlsHidden();
31560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (DEBUG) Log.v(TAG, "onInterceptInputEvent hidden " + controlsHidden + " " + event);
31660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        boolean consumeEvent = false;
317c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        int keyCode = KeyEvent.KEYCODE_UNKNOWN;
318c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout
31960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        if (mInputEventHandler != null) {
32060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            consumeEvent = mInputEventHandler.handleInputEvent(event);
32160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        }
322cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        if (event instanceof KeyEvent) {
323c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout            keyCode = ((KeyEvent) event).getKeyCode();
324c92c356de1a687598a031f3452053dc6c9af9b77Craig Stout        }
32560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout
32660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout        switch (keyCode) {
32760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_CENTER:
32860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_DOWN:
32960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_UP:
33060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_LEFT:
33160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_DPAD_RIGHT:
33260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // Event may be consumed; regardless, if controls are hidden then these keys will
33360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // bring up the controls.
33460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (controlsHidden) {
33560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
33660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
337cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout                tickle();
33860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
33960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            case KeyEvent.KEYCODE_BACK:
340c89266e21f0269aecd5df2dc2a39f6f0cf11a58eCraig Stout            case KeyEvent.KEYCODE_ESCAPE:
34160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // If fading enabled and controls are not hidden, back will be consumed to fade
34260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                // them out (even if the key was consumed by the handler).
34360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (mFadingEnabled && !controlsHidden) {
34460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    consumeEvent = true;
34560bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    mHandler.removeMessages(START_FADE_OUT);
34660bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    fade(false);
34760bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                } else if (consumeEvent) {
34860bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
34960bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
35060bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                break;
35160bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout            default:
35260bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                if (consumeEvent) {
35360bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                    tickle();
35460bb6af2e336072921f5d3c3861e86b3cc6241b3Craig Stout                }
355cbfc318baee2fc054af4c723bfac0fd3c28a1667Craig Stout        }
35661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return consumeEvent;
35761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
35861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
35961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
36061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onResume() {
36161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onResume();
36261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mFadingEnabled) {
36361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            setBgAlpha(0);
36461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            fade(true);
36561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
36661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        getVerticalGridView().setOnTouchInterceptListener(mOnTouchInterceptListener);
36761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        getVerticalGridView().setOnKeyInterceptListener(mOnKeyInterceptListener);
36861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
36961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void startFadeTimer() {
37161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mHandler != null) {
37261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHandler.removeMessages(START_FADE_OUT);
37361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mHandler.sendEmptyMessageDelayed(START_FADE_OUT, mShowTimeMs);
37461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
37561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
37661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
37761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private static ValueAnimator loadAnimator(Context context, int resId) {
37861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(context, resId);
37961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        animator.setDuration(animator.getDuration() * ANIMATION_MULTIPLIER);
38061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return animator;
38161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
38261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
38361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void loadBgAnimator() {
38461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
38561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
38661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onAnimationUpdate(ValueAnimator arg0) {
38761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                setBgAlpha((Integer) arg0.getAnimatedValue());
38861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
38961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
39061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeInAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_in);
39261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeInAnimator.addUpdateListener(listener);
39361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeInAnimator.addListener(mFadeListener);
39461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
39561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeOutAnimator = loadAnimator(getActivity(), R.animator.lb_playback_bg_fade_out);
39661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeOutAnimator.addUpdateListener(listener);
39761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgFadeOutAnimator.addListener(mFadeListener);
39861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
39961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private TimeInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100,0);
40161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private TimeInterpolator mLogAccelerateInterpolator = new LogAccelerateInterpolator(100,0);
40261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
40361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private View getControlRowView() {
40461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getVerticalGridView() == null) {
40561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return null;
40661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
40761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        RecyclerView.ViewHolder vh = getVerticalGridView().findViewHolderForPosition(0);
40861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (vh == null) {
40961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return null;
41061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
41161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return vh.itemView;
41261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
41361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
41461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void loadControlRowAnimator() {
41561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final AnimatorListener listener = new AnimatorListener() {
41661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
41761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            void getViews(ArrayList<View> views) {
41861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                View view = getControlRowView();
41961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (view != null) {
42061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    views.add(view);
42161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
42261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
42361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
42461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
42561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
42661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onAnimationUpdate(ValueAnimator arg0) {
42761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                View view = getControlRowView();
42861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (view != null) {
42961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    final float fraction = (Float) arg0.getAnimatedValue();
43061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (DEBUG) Log.v(TAG, "fraction " + fraction);
43161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    view.setAlpha(fraction);
43261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
43361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
43461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
43561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
43661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
43761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeInAnimator = loadAnimator(
43861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_controls_fade_in);
43961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeInAnimator.addUpdateListener(updateListener);
44061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeInAnimator.addListener(listener);
44161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
44261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
44361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeOutAnimator = loadAnimator(
44461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_controls_fade_out);
44561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeOutAnimator.addUpdateListener(updateListener);
44661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeOutAnimator.addListener(listener);
44761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mControlRowFadeOutAnimator.setInterpolator(mLogAccelerateInterpolator);
44861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
44961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
45061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void loadOtherRowAnimator() {
45161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final AnimatorListener listener = new AnimatorListener() {
45261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
45361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            void getViews(ArrayList<View> views) {
45461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (getVerticalGridView() == null) {
45561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return;
45661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
45761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                final int count = getVerticalGridView().getChildCount();
45861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                for (int i = 0; i < count; i++) {
45961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    View view = getVerticalGridView().getChildAt(i);
46061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (view != null) {
46161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        views.add(view);
46261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
46361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
46461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
46561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
46661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        final AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
46761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
46861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onAnimationUpdate(ValueAnimator arg0) {
469db14dd5106afde6a39ae26448df2b81b536ebc2bCraig Stout                if (getVerticalGridView() == null) {
470db14dd5106afde6a39ae26448df2b81b536ebc2bCraig Stout                    return;
471db14dd5106afde6a39ae26448df2b81b536ebc2bCraig Stout                }
47261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                final float fraction = (Float) arg0.getAnimatedValue();
47361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                for (View view : listener.mViews) {
47461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (getVerticalGridView().getChildPosition(view) > 0) {
47561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        view.setAlpha(fraction);
47661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        view.setTranslationY((float) mAnimationTranslateY * (1f - fraction));
47761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
47861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
47961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
48061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
48161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
48261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeInAnimator = loadAnimator(
48361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_controls_fade_in);
48461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeInAnimator.addListener(listener);
48561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeInAnimator.addUpdateListener(updateListener);
48661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
48761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
48861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeOutAnimator = loadAnimator(
48961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_controls_fade_out);
49061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeOutAnimator.addListener(listener);
49161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeOutAnimator.addUpdateListener(updateListener);
49261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mOtherRowFadeOutAnimator.setInterpolator(new AccelerateInterpolator());
49361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
49461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
49561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void loadDescriptionAnimator() {
49661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        AnimatorUpdateListener listener = new AnimatorUpdateListener() {
49761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            @Override
49861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            public void onAnimationUpdate(ValueAnimator arg0) {
49961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (getVerticalGridView() == null) {
50061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    return;
50161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
50261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                ItemBridgeAdapter.ViewHolder adapterVh = (ItemBridgeAdapter.ViewHolder)
50361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        getVerticalGridView().findViewHolderForPosition(0);
50461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (adapterVh != null && adapterVh.getViewHolder()
50561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        instanceof PlaybackControlsRowPresenter.ViewHolder) {
50661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    final Presenter.ViewHolder vh = ((PlaybackControlsRowPresenter.ViewHolder)
50761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                            adapterVh.getViewHolder()).mDescriptionViewHolder;
50861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    if (vh != null) {
50961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        vh.view.setAlpha((Float) arg0.getAnimatedValue());
51061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    }
51161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
51261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
51361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        };
51461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
51561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mDescriptionFadeInAnimator = loadAnimator(
51661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_description_fade_in);
51761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mDescriptionFadeInAnimator.addUpdateListener(listener);
51861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mDescriptionFadeInAnimator.setInterpolator(mLogDecelerateInterpolator);
51961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mDescriptionFadeOutAnimator = loadAnimator(
52161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getActivity(), R.animator.lb_playback_description_fade_out);
52261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mDescriptionFadeOutAnimator.addUpdateListener(listener);
52361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
52461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
52561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void fade(boolean fadeIn) {
52661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (DEBUG) Log.v(TAG, "fade " + fadeIn);
52761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getView() == null) {
52861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
52961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
53061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if ((fadeIn && mFadingStatus == IN) || (!fadeIn && mFadingStatus == OUT)) {
53161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "requested fade in progress");
53261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
53361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
53461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if ((fadeIn && mBgAlpha == 255) || (!fadeIn && mBgAlpha == 0)) {
53561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "fade is no-op");
53661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
53761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
53861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
53961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mAnimationTranslateY = getVerticalGridView().getSelectedPosition() == 0 ?
54061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mMajorFadeTranslateY : mMinorFadeTranslateY;
54161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
54261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mFadingStatus == IDLE) {
54361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (fadeIn) {
54461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mBgFadeInAnimator.start();
54561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mControlRowFadeInAnimator.start();
54661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mOtherRowFadeInAnimator.start();
54761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mDescriptionFadeInAnimator.start();
54861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
54961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mBgFadeOutAnimator.start();
55061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mControlRowFadeOutAnimator.start();
55161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mOtherRowFadeOutAnimator.start();
55261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mDescriptionFadeOutAnimator.start();
55361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
55461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        } else {
55561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (fadeIn) {
55661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mBgFadeOutAnimator.reverse();
55761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mControlRowFadeOutAnimator.reverse();
55861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mOtherRowFadeOutAnimator.reverse();
55961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mDescriptionFadeOutAnimator.reverse();
56061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            } else {
56161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mBgFadeInAnimator.reverse();
56261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mControlRowFadeInAnimator.reverse();
56361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mOtherRowFadeInAnimator.reverse();
56461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mDescriptionFadeInAnimator.reverse();
56561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
56661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
56761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
56861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // If fading in while control row is focused, set initial translationY so
56961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // views slide in from below.
57061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (fadeIn && mFadingStatus == IDLE) {
57161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int count = getVerticalGridView().getChildCount();
57261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < count; i++) {
57361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getVerticalGridView().getChildAt(i).setTranslationY(mAnimationTranslateY);
57461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
57561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
57661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
57761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mFadingStatus = fadeIn ? IN : OUT;
57861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
57961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
58061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
58161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the list of rows for the fragment.
58261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
58361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
58461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setAdapter(ObjectAdapter adapter) {
58561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (getAdapter() != null) {
58661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getAdapter().unregisterObserver(mObserver);
58761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
58861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.setAdapter(adapter);
58961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (adapter != null) {
59061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            adapter.registerObserver(mObserver);
59161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
59361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
59461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
59561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    void setVerticalGridViewLayout(VerticalGridView listview) {
59661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (listview == null) {
59761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            return;
59861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
59961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Padding affects alignment when last row is focused
60061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // (last is first when there's only one row).
6014fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        setPadding(listview, mPaddingTop, mPaddingBottom);
60261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Item alignment affects focused row that isn't the last.
6044fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setItemAlignmentOffset(0);
6054fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setItemAlignmentOffsetPercent(50);
60661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
60761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Push rows to the bottom.
60861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        listview.setWindowAlignmentOffset(0);
6094fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setWindowAlignmentOffsetPercent(50);
6104fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        listview.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE);
61161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
61261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6134fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri    private static void setPadding(View view, int paddingTop, int paddingBottom) {
6144fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        view.setPadding(view.getPaddingLeft(), paddingTop,
6154fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri                view.getPaddingRight(), paddingBottom);
61661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
61761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
61861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
61961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onCreate(Bundle savedInstanceState) {
62061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onCreate(savedInstanceState);
62161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
6224fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri        mPaddingTop =
6234fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_top);
62461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mPaddingBottom =
62561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getDimensionPixelSize(R.dimen.lb_playback_controls_padding_bottom);
62661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgDarkColor =
62761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getColor(R.color.lb_playback_controls_background_dark);
62861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgLightColor =
62961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getColor(R.color.lb_playback_controls_background_light);
63061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mShowTimeMs =
63161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getInteger(R.integer.lb_playback_controls_show_time_ms);
63261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mMajorFadeTranslateY =
63361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getDimensionPixelSize(R.dimen.lb_playback_major_fade_translate_y);
63461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mMinorFadeTranslateY =
63561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                getResources().getDimensionPixelSize(R.dimen.lb_playback_minor_fade_translate_y);
63661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
63761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        loadBgAnimator();
63861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        loadControlRowAnimator();
63961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        loadOtherRowAnimator();
64061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        loadDescriptionAnimator();
64161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
64261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
64361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
64461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Sets the background type.
64561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     *
64661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * @param type One of BG_LIGHT, BG_DARK, or BG_NONE.
64761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
64861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void setBackgroundType(int type) {
64961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        switch (type) {
65061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        case BG_LIGHT:
65161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        case BG_DARK:
65261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        case BG_NONE:
65361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (type != mBackgroundType) {
65461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mBackgroundType = type;
65561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                updateBackground();
65661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
65761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            break;
65861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        default:
65961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            throw new IllegalArgumentException("Invalid background type");
66061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
66161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
66261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
66361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    /**
66461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     * Returns the background type.
66561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu     */
66661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public int getBackgroundType() {
66761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mBackgroundType;
66861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
66961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
67061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void updateBackground() {
67161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (mRootView != null) {
67261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            int color = mBgDarkColor;
67361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            switch (mBackgroundType) {
67461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case BG_DARK: break;
67561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case BG_LIGHT: color = mBgLightColor; break;
67661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                case BG_NONE: color = Color.TRANSPARENT; break;
67761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
67861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mRootView.setBackground(new ColorDrawable(color));
67961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
68061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
68161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
68261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private void updateControlsBottomSpace(ItemBridgeAdapter.ViewHolder vh) {
68361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        // Add extra space between rows 0 and 1
68461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (vh == null && getVerticalGridView() != null) {
68561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            vh = (ItemBridgeAdapter.ViewHolder)
68661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    getVerticalGridView().findViewHolderForPosition(0);
68761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
68861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        if (vh != null && vh.getPresenter() instanceof PlaybackControlsRowPresenter) {
68961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            final int adapterSize = getAdapter() == null ? 0 : getAdapter().size();
69061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            ((PlaybackControlsRowPresenter) vh.getPresenter()).showBottomSpace(
69161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    (PlaybackControlsRowPresenter.ViewHolder) vh.getViewHolder(),
69261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    adapterSize > 1);
69361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
69461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
69561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
69661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final ItemBridgeAdapter.AdapterListener mAdapterListener =
69761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            new ItemBridgeAdapter.AdapterListener() {
69861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
69961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAttachedToWindow(ItemBridgeAdapter.ViewHolder vh) {
70061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onAttachedToWindow " + vh.getViewHolder().view);
70161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if ((mFadingStatus == IDLE && mBgAlpha == 0) || mFadingStatus == OUT) {
70261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (DEBUG) Log.v(TAG, "setting alpha to 0");
70361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                vh.getViewHolder().view.setAlpha(0);
70461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
70561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (vh.getPosition() == 0 && mResetControlsToPrimaryActionsPending) {
70661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                resetControlsToPrimaryActions(vh);
70761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
70861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
70961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
71061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onDetachedFromWindow(ItemBridgeAdapter.ViewHolder vh) {
71161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (DEBUG) Log.v(TAG, "onDetachedFromWindow " + vh.getViewHolder().view);
71261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            // Reset animation state
71361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            vh.getViewHolder().view.setAlpha(1f);
71461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            vh.getViewHolder().view.setTranslationY(0);
71561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (vh.getViewHolder() instanceof PlaybackControlsRowPresenter.ViewHolder) {
71661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                Presenter.ViewHolder descriptionVh = ((PlaybackControlsRowPresenter.ViewHolder)
71761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                        vh.getViewHolder()).mDescriptionViewHolder;
71861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                if (descriptionVh != null) {
71961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                    descriptionVh.view.setAlpha(1f);
72061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                }
72161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
72261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
72361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        @Override
72461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onBind(ItemBridgeAdapter.ViewHolder vh) {
72561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            if (vh.getPosition() == 0) {
72661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                updateControlsBottomSpace(vh);
72761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
72861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
72961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
73061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
73161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
73261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public View onCreateView(LayoutInflater inflater, ViewGroup container,
73361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            Bundle savedInstanceState) {
73461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRootView = super.onCreateView(inflater, container, savedInstanceState);
73561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mBgAlpha = 255;
73661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        updateBackground();
73761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        getRowsSupportFragment().setExternalAdapterListener(mAdapterListener);
73861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        return mRootView;
73961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
74061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
74161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    @Override
74261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    public void onDestroyView() {
74361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        mRootView = null;
74461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        super.onDestroyView();
74561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    }
74661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
74761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    private final DataObserver mObserver = new DataObserver() {
74861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onChanged() {
74961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            updateControlsBottomSpace(null);
75061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
75161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
75261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
75361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    static abstract class AnimatorListener implements Animator.AnimatorListener {
75461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ArrayList<View> mViews = new ArrayList<View>();
75561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        ArrayList<Integer> mLayerType = new ArrayList<Integer>();
75661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu
75761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationCancel(Animator animation) {
75861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
75961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationRepeat(Animator animation) {
76061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
76161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationStart(Animator animation) {
76261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            getViews(mViews);
76361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (View view : mViews) {
76461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mLayerType.add(view.getLayerType());
76561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
76661905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
76761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
76861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        public void onAnimationEnd(Animator animation) {
76961905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            for (int i = 0; i < mViews.size(); i++) {
77061905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu                mViews.get(i).setLayerType(mLayerType.get(i), null);
77161905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            }
77261905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mLayerType.clear();
77361905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu            mViews.clear();
77461905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        }
77561905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu        abstract void getViews(ArrayList<View> views);
7764fe538f2d65eefc57f618887ccb1226ec1a9741dKeyvan Amiri
77761905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu    };
77861905b0b52c50018dcaebcd79699c39b8f28d622Dake Gu}
779