Home | History | Annotate | Download | only in setup
      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      */
     77     protected boolean isEnterTransitionRunning() {
     78         return mEnterTransitionRunning;
     79     }
     80 
     81     /**
     82      * Called when the enter/reenter transition ends.
     83      */
     84     protected void onEnterTransitionEnd() { }
     85 
     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
     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      */
    106     abstract protected int getLayoutResourceId();
    107 
    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 
    117     protected boolean onActionClick(String category, int actionId) {
    118         return SetupActionHelper.onActionClick(this, category, actionId);
    119     }
    120 
    121     protected boolean onActionClick(String category, int actionId, Bundle params) {
    122         return SetupActionHelper.onActionClick(this, category, actionId, params);
    123     }
    124 
    125     @Override
    126     public void setEnterTransition(Transition transition) {
    127         super.setEnterTransition(transition);
    128         if (transition != null) {
    129             transition.addListener(mTransitionListener);
    130         }
    131     }
    132 
    133     @Override
    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      */
    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      */
    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 
    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      */
    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      */
    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      */
    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      */
    242     public int[] getSharedElementIds() {
    243         return null;
    244     }
    245 }
    246