1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.common.ui.setup;
18 
19 import android.app.Fragment;
20 import android.os.Bundle;
21 import android.support.annotation.IntDef;
22 import android.transition.Transition;
23 import android.transition.Transition.TransitionListener;
24 import android.view.Gravity;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.view.View.OnClickListener;
28 import android.view.ViewGroup;
29 import com.android.tv.common.ui.setup.animation.FadeAndShortSlide;
30 import com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /** A fragment which slides when it is entering/exiting. */
35 public abstract class SetupFragment extends Fragment {
36     @Retention(RetentionPolicy.SOURCE)
37     @IntDef(
38         flag = true,
39         value = {
40             FRAGMENT_ENTER_TRANSITION,
41             FRAGMENT_EXIT_TRANSITION,
42             FRAGMENT_REENTER_TRANSITION,
43             FRAGMENT_RETURN_TRANSITION
44         }
45     )
46     public @interface FragmentTransitionType {}
47 
48     public static final int FRAGMENT_ENTER_TRANSITION = 0x01;
49     public static final int FRAGMENT_EXIT_TRANSITION = FRAGMENT_ENTER_TRANSITION << 1;
50     public static final int FRAGMENT_REENTER_TRANSITION = FRAGMENT_ENTER_TRANSITION << 2;
51     public static final int FRAGMENT_RETURN_TRANSITION = FRAGMENT_ENTER_TRANSITION << 3;
52 
53     private boolean mEnterTransitionRunning;
54 
55     private final TransitionListener mTransitionListener =
56             new TransitionListener() {
57                 @Override
58                 public void onTransitionStart(Transition transition) {
59                     mEnterTransitionRunning = true;
60                 }
61 
62                 @Override
63                 public void onTransitionEnd(Transition transition) {
64                     mEnterTransitionRunning = false;
65                     onEnterTransitionEnd();
66                 }
67 
68                 @Override
69                 public void onTransitionCancel(Transition transition) {}
70 
71                 @Override
72                 public void onTransitionPause(Transition transition) {}
73 
74                 @Override
75                 public void onTransitionResume(Transition transition) {}
76             };
77 
78     /** Returns {@code true} if the enter/reenter transition is running. */
isEnterTransitionRunning()79     protected boolean isEnterTransitionRunning() {
80         return mEnterTransitionRunning;
81     }
82 
83     /** Called when the enter/reenter transition ends. */
onEnterTransitionEnd()84     protected void onEnterTransitionEnd() {}
85 
SetupFragment()86     public SetupFragment() {
87         setAllowEnterTransitionOverlap(false);
88         setAllowReturnTransitionOverlap(false);
89         enableFragmentTransition(
90                 FRAGMENT_ENTER_TRANSITION
91                         | FRAGMENT_EXIT_TRANSITION
92                         | FRAGMENT_REENTER_TRANSITION
93                         | FRAGMENT_RETURN_TRANSITION);
94     }
95 
96     @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)97     public View onCreateView(
98             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
99         View view = inflater.inflate(getLayoutResourceId(), container, false);
100         // After the transition animation, we need to request the focus. If not, this fragment
101         // doesn't have the focus.
102         view.requestFocus();
103         return view;
104     }
105 
106     /** Returns the layout resource ID for this fragment. */
getLayoutResourceId()107     protected abstract int getLayoutResourceId();
108 
setOnClickAction(View view, final String category, final int actionId)109     protected void setOnClickAction(View view, final String category, final int actionId) {
110         view.setOnClickListener(
111                 new OnClickListener() {
112                     @Override
113                     public void onClick(View view) {
114                         onActionClick(category, actionId);
115                     }
116                 });
117     }
118 
onActionClick(String category, int actionId)119     protected boolean onActionClick(String category, int actionId) {
120         return SetupActionHelper.onActionClick(this, category, actionId);
121     }
122 
onActionClick(String category, int actionId, Bundle params)123     protected boolean onActionClick(String category, int actionId, Bundle params) {
124         return SetupActionHelper.onActionClick(this, category, actionId, params);
125     }
126 
127     @Override
setEnterTransition(Transition transition)128     public void setEnterTransition(Transition transition) {
129         super.setEnterTransition(transition);
130         if (transition != null) {
131             transition.addListener(mTransitionListener);
132         }
133     }
134 
135     @Override
setReenterTransition(Transition transition)136     public void setReenterTransition(Transition transition) {
137         super.setReenterTransition(transition);
138         if (transition != null) {
139             transition.addListener(mTransitionListener);
140         }
141     }
142 
143     /**
144      * Enables fragment transition according to the given {@code mask}.
145      *
146      * @param mask This value is the combination of {@link #FRAGMENT_ENTER_TRANSITION}, {@link
147      *     #FRAGMENT_EXIT_TRANSITION}, {@link #FRAGMENT_REENTER_TRANSITION}, and {@link
148      *     #FRAGMENT_RETURN_TRANSITION}.
149      */
enableFragmentTransition(@ragmentTransitionType int mask)150     public void enableFragmentTransition(@FragmentTransitionType int mask) {
151         setEnterTransition(
152                 (mask & FRAGMENT_ENTER_TRANSITION) == 0 ? null : createTransition(Gravity.END));
153         setExitTransition(
154                 (mask & FRAGMENT_EXIT_TRANSITION) == 0 ? null : createTransition(Gravity.START));
155         setReenterTransition(
156                 (mask & FRAGMENT_REENTER_TRANSITION) == 0 ? null : createTransition(Gravity.START));
157         setReturnTransition(
158                 (mask & FRAGMENT_RETURN_TRANSITION) == 0 ? null : createTransition(Gravity.END));
159     }
160 
161     /** Sets the transition with the given {@code slidEdge}. */
setFragmentTransition(@ragmentTransitionType int transitionType, int slideEdge)162     public void setFragmentTransition(@FragmentTransitionType int transitionType, int slideEdge) {
163         switch (transitionType) {
164             case FRAGMENT_ENTER_TRANSITION:
165                 setEnterTransition(createTransition(slideEdge));
166                 break;
167             case FRAGMENT_EXIT_TRANSITION:
168                 setExitTransition(createTransition(slideEdge));
169                 break;
170             case FRAGMENT_REENTER_TRANSITION:
171                 setReenterTransition(createTransition(slideEdge));
172                 break;
173             case FRAGMENT_RETURN_TRANSITION:
174                 setReturnTransition(createTransition(slideEdge));
175                 break;
176         }
177     }
178 
createTransition(int slideEdge)179     private Transition createTransition(int slideEdge) {
180         return new SetupAnimationHelper.TransitionBuilder()
181                 .setSlideEdge(slideEdge)
182                 .setParentIdsForDelay(getParentIdsForDelay())
183                 .setExcludeIds(getExcludedTargetIds())
184                 .build();
185     }
186 
187     /** Changes the move distance of the transitions to short distance. */
setShortDistance(@ragmentTransitionType int mask)188     public void setShortDistance(@FragmentTransitionType int mask) {
189         if ((mask & FRAGMENT_ENTER_TRANSITION) != 0) {
190             Transition transition = getEnterTransition();
191             if (transition instanceof FadeAndShortSlide) {
192                 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
193             }
194         }
195         if ((mask & FRAGMENT_EXIT_TRANSITION) != 0) {
196             Transition transition = getExitTransition();
197             if (transition instanceof FadeAndShortSlide) {
198                 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
199             }
200         }
201         if ((mask & FRAGMENT_REENTER_TRANSITION) != 0) {
202             Transition transition = getReenterTransition();
203             if (transition instanceof FadeAndShortSlide) {
204                 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
205             }
206         }
207         if ((mask & FRAGMENT_RETURN_TRANSITION) != 0) {
208             Transition transition = getReturnTransition();
209             if (transition instanceof FadeAndShortSlide) {
210                 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition);
211             }
212         }
213     }
214 
215     /**
216      * Returns the ID's of the view's whose descendants will perform delayed move.
217      *
218      * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder
219      *     #setParentIdsForDelay
220      */
getParentIdsForDelay()221     protected int[] getParentIdsForDelay() {
222         return null;
223     }
224 
225     /**
226      * Sets the ID's of the views which will not be included in the transition.
227      *
228      * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder
229      *     #setExcludeIds
230      */
getExcludedTargetIds()231     protected int[] getExcludedTargetIds() {
232         return null;
233     }
234 
235     /**
236      * Returns the ID's of the shared elements.
237      *
238      * <p>Note that the shared elements should have their own transition names.
239      */
getSharedElementIds()240     public int[] getSharedElementIds() {
241         return null;
242     }
243 }
244