1+ /*
2+ * Copyright (C) 2023 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 android .support .drag2d ;
18+
19+
20+ import android .content .Context ;
21+ import android .graphics .Canvas ;
22+ import android .graphics .Color ;
23+ import android .graphics .Paint ;
24+ import android .graphics .drawable .Drawable ;
25+ import android .os .Bundle ;
26+ import android .os .SystemClock ;
27+ import android .support .drag2d .lib .MaterialEasing ;
28+ import android .support .drag2d .lib .MaterialVelocity ;
29+ import android .support .drag2d .lib .Velocity2D ;
30+ import android .util .AttributeSet ;
31+ import android .view .MotionEvent ;
32+ import android .view .VelocityTracker ;
33+ import android .view .View ;
34+ import android .view .Window ;
35+ import android .widget .Button ;
36+ import android .widget .LinearLayout ;
37+ import android .widget .ScrollView ;
38+
39+ import androidx .annotation .Nullable ;
40+ import androidx .appcompat .app .AppCompatActivity ;
41+ import androidx .appcompat .widget .AppCompatButton ;
42+ import androidx .core .content .res .ResourcesCompat ;
43+
44+ import com .google .android .material .button .MaterialButton ;
45+
46+
47+ public class MainActivity extends AppCompatActivity {
48+ int backgroundColor = 0xFF000000 |(200 *256 +250 )*256 +200 ;
49+ static String []sEasingNames = {
50+ "DECELERATE" ,
51+ "LINEAR" ,
52+ "OVERSHOOT" ,
53+ "EASE_OUT_SINE" ,
54+ "EASE_OUT_CUBIC" ,
55+ "EASE_OUT_QUINT" ,
56+ "EASE_OUT_CIRC" ,
57+ "EASE_OUT_QUAD" ,
58+ "EASE_OUT_QUART" ,
59+ "EASE_OUT_EXPO" ,
60+ "EASE_OUT_BACK" ,
61+ "EASE_OUT_ELASTIC" ,
62+ "EASE_OUT_BOUNCE"
63+ };
64+ static MaterialVelocity .Easing [] sEasings = {
65+ MaterialEasing .DECELERATE ,
66+ MaterialEasing .LINEAR ,
67+ MaterialEasing .OVERSHOOT ,
68+ MaterialEasing .EASE_OUT_SINE ,
69+ MaterialEasing .EASE_OUT_CUBIC ,
70+ MaterialEasing .EASE_OUT_QUINT ,
71+ MaterialEasing .EASE_OUT_CIRC ,
72+ MaterialEasing .EASE_OUT_QUAD ,
73+ MaterialEasing .EASE_OUT_QUART ,
74+ MaterialEasing .EASE_OUT_EXPO ,
75+ MaterialEasing .EASE_OUT_BACK ,
76+ MaterialEasing .EASE_OUT_ELASTIC ,
77+ MaterialEasing .EASE_OUT_BOUNCE
78+ };
79+ @ Override
80+ protected void onCreate (Bundle savedInstanceState ) {
81+ super .onCreate (savedInstanceState );
82+ requestWindowFeature (Window .FEATURE_ACTION_BAR );
83+ LinearLayout row = new LinearLayout (this );
84+ LinearLayout col = new LinearLayout (this );
85+ col .setOrientation (LinearLayout .VERTICAL );
86+ ScrollView scrollView = new ScrollView (this );
87+ BallMover m = new BallMover (this );
88+ for (int i = 0 ; i < sEasingNames .length ; i ++) {
89+ AppCompatButton b = new AppCompatButton (this );
90+ b .setText (sEasingNames [i ]);
91+ MaterialVelocity .Easing easing = sEasings [i ];
92+ b .setTextAlignment (View .TEXT_ALIGNMENT_CENTER );
93+
94+ b .setPadding (1 ,1 ,5 ,5 );
95+ col .addView (b );
96+ b .setOnClickListener (c ->{m .setEasing (easing );});
97+
98+ }
99+ col .setBackgroundColor (backgroundColor );
100+ scrollView .addView (col );
101+ row .addView (scrollView );
102+ row .addView (m );
103+ setContentView (row );
104+
105+ }
106+
107+ static class BallMover extends View {
108+ Drawable ball ;
109+ VelocityTracker velocityTracker = VelocityTracker .obtain ();
110+ Velocity2D velocity2D = new Velocity2D ();
111+ int ballX ;
112+ int ballY ;
113+ int ballW = 128 ;
114+ int ballH = 128 ;
115+ MaterialVelocity .Easing easing = null ;
116+ float [] points = new float [10000 ];
117+ Paint paint = new Paint ();
118+
119+
120+ public BallMover (Context context ) {
121+ super (context );
122+ setup (context );
123+ }
124+
125+ public BallMover (Context context , @ Nullable AttributeSet attrs ) {
126+ super (context , attrs );
127+ setup (context );
128+ }
129+
130+ public BallMover (Context context , @ Nullable AttributeSet attrs , int defStyleAttr ) {
131+ super (context , attrs , defStyleAttr );
132+ setup (context );
133+ }
134+
135+
136+ void setup (Context context ) {
137+ ball = ResourcesCompat .getDrawable (context .getResources (), R .drawable .volleyball , null );
138+ paint .setStrokeWidth (3 );
139+ }
140+ public void setEasing (MaterialVelocity .Easing easing ) {
141+ this .easing = easing ;
142+ }
143+ @ Override
144+ protected void onDraw (Canvas canvas ) {
145+ canvas .drawRGB (200 ,250 ,200 );
146+ if (startAnimationTime != 0 ) {
147+
148+ long timeMillis = SystemClock .uptimeMillis () - startAnimationTime ;
149+ float time = timeMillis / 1000f ;
150+ ballX = (int ) velocity2D .getX (time );
151+ ballY = (int ) velocity2D .getY (time );
152+
153+ if (velocity2D .isStillMoving (time )) {
154+ invalidate ();
155+ } else {
156+ startAnimationTime = 0 ;
157+ }
158+ canvas .drawLines (points , paint );
159+ }
160+
161+ ball .setBounds (getWidth () / 2 , getHeight () / 2 , ballW + getWidth () / 2 , ballH + getHeight () / 2 );
162+ ball .setTint (Color .CYAN );
163+ ball .draw (canvas );
164+ ball .setBounds (ballX , ballY , ballW + ballX , ballH + ballY );
165+ ball .setTint (Color .BLACK );
166+ ball .draw (canvas );
167+ }
168+
169+ float touchDownX ;
170+ float touchDownY ;
171+ float touchDeltaX , touchDeltaY ;
172+ int ballDownX , ballDownY ;
173+ long startAnimationTime ;
174+
175+
176+ @ Override
177+ public boolean onTouchEvent (MotionEvent event ) {
178+ velocityTracker .addMovement (event );
179+ switch (event .getAction ()) {
180+
181+ case MotionEvent .ACTION_DOWN :
182+ System .out .println ("------- down ---------" );
183+
184+ startAnimationTime = 0 ;
185+ touchDownX = event .getX ();
186+ touchDownY = event .getY ();
187+ ballDownX = ballX ;
188+ ballDownY = ballY ;
189+ break ;
190+
191+ case MotionEvent .ACTION_MOVE :
192+ System .out .println ("------- move ---------" );
193+
194+ touchDeltaX = event .getX () - touchDownX ;
195+ touchDeltaY = event .getY () - touchDownY ;
196+ ballX = (int ) (ballDownX + touchDeltaX );
197+ ballY = (int ) (ballDownY + touchDeltaY );
198+ invalidate ();
199+
200+ break ;
201+ case MotionEvent .ACTION_UP :
202+ System .out .println ("------- UP ---------" );
203+
204+ velocityTracker .computeCurrentVelocity (1000 );
205+ float velocityX = velocityTracker .getXVelocity ();
206+ float velocityY = velocityTracker .getYVelocity ();
207+ System .out .println ("initial velocity " + velocityX + "," + velocityY );
208+ startAnimationTime = event .getEventTime ();
209+ velocity2D .configure (ballX , ballY ,
210+ velocityX , velocityY ,
211+ getWidth () / 2 , getHeight () / 2 ,
212+ 4 , 1000 , 1000 ,
213+ easing );
214+ velocity2D .getCurves (points , getWidth (), getHeight ());
215+ invalidate ();
216+ break ;
217+
218+ }
219+ return true ;
220+ }
221+ }
222+ }
0 commit comments