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 package com.android.quickstep.interaction;
17 
18 import android.content.Context;
19 import android.graphics.drawable.Animatable2;
20 import android.graphics.drawable.AnimatedVectorDrawable;
21 import android.graphics.drawable.Drawable;
22 import android.view.View;
23 import android.widget.ImageView;
24 
25 import androidx.core.content.ContextCompat;
26 
27 import com.android.launcher3.R;
28 import com.android.quickstep.interaction.TutorialController.TutorialType;
29 
30 import java.time.Duration;
31 
32 /** Hand coaching animation. */
33 final class TutorialHandAnimation {
34 
35     // A delay for waiting the Activity fully launches.
36     private static final Duration ANIMATION_START_DELAY = Duration.ofMillis(300L);
37 
38     private final ImageView mHandCoachingView;
39     private final AnimatedVectorDrawable mGestureAnimation;
40 
TutorialHandAnimation(Context context, View rootView, int resId)41     TutorialHandAnimation(Context context, View rootView, int resId) {
42         mHandCoachingView = rootView.findViewById(R.id.gesture_tutorial_fragment_hand_coaching);
43         mGestureAnimation = (AnimatedVectorDrawable) ContextCompat.getDrawable(context, resId);
44     }
45 
46     /** [Re]starts animation for the given tutorial. */
startLoopedAnimation(TutorialType tutorialType)47     void startLoopedAnimation(TutorialType tutorialType) {
48         mHandCoachingView.setVisibility(View.VISIBLE);
49         if (mGestureAnimation.isRunning()) {
50             stop();
51         }
52 
53         mGestureAnimation.clearAnimationCallbacks();
54         mGestureAnimation.registerAnimationCallback(
55                 new Animatable2.AnimationCallback() {
56                     @Override
57                     public void onAnimationEnd(Drawable drawable) {
58                         super.onAnimationEnd(drawable);
59                         mGestureAnimation.start();
60                     }
61                 });
62         start(tutorialType);
63     }
64 
start(TutorialType tutorialType)65     private void start(TutorialType tutorialType) {
66         // Because the gesture animation has only the right side form.
67         // The left side form of the gesture animation is made from flipping the View.
68         float rotationY = tutorialType == TutorialType.LEFT_EDGE_BACK_NAVIGATION ? 180f : 0f;
69         mHandCoachingView.setRotationY(rotationY);
70         mHandCoachingView.setImageDrawable(mGestureAnimation);
71         mHandCoachingView.postDelayed(mGestureAnimation::start, ANIMATION_START_DELAY.toMillis());
72     }
73 
stop()74     void stop() {
75         mGestureAnimation.clearAnimationCallbacks();
76         mGestureAnimation.stop();
77     }
78 }
79