1b86a6c2c71514e0cb693597a955e224811b90f96Dake Gu// CHECKSTYLE:OFF Generated code
2b86a6c2c71514e0cb693597a955e224811b90f96Dake Gu/* This file is auto-generated from {}DetailsSupportFragmentBackgroundController.java.  DO NOT MODIFY. */
3b86a6c2c71514e0cb693597a955e224811b90f96Dake Gu
4e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu/*
5e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Copyright (C) 2017 The Android Open Source Project
6e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
7e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Licensed under the Apache License, Version 2.0 (the "License");
8e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * you may not use this file except in compliance with the License.
9e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * You may obtain a copy of the License at
10e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
11e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *      http://www.apache.org/licenses/LICENSE-2.0
12e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
13e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Unless required by applicable law or agreed to in writing, software
14e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * distributed under the License is distributed on an "AS IS" BASIS,
15e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * See the License for the specific language governing permissions and
17e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * limitations under the License.
18e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu */
19e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gupackage android.support.v17.leanback.app;
20e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
21e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.animation.PropertyValuesHolder;
22e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.graphics.Bitmap;
23e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.graphics.Color;
24e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.graphics.drawable.ColorDrawable;
25e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.graphics.drawable.Drawable;
26e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.annotation.ColorInt;
27e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.annotation.NonNull;
28e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.annotation.Nullable;
29e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.R;
30e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.graphics.FitWidthBitmapDrawable;
31e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.media.PlaybackGlue;
32e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.media.PlaybackGlueHost;
33e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.widget.DetailsParallaxDrawable;
34e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Guimport android.support.v17.leanback.widget.ParallaxTarget;
35b86a6c2c71514e0cb693597a955e224811b90f96Dake Guimport android.app.Fragment;
36e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
37e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu/**
38e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Controller for DetailsFragment parallax background and embedded video play.
39e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * <p>
40e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * The parallax background drawable is made of two parts: cover drawable (by default
41e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link FitWidthBitmapDrawable}) above the details overview row and bottom drawable (by default
42e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link ColorDrawable}) below the details overview row. While vertically scrolling rows, the size
43e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * of cover drawable and bottom drawable will be updated and the cover drawable will by default
44e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * perform a parallax shift using {@link FitWidthBitmapDrawable#PROPERTY_VERTICAL_OFFSET}.
45e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * </p>
46e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * <pre>
47e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        ***************************
48e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *      Cover Drawable     *
49e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        * (FitWidthBitmapDrawable)*
50e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *                         *
51e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        ***************************
52e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *    DetailsOverviewRow   *
53e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *                         *
54e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        ***************************
55e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *     Bottom Drawable     *
56e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *      (ColorDrawable)    *
57e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *         Related         *
58e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        *         Content         *
59e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *        ***************************
60e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * </pre>
61e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Both parallax background drawable and embedded video play are optional. App must call
62e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link #enableParallax()} and/or {@link #setupVideoPlayback(PlaybackGlue)} explicitly.
63e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * The PlaybackGlue is automatically {@link PlaybackGlue#play()} when fragment starts and
64e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link PlaybackGlue#pause()} when fragment stops. When video is ready to play, cover drawable
65e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * will be faded out.
66e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * Example:
67e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * <pre>
68e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * DetailsFragmentBackgroundController mController = new DetailsFragmentBackgroundController(this);
69e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
70e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * public void onCreate(Bundle savedInstance) {
71e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     super.onCreate(savedInstance);
72e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     MediaPlayerGlue player = new MediaPlayerGlue(..);
73e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     player.setUrl(...);
74e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     mController.enableParallax();
75e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     mController.setupVideoPlayback(player);
76e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * }
77e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
78e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * static class MyLoadBitmapTask extends ... {
79e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     WeakReference<MyFragment> mFragmentRef;
80e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     MyLoadBitmapTask(MyFragment fragment) {
81e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *         mFragmentRef = new WeakReference(fragment);
82e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     }
83e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     protected void onPostExecute(Bitmap bitmap) {
84e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *         MyFragment fragment = mFragmentRef.get();
85e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *         if (fragment != null) {
86e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *             fragment.mController.setCoverBitmap(bitmap);
87e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *         }
88e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     }
89e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * }
90e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
91e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * public void onStart() {
92e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     new MyLoadBitmapTask(this).execute(url);
93e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * }
94e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
95e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * public void onStop() {
96e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *     mController.setCoverBitmap(null);
97e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * }
98e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * </pre>
99e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * <p>
100e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * To customize cover drawable and/or bottom drawable, app should call
101e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link #enableParallax(Drawable, Drawable, ParallaxTarget.PropertyValuesHolderTarget)}.
102e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * If app supplies a custom cover Drawable, it should not call {@link #setCoverBitmap(Bitmap)}.
103e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * If app supplies a custom bottom Drawable, it should not call {@link #setSolidColor(int)}.
104e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * </p>
105e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * <p>
106e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * To customize playback fragment, app should override {@link #onCreateVideoFragment()} and
107e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * {@link #onCreateGlueHost()}.
108e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu * </p>
109e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu *
110e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu */
111e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gupublic class DetailsFragmentBackgroundController {
112e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
113f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    final DetailsFragment mFragment;
114f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    DetailsParallaxDrawable mParallaxDrawable;
115f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    int mParallaxDrawableMaxOffset;
116f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    PlaybackGlue mPlaybackGlue;
117f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    DetailsBackgroundVideoHelper mVideoHelper;
118f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    Bitmap mCoverBitmap;
119f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    int mSolidColor;
120f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    boolean mCanUseHost = false;
1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    boolean mInitialControlVisible = false;
122e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
123c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin    private Fragment mLastVideoFragmentForGlueHost;
124c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin
125e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
126e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Creates a DetailsFragmentBackgroundController for a DetailsFragment. Note that
127e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * each DetailsFragment can only associate with one DetailsFragmentBackgroundController.
128e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
129e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param fragment The DetailsFragment to control background and embedded video playing.
130e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @throws IllegalStateException If fragment was already associated with another controller.
131e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
132e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public DetailsFragmentBackgroundController(DetailsFragment fragment) {
133e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (fragment.mDetailsBackgroundController != null) {
134e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            throw new IllegalStateException("Each DetailsFragment is allowed to initialize "
135e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    + "DetailsFragmentBackgroundController once");
136e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
137e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        fragment.mDetailsBackgroundController = this;
138e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mFragment = fragment;
139e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
140e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
141e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
142e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Enables default parallax background using a {@link FitWidthBitmapDrawable} as cover drawable
143e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * and {@link ColorDrawable} as bottom drawable. A vertical parallax movement will be applied
144e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * to the FitWidthBitmapDrawable. App may use {@link #setSolidColor(int)} and
145e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link #setCoverBitmap(Bitmap)} to change the content of bottom drawable and cover drawable.
146e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * This method must be called before {@link #setupVideoPlayback(PlaybackGlue)}.
147e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
148e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #setCoverBitmap(Bitmap)
149e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #setSolidColor(int)
150e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @throws IllegalStateException If {@link #setupVideoPlayback(PlaybackGlue)} was called.
151e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
152e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public void enableParallax() {
153e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        int offset = mParallaxDrawableMaxOffset;
154e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (offset == 0) {
155e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            offset = FragmentUtil.getContext(mFragment).getResources()
156e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    .getDimensionPixelSize(R.dimen.lb_details_cover_drawable_parallax_movement);
157e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
158e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        Drawable coverDrawable = new FitWidthBitmapDrawable();
159e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        ColorDrawable colorDrawable = new ColorDrawable();
160e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        enableParallax(coverDrawable, colorDrawable,
161e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                new ParallaxTarget.PropertyValuesHolderTarget(
162e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                        coverDrawable,
163e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                        PropertyValuesHolder.ofInt(FitWidthBitmapDrawable.PROPERTY_VERTICAL_OFFSET,
164e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                                0, -offset)
165e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                ));
166e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
167e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
168e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
169e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Enables parallax background using a custom cover drawable at top and a custom bottom
170e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * drawable. This method must be called before {@link #setupVideoPlayback(PlaybackGlue)}.
171e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
172e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param coverDrawable Custom cover drawable shown at top. {@link #setCoverBitmap(Bitmap)}
173e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                      will not work if coverDrawable is not {@link FitWidthBitmapDrawable};
174e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                      in that case it's app's responsibility to set content into
175e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                      coverDrawable.
176e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param bottomDrawable Drawable shown at bottom. {@link #setSolidColor(int)} will not work
177e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                       if bottomDrawable is not {@link ColorDrawable}; in that case it's app's
178e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                       responsibility to set content of bottomDrawable.
179e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param coverDrawableParallaxTarget Target to perform parallax effect within coverDrawable.
180e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                    Use null for no parallax movement effect.
181e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                    Example to move bitmap within FitWidthBitmapDrawable:
182e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                    new ParallaxTarget.PropertyValuesHolderTarget(
183e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                        coverDrawable, PropertyValuesHolder.ofInt(
184e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                            FitWidthBitmapDrawable.PROPERTY_VERTICAL_OFFSET,
185e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *                                            0, -120))
186e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @throws IllegalStateException If {@link #setupVideoPlayback(PlaybackGlue)} was called.
187e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
188e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public void enableParallax(@NonNull Drawable coverDrawable, @NonNull Drawable bottomDrawable,
189e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                               @Nullable ParallaxTarget.PropertyValuesHolderTarget
190e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                                       coverDrawableParallaxTarget) {
191e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mParallaxDrawable != null) {
192e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            return;
193e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
194e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        // if bitmap is set before enableParallax, use it as initial value.
195e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mCoverBitmap != null && coverDrawable instanceof FitWidthBitmapDrawable) {
196e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            ((FitWidthBitmapDrawable) coverDrawable).setBitmap(mCoverBitmap);
197e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
198e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        // if solid color is set before enableParallax, use it as initial value.
199e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mSolidColor != Color.TRANSPARENT && bottomDrawable instanceof ColorDrawable) {
200e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            ((ColorDrawable) bottomDrawable).setColor(mSolidColor);
201e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
202e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mPlaybackGlue != null) {
203e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            throw new IllegalStateException("enableParallaxDrawable must be called before "
204e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                    + "enableVideoPlayback");
205e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
206e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mParallaxDrawable = new DetailsParallaxDrawable(
207e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                FragmentUtil.getContext(mFragment),
208e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                mFragment.getParallax(),
209e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                coverDrawable,
210e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                bottomDrawable,
211e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu                coverDrawableParallaxTarget);
212e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mFragment.setBackgroundDrawable(mParallaxDrawable);
21389097f67f988ebba714a95e10369665280db0c27Dake Gu        // create a VideoHelper with null PlaybackGlue for changing CoverDrawable visibility
21489097f67f988ebba714a95e10369665280db0c27Dake Gu        // before PlaybackGlue is ready.
21589097f67f988ebba714a95e10369665280db0c27Dake Gu        mVideoHelper = new DetailsBackgroundVideoHelper(null,
21689097f67f988ebba714a95e10369665280db0c27Dake Gu                mFragment.getParallax(), mParallaxDrawable.getCoverDrawable());
217e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
218e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
219e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
220e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Enable video playback and set proper {@link PlaybackGlueHost}. This method by default
221e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * creates a VideoFragment and VideoFragmentGlueHost to host the PlaybackGlue.
222f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * This method must be called after calling details Fragment super.onCreate(). This method
223f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * can be called multiple times to replace existing PlaybackGlue or calling
224f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * setupVideoPlayback(null) to clear. Note a typical {@link PlaybackGlue} subclass releases
225f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * resources in {@link PlaybackGlue#onDetachedFromHost()}, when the {@link PlaybackGlue}
226f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * subclass is not doing that, it's app's responsibility to release the resources.
227e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
228f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * @param playbackGlue The new PlaybackGlue to set as background or null to clear existing one.
229e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #onCreateVideoFragment()
230e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #onCreateGlueHost().
231e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
23276c53f6a2152d31a255a36276ada145be5ec474aDake Gu    @SuppressWarnings("ReferenceEquality")
233e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public void setupVideoPlayback(@NonNull PlaybackGlue playbackGlue) {
23401f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        if (mPlaybackGlue == playbackGlue) {
23501f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            return;
23601f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        }
237c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin
238c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin        PlaybackGlueHost playbackGlueHost = null;
239f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu        if (mPlaybackGlue != null) {
240c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin            playbackGlueHost = mPlaybackGlue.getHost();
241f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu            mPlaybackGlue.setHost(null);
242f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu        }
243c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin
244e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mPlaybackGlue = playbackGlue;
24589097f67f988ebba714a95e10369665280db0c27Dake Gu        mVideoHelper.setPlaybackGlue(mPlaybackGlue);
246f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu        if (mCanUseHost && mPlaybackGlue != null) {
247c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin            if (playbackGlueHost == null
248c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin                    || mLastVideoFragmentForGlueHost != findOrCreateVideoFragment()) {
2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mPlaybackGlue.setHost(createGlueHost());
250c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin                mLastVideoFragmentForGlueHost = findOrCreateVideoFragment();
251c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin            } else {
252c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin                mPlaybackGlue.setHost(playbackGlueHost);
253c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin            }
25401f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        }
25501f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu    }
25601f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu
25701f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu    /**
258f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * Returns current PlaybackGlue or null if not set or cleared.
259f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     *
260f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * @return Current PlaybackGlue or null
261f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     */
262f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    public final PlaybackGlue getPlaybackGlue() {
263f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu        return mPlaybackGlue;
264f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    }
265f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu
266f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    /**
267f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * Precondition allows user navigate to video fragment using DPAD. Default implementation
268f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * returns true if PlaybackGlue is not null. Subclass may override, e.g. only allow navigation
2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu     * when {@link PlaybackGlue#isPrepared()} is true. Note this method does not block
270f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * app calls {@link #switchToVideo}.
271f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     *
272f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * @return True allow to navigate to video fragment.
273f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     */
274f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    public boolean canNavigateToVideoFragment() {
275f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu        return mPlaybackGlue != null;
276f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    }
277f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu
2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void switchToVideoBeforeCreate() {
2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mVideoHelper.crossFadeBackgroundToVideo(true, true);
2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mInitialControlVisible = true;
28189097f67f988ebba714a95e10369665280db0c27Dake Gu    }
28289097f67f988ebba714a95e10369665280db0c27Dake Gu
283f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    /**
284f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * Switch to video fragment, note that this method is not affected by result of
28589097f67f988ebba714a95e10369665280db0c27Dake Gu     * {@link #canNavigateToVideoFragment()}. If the method is called in DetailsFragment.onCreate()
28689097f67f988ebba714a95e10369665280db0c27Dake Gu     * it will make video fragment to be initially focused once it is created.
28789097f67f988ebba714a95e10369665280db0c27Dake Gu     * <p>
28889097f67f988ebba714a95e10369665280db0c27Dake Gu     * Calling switchToVideo() in DetailsFragment.onCreate() will clear the activity enter
28989097f67f988ebba714a95e10369665280db0c27Dake Gu     * transition and shared element transition.
29089097f67f988ebba714a95e10369665280db0c27Dake Gu     * </p>
29189097f67f988ebba714a95e10369665280db0c27Dake Gu     * <p>
29289097f67f988ebba714a95e10369665280db0c27Dake Gu     * If switchToVideo() is called after {@link DetailsFragment#prepareEntranceTransition()} and
29389097f67f988ebba714a95e10369665280db0c27Dake Gu     * before {@link DetailsFragment#onEntranceTransitionEnd()}, it will be ignored.
29489097f67f988ebba714a95e10369665280db0c27Dake Gu     * </p>
29589097f67f988ebba714a95e10369665280db0c27Dake Gu     * <p>
29689097f67f988ebba714a95e10369665280db0c27Dake Gu     * If {@link DetailsFragment#prepareEntranceTransition()} is called after switchToVideo(), an
29789097f67f988ebba714a95e10369665280db0c27Dake Gu     * IllegalStateException will be thrown.
29889097f67f988ebba714a95e10369665280db0c27Dake Gu     * </p>
299f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     */
300f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    public final void switchToVideo() {
30189097f67f988ebba714a95e10369665280db0c27Dake Gu        mFragment.switchToVideo();
302f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    }
303f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu
304f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    /**
305f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     * Switch to rows fragment.
306f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu     */
307f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    public final void switchToRows() {
30889097f67f988ebba714a95e10369665280db0c27Dake Gu        mFragment.switchToRows();
309f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    }
310f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu
311f87eb1d84dfee2f1be9ea326754829b1eff4967fDake Gu    /**
312f37579e64940bfdd642cc315f6347d60b5addd69Dake Gu     * When fragment is started and no running transition. First set host if not yet set, second
313f37579e64940bfdd642cc315f6347d60b5addd69Dake Gu     * start playing if it was paused before.
31401f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu     */
315f37579e64940bfdd642cc315f6347d60b5addd69Dake Gu    void onStart() {
31601f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        if (!mCanUseHost) {
31701f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            mCanUseHost = true;
31801f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            if (mPlaybackGlue != null) {
3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mPlaybackGlue.setHost(createGlueHost());
320c65ceae1251b35fbf4aa72df7b5d20e764bed9d2Wei-Hsin                mLastVideoFragmentForGlueHost = findOrCreateVideoFragment();
32101f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            }
32201f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        }
3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mPlaybackGlue != null && mPlaybackGlue.isPrepared()) {
3243961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu            mPlaybackGlue.play();
3253961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu        }
3263961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu    }
3273961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu
3283961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu    void onStop() {
3293961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu        if (mPlaybackGlue != null) {
3303961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu            mPlaybackGlue.pause();
3313961cea270f51c29433a7eb21ec5f8c9ca7bd7d7Dake Gu        }
33201f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu    }
33301f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu
33401f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu    /**
33501f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu     * Disable parallax that would auto-start video playback
33601f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu     * @return true if video fragment is visible or false otherwise.
33701f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu     */
33801f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu    boolean disableVideoParallax() {
33901f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        if (mVideoHelper != null) {
34001f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            mVideoHelper.stopParallax();
34101f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu            return mVideoHelper.isVideoVisible();
34201f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        }
34301f4dd4a9bc3b80d3ddecc0264facbf6abfc1cc3Dake Gu        return false;
344e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
345e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
346e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
347e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Returns the cover drawable at top. Returns null if {@link #enableParallax()} is not called.
348e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * By default it's a {@link FitWidthBitmapDrawable}.
349e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
350e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return The cover drawable at top.
351e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
352e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final Drawable getCoverDrawable() {
353e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mParallaxDrawable == null) {
354e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            return null;
355e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
356e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mParallaxDrawable.getCoverDrawable();
357e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
358e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
359e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
360e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Returns the drawable at bottom. Returns null if {@link #enableParallax()} is not called.
361e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * By default it's a {@link ColorDrawable}.
362e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
363e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return The bottom drawable.
364e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
365e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final Drawable getBottomDrawable() {
366e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mParallaxDrawable == null) {
367e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            return null;
368e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
369e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mParallaxDrawable.getBottomDrawable();
370e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
371e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
372e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
373e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Creates a Fragment to host {@link PlaybackGlue}. Returns a new {@link VideoFragment} by
374e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * default. App may override and return a different fragment and it also must override
375e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link #onCreateGlueHost()}.
376e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
377e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return A new fragment used in {@link #onCreateGlueHost()}.
378e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #onCreateGlueHost()
379e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #setupVideoPlayback(PlaybackGlue)
380e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
381e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public Fragment onCreateVideoFragment() {
382e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return new VideoFragment();
383e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
384e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
385e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
386e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Creates a PlaybackGlueHost to host PlaybackGlue. App may override this if it overrides
387e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link #onCreateVideoFragment()}. This method must be called after calling Fragment
388e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * super.onCreate(). When override this method, app may call
389e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link #findOrCreateVideoFragment()} to get or create a fragment.
390e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
391e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return A new PlaybackGlueHost to host PlaybackGlue.
392e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #onCreateVideoFragment()
393e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #findOrCreateVideoFragment()
394e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #setupVideoPlayback(PlaybackGlue)
395e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
396e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public PlaybackGlueHost onCreateGlueHost() {
397e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return new VideoFragmentGlueHost((VideoFragment) findOrCreateVideoFragment());
398e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
399e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
4003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackGlueHost createGlueHost() {
4013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackGlueHost host = onCreateGlueHost();
4023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (mInitialControlVisible) {
4033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            host.showControlsOverlay(false);
4043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        } else {
4053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            host.hideControlsOverlay(false);
4063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
4073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        return host;
4083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
410e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
411e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Adds or gets fragment for rendering video in DetailsFragment. A subclass that
412e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * overrides {@link #onCreateGlueHost()} should call this method to get a fragment for creating
413e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * a {@link PlaybackGlueHost}.
414e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
415e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return Fragment the added or restored fragment responsible for rendering video.
416e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #onCreateGlueHost()
417e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
418e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final Fragment findOrCreateVideoFragment() {
419e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mFragment.findOrCreateVideoFragment();
420e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
421e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
422e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
423e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Convenient method to set Bitmap in cover drawable. If app is not using default
424e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link FitWidthBitmapDrawable}, app should not use this method  It's safe to call
425e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * setCoverBitmap() before calling {@link #enableParallax()}.
426e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
427e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param bitmap bitmap to set as cover.
428e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
429e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final void setCoverBitmap(Bitmap bitmap) {
430e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mCoverBitmap = bitmap;
431e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        Drawable drawable = getCoverDrawable();
432e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (drawable instanceof FitWidthBitmapDrawable) {
433e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            ((FitWidthBitmapDrawable) drawable).setBitmap(mCoverBitmap);
434e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
435e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
436e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
437e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
438e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Returns Bitmap set by {@link #setCoverBitmap(Bitmap)}.
439e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
440e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return Bitmap for cover drawable.
441e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
442e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final Bitmap getCoverBitmap() {
443e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mCoverBitmap;
444e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
445e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
446e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
447e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Returns color set by {@link #setSolidColor(int)}.
448e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
449e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return Solid color used for bottom drawable.
450e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
451e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final @ColorInt int getSolidColor() {
452e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mSolidColor;
453e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
454e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
455e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
456e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Convenient method to set color in bottom drawable. If app is not using default
457e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * {@link ColorDrawable}, app should not use this method. It's safe to call setSolidColor()
458e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * before calling {@link #enableParallax()}.
459e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
460e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param color color for bottom drawable.
461e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
462e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final void setSolidColor(@ColorInt int color) {
463e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mSolidColor = color;
464e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        Drawable bottomDrawable = getBottomDrawable();
465e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (bottomDrawable instanceof ColorDrawable) {
466e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            ((ColorDrawable) bottomDrawable).setColor(color);
467e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
468e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
469e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
470e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
471e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Sets default parallax offset in pixels for bitmap moving vertically. This method must
472e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * be called before {@link #enableParallax()}.
473e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
474e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @param offset Offset in pixels (e.g. 120).
475e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #enableParallax()
476e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
477e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final void setParallaxDrawableMaxOffset(int offset) {
478e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        if (mParallaxDrawable != null) {
479e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu            throw new IllegalStateException("enableParallax already called");
480e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        }
481e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        mParallaxDrawableMaxOffset = offset;
482e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
483e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
484e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    /**
485e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * Returns Default parallax offset in pixels for bitmap moving vertically.
486e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * When 0, a default value would be used.
487e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     *
488e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @return Default parallax offset in pixels for bitmap moving vertically.
489e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     * @see #enableParallax()
490e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu     */
491e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    public final int getParallaxDrawableMaxOffset() {
492e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu        return mParallaxDrawableMaxOffset;
493e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu    }
494e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu
495e1cde4d4ac42a6e9e16aad2b4df970c7c7d0771cDake Gu}
496