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 30 import com.android.tv.common.ui.setup.animation.FadeAndShortSlide; 31 import com.android.tv.common.ui.setup.animation.SetupAnimationHelper; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 36 /** 37 * A fragment which slides when it is entering/exiting. 38 */ 39 public abstract class SetupFragment extends Fragment { 40 @Retention(RetentionPolicy.SOURCE) 41 @IntDef(flag = true, 42 value = {FRAGMENT_ENTER_TRANSITION, FRAGMENT_EXIT_TRANSITION, 43 FRAGMENT_REENTER_TRANSITION, FRAGMENT_RETURN_TRANSITION}) 44 public @interface FragmentTransitionType {} 45 public static final int FRAGMENT_ENTER_TRANSITION = 0x01; 46 public static final int FRAGMENT_EXIT_TRANSITION = FRAGMENT_ENTER_TRANSITION << 1; 47 public static final int FRAGMENT_REENTER_TRANSITION = FRAGMENT_ENTER_TRANSITION << 2; 48 public static final int FRAGMENT_RETURN_TRANSITION = FRAGMENT_ENTER_TRANSITION << 3; 49 50 private boolean mEnterTransitionRunning; 51 52 private final TransitionListener mTransitionListener = new TransitionListener() { 53 @Override 54 public void onTransitionStart(Transition transition) { 55 mEnterTransitionRunning = true; 56 } 57 58 @Override 59 public void onTransitionEnd(Transition transition) { 60 mEnterTransitionRunning = false; 61 onEnterTransitionEnd(); 62 } 63 64 @Override 65 public void onTransitionCancel(Transition transition) { } 66 67 @Override 68 public void onTransitionPause(Transition transition) { } 69 70 @Override 71 public void onTransitionResume(Transition transition) { } 72 }; 73 74 /** 75 * Returns {@code true} if the enter/reenter transition is running. 76 */ isEnterTransitionRunning()77 protected boolean isEnterTransitionRunning() { 78 return mEnterTransitionRunning; 79 } 80 81 /** 82 * Called when the enter/reenter transition ends. 83 */ onEnterTransitionEnd()84 protected void onEnterTransitionEnd() { } 85 SetupFragment()86 public SetupFragment() { 87 setAllowEnterTransitionOverlap(false); 88 setAllowReturnTransitionOverlap(false); 89 enableFragmentTransition(FRAGMENT_ENTER_TRANSITION | FRAGMENT_EXIT_TRANSITION 90 | FRAGMENT_REENTER_TRANSITION | FRAGMENT_RETURN_TRANSITION); 91 } 92 93 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)94 public View onCreateView(LayoutInflater inflater, ViewGroup container, 95 Bundle savedInstanceState) { 96 View view = inflater.inflate(getLayoutResourceId(), container, false); 97 // After the transition animation, we need to request the focus. If not, this fragment 98 // doesn't have the focus. 99 view.requestFocus(); 100 return view; 101 } 102 103 /** 104 * Returns the layout resource ID for this fragment. 105 */ getLayoutResourceId()106 abstract protected int getLayoutResourceId(); 107 setOnClickAction(View view, final String category, final int actionId)108 protected void setOnClickAction(View view, final String category, final int actionId) { 109 view.setOnClickListener(new OnClickListener() { 110 @Override 111 public void onClick(View view) { 112 onActionClick(category, actionId); 113 } 114 }); 115 } 116 onActionClick(String category, int actionId)117 protected boolean onActionClick(String category, int actionId) { 118 return SetupActionHelper.onActionClick(this, category, actionId); 119 } 120 onActionClick(String category, int actionId, Bundle params)121 protected boolean onActionClick(String category, int actionId, Bundle params) { 122 return SetupActionHelper.onActionClick(this, category, actionId, params); 123 } 124 125 @Override setEnterTransition(Transition transition)126 public void setEnterTransition(Transition transition) { 127 super.setEnterTransition(transition); 128 if (transition != null) { 129 transition.addListener(mTransitionListener); 130 } 131 } 132 133 @Override setReenterTransition(Transition transition)134 public void setReenterTransition(Transition transition) { 135 super.setReenterTransition(transition); 136 if (transition != null) { 137 transition.addListener(mTransitionListener); 138 } 139 } 140 141 /** 142 * Enables fragment transition according to the given {@code mask}. 143 * 144 * @param mask This value is the combination of {@link #FRAGMENT_ENTER_TRANSITION}, 145 * {@link #FRAGMENT_EXIT_TRANSITION}, {@link #FRAGMENT_REENTER_TRANSITION}, and 146 * {@link #FRAGMENT_RETURN_TRANSITION}. 147 */ enableFragmentTransition(@ragmentTransitionType int mask)148 public void enableFragmentTransition(@FragmentTransitionType int mask) { 149 setEnterTransition((mask & FRAGMENT_ENTER_TRANSITION) == 0 ? null 150 : createTransition(Gravity.END)); 151 setExitTransition((mask & FRAGMENT_EXIT_TRANSITION) == 0 ? null 152 : createTransition(Gravity.START)); 153 setReenterTransition((mask & FRAGMENT_REENTER_TRANSITION) == 0 ? null 154 : createTransition(Gravity.START)); 155 setReturnTransition((mask & FRAGMENT_RETURN_TRANSITION) == 0 ? null 156 : createTransition(Gravity.END)); 157 } 158 159 /** 160 * Sets the transition with the given {@code slidEdge}. 161 */ 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 /** 188 * Changes the move distance of the transitions to short distance. 189 */ setShortDistance(@ragmentTransitionType int mask)190 public void setShortDistance(@FragmentTransitionType int mask) { 191 if ((mask & FRAGMENT_ENTER_TRANSITION) != 0) { 192 Transition transition = getEnterTransition(); 193 if (transition instanceof FadeAndShortSlide) { 194 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition); 195 } 196 } 197 if ((mask & FRAGMENT_EXIT_TRANSITION) != 0) { 198 Transition transition = getExitTransition(); 199 if (transition instanceof FadeAndShortSlide) { 200 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition); 201 } 202 } 203 if ((mask & FRAGMENT_REENTER_TRANSITION) != 0) { 204 Transition transition = getReenterTransition(); 205 if (transition instanceof FadeAndShortSlide) { 206 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition); 207 } 208 } 209 if ((mask & FRAGMENT_RETURN_TRANSITION) != 0) { 210 Transition transition = getReturnTransition(); 211 if (transition instanceof FadeAndShortSlide) { 212 SetupAnimationHelper.setShortDistance((FadeAndShortSlide) transition); 213 } 214 } 215 } 216 217 /** 218 * Returns the ID's of the view's whose descendants will perform delayed move. 219 * 220 * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder 221 * #setParentIdsForDelay 222 */ getParentIdsForDelay()223 protected int[] getParentIdsForDelay() { 224 return null; 225 } 226 227 /** 228 * Sets the ID's of the views which will not be included in the transition. 229 * 230 * @see com.android.tv.common.ui.setup.animation.SetupAnimationHelper.TransitionBuilder 231 * #setExcludeIds 232 */ getExcludedTargetIds()233 protected int[] getExcludedTargetIds() { 234 return null; 235 } 236 237 /** 238 * Returns the ID's of the shared elements. 239 * 240 * <p>Note that the shared elements should have their own transition names. 241 */ getSharedElementIds()242 public int[] getSharedElementIds() { 243 return null; 244 } 245 } 246