1/* This file is auto-generated from BaseFragment.java.  DO NOT MODIFY. */
2
3/*
4 * Copyright (C) 2014 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 * in compliance with the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software distributed under the License
12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package android.support.v17.leanback.app;
17
18import android.os.Bundle;
19import android.support.v17.leanback.R;
20import android.support.v17.leanback.transition.TransitionHelper;
21import android.support.v17.leanback.transition.TransitionListener;
22import android.view.View;
23import android.view.ViewTreeObserver;
24
25/**
26 * @hide
27 */
28class BaseSupportFragment extends BrandedSupportFragment {
29
30    private boolean mEntranceTransitionEnabled = false;
31    private boolean mStartEntranceTransitionPending = false;
32    private boolean mEntranceTransitionPreparePending = false;
33    private Object mEntranceTransition;
34
35    static TransitionHelper sTransitionHelper = TransitionHelper.getInstance();
36
37    @Override
38    public void onViewCreated(View view, Bundle savedInstanceState) {
39        super.onViewCreated(view, savedInstanceState);
40        if (mEntranceTransitionPreparePending) {
41            mEntranceTransitionPreparePending = false;
42            onEntranceTransitionPrepare();
43        }
44        if (mStartEntranceTransitionPending) {
45            mStartEntranceTransitionPending = false;
46            startEntranceTransition();
47        }
48    }
49
50    /**
51     * Enables entrance transition.<p>
52     * Entrance transition is the standard slide-in transition that shows rows of data in
53     * browse screen and details screen.
54     * <p>
55     * The method is ignored before LOLLIPOP (API21).
56     * <p>
57     * This method must be called in or
58     * before onCreate().  Typically entrance transition should be enabled when savedInstance is
59     * null so that fragment restored from instanceState does not run an extra entrance transition.
60     * When the entrance transition is enabled, the fragment will make headers and content
61     * hidden initially.
62     * When data of rows are ready, app must call {@link #startEntranceTransition()} to kick off
63     * the transition, otherwise the rows will be invisible forever.
64     * <p>
65     * It is similar to android:windowsEnterTransition and can be considered a late-executed
66     * android:windowsEnterTransition controlled by app.  There are two reasons that app needs it:
67     * <li> Workaround the problem that activity transition is not available between launcher and
68     * app.  Browse activity must programmatically start the slide-in transition.</li>
69     * <li> Separates DetailsOverviewRow transition from other rows transition.  So that
70     * the DetailsOverviewRow transition can be executed earlier without waiting for all rows
71     * to be loaded.</li>
72     * <p>
73     * Transition object is returned by createEntranceTransition().  Typically the app does not need
74     * override the default transition that browse and details provides.
75     */
76    public void prepareEntranceTransition() {
77        if (TransitionHelper.systemSupportsEntranceTransitions()) {
78            mEntranceTransitionEnabled = true;
79            if (getView() == null) {
80                mEntranceTransitionPreparePending = true;
81                return;
82            }
83            onEntranceTransitionPrepare();
84        }
85    }
86
87    /**
88     * Return true if entrance transition is enabled and not started yet.
89     * Entrance transition can only be executed once and isEntranceTransitionEnabled()
90     * is reset to false after entrance transition is started.
91     */
92    boolean isEntranceTransitionEnabled() {
93        return mEntranceTransitionEnabled;
94    }
95
96    /**
97     * Create entrance transition.  Subclass can override to load transition from
98     * resource or construct manually.  Typically app does not need to
99     * override the default transition that browse and details provides.
100     */
101    protected Object createEntranceTransition() {
102        return null;
103    }
104
105    /**
106     * Run entrance transition.  Subclass may use TransitionManager to perform
107     * go(Scene) or beginDelayedTransition().  App should not override the default
108     * implementation of browse and details fragment.
109     */
110    protected void runEntranceTransition(Object entranceTransition) {
111    }
112
113    /**
114     * Callback when entrance transition is prepared.  This is when fragment should
115     * stop user input and animations.
116     */
117    protected void onEntranceTransitionPrepare() {
118    }
119
120    /**
121     * Callback when entrance transition is started.  This is when fragment should
122     * stop processing layout.
123     */
124    protected void onEntranceTransitionStart() {
125    }
126
127    /**
128     * Callback when entrance transition is ended.
129     */
130    protected void onEntranceTransitionEnd() {
131    }
132
133    /**
134     * When fragment finishes loading data, it should call startEntranceTransition()
135     * to execute the entrance transition.
136     * startEntranceTransition() will start transition only if both two conditions
137     * are satisfied:
138     * <li> prepareEntranceTransition() was called.</li>
139     * <li> has not executed entrance transition yet.</li>
140     * <p>
141     * If startEntranceTransition() is called before onViewCreated(), it will be pending
142     * and executed when view is created.
143     */
144    public void startEntranceTransition() {
145        if (!mEntranceTransitionEnabled || mEntranceTransition != null) {
146            return;
147        }
148        // if view is not created yet, delay until onViewCreated()
149        if (getView() == null) {
150            mStartEntranceTransitionPending = true;
151            return;
152        }
153        if (mEntranceTransitionPreparePending) {
154            mEntranceTransitionPreparePending = false;
155            onEntranceTransitionPrepare();
156        }
157        // wait till views get their initial position before start transition
158        final View view = getView();
159        view.getViewTreeObserver().addOnPreDrawListener(
160                new ViewTreeObserver.OnPreDrawListener() {
161            @Override
162            public boolean onPreDraw() {
163                view.getViewTreeObserver().removeOnPreDrawListener(this);
164                internalCreateEntranceTransition();
165                mEntranceTransitionEnabled = false;
166                if (mEntranceTransition != null) {
167                    onEntranceTransitionStart();
168                    runEntranceTransition(mEntranceTransition);
169                }
170                return false;
171            }
172        });
173        view.invalidate();
174    }
175
176    void internalCreateEntranceTransition() {
177        mEntranceTransition = createEntranceTransition();
178        if (mEntranceTransition == null) {
179            return;
180        }
181        sTransitionHelper.setTransitionListener(mEntranceTransition, new TransitionListener() {
182            @Override
183            public void onTransitionEnd(Object transition) {
184                mEntranceTransition = null;
185                onEntranceTransitionEnd();
186            }
187        });
188    }
189}
190