• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.example.android.support.animation;
18 
19 import android.app.Activity;
20 import android.os.Bundle;
21 import android.view.MotionEvent;
22 import android.view.VelocityTracker;
23 import android.view.View;
24 import android.widget.SeekBar;
25 import android.widget.TextView;
26 
27 import androidx.dynamicanimation.animation.DynamicAnimation;
28 import androidx.dynamicanimation.animation.SpringAnimation;
29 
30 /**
31  * This is a single spring animation. It provides a UI to interact with the spring, and two seek
32  * bars to tune the spring constants.
33  */
34 public class SpringActivity extends Activity {
35     private float mDampingRatio;
36     private float mStiffness;
37     private SpringView mSpringView;
38 
39     @Override
onCreate(Bundle savedInstanceState)40     protected void onCreate(Bundle savedInstanceState) {
41         super.onCreate(savedInstanceState);
42         setContentView(R.layout.activity_main);
43 
44         final View v = findViewById(R.id.container);
45         mSpringView = findViewById(R.id.actual_spring);
46 
47         final View img = findViewById(R.id.imageView);
48         setupSeekBars();
49         final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y,
50                 0 /* final position */);
51         anim.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {
52             @Override
53             public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float v, float v1) {
54                 // Update the drawing of the spring.
55                 mSpringView.setMassHeight(img.getY());
56             }
57         });
58 
59         ((View) img.getParent()).setOnTouchListener(new View.OnTouchListener() {
60             public float touchOffset;
61             public VelocityTracker vt;
62             @Override
63             public boolean onTouch(View v, MotionEvent motionEvent) {
64                 if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
65                     // check whether the touch happens inside of the img view.
66                     boolean inside = motionEvent.getX() >= img.getX()
67                             && motionEvent.getX() <= img.getX() + img.getWidth()
68                             && motionEvent.getY() >= img.getY()
69                             && motionEvent.getY() <= img.getY() + img.getHeight();
70 
71                     anim.cancel();
72 
73                     if (!inside) {
74                         return false;
75                     }
76                     // Apply this offset to all the subsequent events
77                     touchOffset = img.getTranslationY() - motionEvent.getY();
78                     vt = VelocityTracker.obtain();
79                     vt.clear();
80                 }
81 
82                 vt.addMovement(motionEvent);
83 
84                 if (motionEvent.getActionMasked() == MotionEvent.ACTION_MOVE) {
85                     img.setTranslationY(motionEvent.getY() + touchOffset);
86                     // Updates the drawing of the spring.
87                     mSpringView.setMassHeight(img.getY());
88                 } else if (motionEvent.getActionMasked() == MotionEvent.ACTION_CANCEL
89                         || motionEvent.getActionMasked() == MotionEvent.ACTION_UP) {
90                     // Compute the velocity in unit: pixel/second
91                     vt.computeCurrentVelocity(1000);
92                     float velocity = vt.getYVelocity();
93                     anim.getSpring().setDampingRatio(mDampingRatio).setStiffness(mStiffness);
94                     anim.setStartVelocity(velocity).start();
95                     vt.recycle();
96                 }
97                 return true;
98             }
99         });
100     }
101 
102     // Setup seek bars so damping ratio and stiffness for the spring can be modified through the UI.
setupSeekBars()103     void setupSeekBars() {
104         SeekBar dr = findViewById(R.id.damping_ratio);
105         dr.setMax(130);
106         final TextView drTxt = findViewById(R.id.damping_ratio_txt);
107         dr.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
108             @Override
109             public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
110                 if (i < 80) {
111                     mDampingRatio = i / 80.0f;
112                 } else if (i > 90) {
113                     mDampingRatio = (float) Math.exp((i - 90) / 10.0);
114                 } else {
115                     mDampingRatio = 1;
116                 }
117                 drTxt.setText(String.format("%.4f", (float) mDampingRatio));
118             }
119 
120             @Override
121             public void onStartTrackingTouch(SeekBar seekBar) {
122 
123             }
124 
125             @Override
126             public void onStopTrackingTouch(SeekBar seekBar) {
127 
128             }
129         });
130 
131         SeekBar stiff = findViewById(R.id.stiffness);
132         stiff.setMax(110);
133         final TextView nfTxt = findViewById(R.id.stiffness_txt);
134         stiff.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
135             @Override
136             public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
137                 float stiffness = (float) Math.exp(i / 10d);
138                 mStiffness = stiffness;
139                 nfTxt.setText(String.format("%.3f", (float) stiffness));
140             }
141 
142             @Override
143             public void onStartTrackingTouch(SeekBar seekBar) {
144 
145             }
146 
147             @Override
148             public void onStopTrackingTouch(SeekBar seekBar) {
149 
150             }
151         });
152         dr.setProgress(40);
153         stiff.setProgress(60);
154     }
155 }
156