1 /*
2  * Copyright (C) 2020 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.google.android.setupdesign.transition.support;
18 
19 import static com.google.android.setupdesign.transition.TransitionHelper.CONFIG_TRANSITION_SHARED_X_AXIS;
20 import static com.google.android.setupdesign.transition.TransitionHelper.getConfigTransitionType;
21 
22 import android.annotation.TargetApi;
23 import android.app.Activity;
24 import android.os.Build;
25 import android.os.Build.VERSION_CODES;
26 import androidx.fragment.app.Fragment;
27 import android.util.Log;
28 import android.view.Window;
29 import androidx.annotation.Nullable;
30 import androidx.core.app.ActivityOptionsCompat;
31 import com.google.android.material.transition.platform.MaterialSharedAxis;
32 import com.google.android.setupcompat.partnerconfig.PartnerConfig;
33 
34 /** Helper class for apply the transition to the pages which uses support library. */
35 public class TransitionHelper {
36 
37   private static final String TAG = "TransitionHelper";
38 
TransitionHelper()39   private TransitionHelper() {}
40 
41   /**
42    * Apply the transition for going forward which is decided by partner resource {@link
43    * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}.
44    * The default transition that will be applied is {@link
45    * com.google.android.setupdesign.transition.TransitionHelper#CONFIG_TRANSITION_NONE}. The timing
46    * to apply the transition is going forward from the previous {@link Fragment} to this, or going
47    * forward from this {@link Fragment} to the next.
48    */
49   @TargetApi(VERSION_CODES.M)
applyForwardTransition(Fragment fragment)50   public static void applyForwardTransition(Fragment fragment) {
51     if (Build.VERSION.SDK_INT >= VERSION_CODES.M) {
52       if (CONFIG_TRANSITION_SHARED_X_AXIS == getConfigTransitionType(fragment.getContext())) {
53         MaterialSharedAxis exitTransition =
54             new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true);
55         fragment.setExitTransition(exitTransition);
56 
57         MaterialSharedAxis enterTransition =
58             new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ true);
59         fragment.setEnterTransition(enterTransition);
60       } else {
61         Log.w(TAG, "Not apply the forward transition for support lib's fragment.");
62       }
63     } else {
64       Log.w(
65           TAG,
66           "Not apply the forward transition for support lib's fragment. The API is supported from"
67               + " Android Sdk "
68               + VERSION_CODES.M);
69     }
70   }
71 
72   /**
73    * Apply the transition for going backward which is decided by partner resource {@link
74    * PartnerConfig#CONFIG_TRANSITION_TYPE} and system property {@code setupwizard.transition_type}.
75    * The default transition that will be applied is {@link
76    * com.google.android.setupdesign.transition.TransitionHelper#CONFIG_TRANSITION_NONE}. The timing
77    * to apply the transition is going backward from the next {@link Fragment} to this, or going
78    * backward from this {@link Fragment} to the previous.
79    */
80   @TargetApi(VERSION_CODES.M)
applyBackwardTransition(Fragment fragment)81   public static void applyBackwardTransition(Fragment fragment) {
82     if (Build.VERSION.SDK_INT >= VERSION_CODES.M) {
83       if (CONFIG_TRANSITION_SHARED_X_AXIS == getConfigTransitionType(fragment.getContext())) {
84         MaterialSharedAxis returnTransition =
85             new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false);
86         fragment.setReturnTransition(returnTransition);
87 
88         MaterialSharedAxis reenterTransition =
89             new MaterialSharedAxis(MaterialSharedAxis.X, /* forward= */ false);
90         fragment.setReenterTransition(reenterTransition);
91       } else {
92         Log.w(TAG, "Not apply the backward transition for support lib's fragment.");
93       }
94     } else {
95       Log.w(
96           TAG,
97           "Not apply the backward transition for support lib's fragment. The API is supported from"
98               + " Android Sdk "
99               + VERSION_CODES.M);
100     }
101   }
102 
103   /**
104    * A wrapper method, create an {@link ActivityOptionsCompat} to transition between activities as
105    * the {@link ActivityOptionsCompat} parameter of {@link
106    * androidx.activity.result.ActivityResultLauncher#launch(I, ActivityOptionsCompat)} method.
107    */
108   @Nullable
makeActivityOptionsCompat(Activity activity)109   public static ActivityOptionsCompat makeActivityOptionsCompat(Activity activity) {
110     ActivityOptionsCompat activityOptionsCompat = null;
111     if (activity == null) {
112       return activityOptionsCompat;
113     }
114 
115     if (getConfigTransitionType(activity) == CONFIG_TRANSITION_SHARED_X_AXIS) {
116       if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
117         if (activity.getWindow() != null
118             && !activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) {
119           Log.w(
120               TAG,
121               "The transition won't take effect due to NO FEATURE_ACTIVITY_TRANSITIONS feature");
122         }
123 
124         activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity);
125       }
126     }
127 
128     return activityOptionsCompat;
129   }
130 }
131