基于用户拖动事件的动画持续时间(Duration of animation based on user drag event)

编程入门 行业动态 更新时间:2024-10-27 15:17:53
基于用户拖动事件的动画持续时间(Duration of animation based on user drag event)

我现在在SpinTheBottle应用程序上工作,我的瓶子正在旋转,但我希望旋转的速度将基于用户onTouch事件,我希望它在随机位置停止,我可以拖动瓶子,但动画始终开始从中心开始,在两次旋转之后停止在与开始时相同的位置。

我究竟做错了什么?

我的代码:

@Override public boolean onTouch(View v, MotionEvent event) { final float xc = bottle.getWidth() / 2; final float yc = bottle.getHeight() / 2; final float x = event.getX(); final float y = event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: { bottle.clearAnimation(); mCurrAngle = Math.toDegrees(Math.atan2( x - xc, yc - y)); break; }case MotionEvent.ACTION_MOVE: { mPrevAngle = mCurrAngle; mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y)); animate(mPrevAngle, mCurrAngle, 0); System.out.println(mCurrAngle); break; }case MotionEvent.ACTION_CANCEL: { mPrevAngle = mCurrAngle = 0; float toDegrees = new Random().nextFloat() * Integer.MAX_VALUE % 360; final Animation animRotate = AnimationUtils.loadAnimation(this, R.anim.mainanim); animRotate.setDuration(1000); animRotate.setRepeatCount(1); animRotate.setFillAfter(true); bottle.startAnimation(animRotate); break; }case MotionEvent.ACTION_UP:{ } } return true; } private void animate(double fromDegrees, double toDegrees, long durationMillis){ final RotateAnimation rotate = new RotateAnimation((float) fromDegrees, (float) toDegrees, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(durationMillis); rotate.setFillEnabled(true); rotate.setFillAfter(true); bottle.startAnimation(rotate); System.out.println(mCurrAngle); }

动画布局:

<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:pivotX="50%" android:pivotY="50%" android:fromDegrees="0" android:toDegrees="360" android:drawable="@drawable/campari" android:duration="2500" android:fillAfter="true" android:fillBefore="true" android:fillEnabled="true" android:repeatCount="1" />

I now work on SpinTheBottle app, my bottle is spinning, but I want the speed of the spinning will be based on the users onTouch event, and I want it to be stopped at random positions, I can drag the bottle but the animation always starts from the center and after 2 rotations stops at the same position as in the beginning.

What am I doing wrong?

my code:

@Override public boolean onTouch(View v, MotionEvent event) { final float xc = bottle.getWidth() / 2; final float yc = bottle.getHeight() / 2; final float x = event.getX(); final float y = event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: { bottle.clearAnimation(); mCurrAngle = Math.toDegrees(Math.atan2( x - xc, yc - y)); break; }case MotionEvent.ACTION_MOVE: { mPrevAngle = mCurrAngle; mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y)); animate(mPrevAngle, mCurrAngle, 0); System.out.println(mCurrAngle); break; }case MotionEvent.ACTION_CANCEL: { mPrevAngle = mCurrAngle = 0; float toDegrees = new Random().nextFloat() * Integer.MAX_VALUE % 360; final Animation animRotate = AnimationUtils.loadAnimation(this, R.anim.mainanim); animRotate.setDuration(1000); animRotate.setRepeatCount(1); animRotate.setFillAfter(true); bottle.startAnimation(animRotate); break; }case MotionEvent.ACTION_UP:{ } } return true; } private void animate(double fromDegrees, double toDegrees, long durationMillis){ final RotateAnimation rotate = new RotateAnimation((float) fromDegrees, (float) toDegrees, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); rotate.setDuration(durationMillis); rotate.setFillEnabled(true); rotate.setFillAfter(true); bottle.startAnimation(rotate); System.out.println(mCurrAngle); }

anim layout:

<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator" android:pivotX="50%" android:pivotY="50%" android:fromDegrees="0" android:toDegrees="360" android:drawable="@drawable/campari" android:duration="2500" android:fillAfter="true" android:fillBefore="true" android:fillEnabled="true" android:repeatCount="1" />

最满意答案

我究竟做错了什么?

很多东西。 Fe您正在ACTION_MOVE中实现动画,MotionEvent.ACTION_CANCEL中的随机数,此外还有一个额外的xml RotateAnimation,您不需要它。

我会在这里采取一种非常不同的方法。 对于一般的动画检查ViewPropertyAnimator及其方法,它是动画视图最简单的方法。 继承人:

旋转连接到Touch事件的瓶子的最小示例:

int start = 1000; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: start = 1000; break; case MotionEvent.ACTION_MOVE: start = start + 250; break; case MotionEvent.ACTION_UP: Random random = new Random(); int toDegrees = random.nextInt(start); int duration = random.nextInt(start + 1000); bottle.animate() .rotation(toDegrees) .setInterpolator(new DecelerateInterpolator()) .setDuration(duration); break; } return true; }

这具有start = 1000的最小持续时间/旋转; :

case MotionEvent.ACTION_DOWN: start = 1000; break;

,在屏幕上移动的时间越长,开始的时间越长,并且持续时间/轮换的时间越长:

case MotionEvent.ACTION_MOVE: start = start + 250; break;

然后,当你松开屏幕时,创建随机数:

case MotionEvent.ACTION_UP: Random random = new Random(); int toDegrees = random.nextInt(start); int duration = random.nextInt(start + 1000);

它将在0和'start'之间生成一个随机数。

这是ViewPropertyAnimator旋转你的瓶子的速度和你产生的随机旋转/持续时间:

bottle.animate() .rotation(toDegrees) .setInterpolator(new DecelerateInterpolator()) .setDuration(duration);

基本上所有你需要的,只是给你一个替代的想法,在我看来,更好的方法为未来的动画。

What am I doing wrong?

Many things. F.e. You are implementing your animation in ACTION_MOVE, random numbers in MotionEvent.ACTION_CANCEL , plus you have an extra xml RotateAnimation, which you don't need.

I would go a very different approach here. For general animations check out ViewPropertyAnimator and its methods, its the easiest way to animate Views. Heres something to start with :

Minimal example for spinning your bottle connected to a Touch Event :

int start = 1000; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: start = 1000; break; case MotionEvent.ACTION_MOVE: start = start + 250; break; case MotionEvent.ACTION_UP: Random random = new Random(); int toDegrees = random.nextInt(start); int duration = random.nextInt(start + 1000); bottle.animate() .rotation(toDegrees) .setInterpolator(new DecelerateInterpolator()) .setDuration(duration); break; } return true; }

This has a minimum duration/rotation of start = 1000; :

case MotionEvent.ACTION_DOWN: start = 1000; break;

, and the longer you move around on the screen the bigger start gets and with it the duration/rotation :

case MotionEvent.ACTION_MOVE: start = start + 250; break;

Then when you let go of the screen create Random numbers :

case MotionEvent.ACTION_UP: Random random = new Random(); int toDegrees = random.nextInt(start); int duration = random.nextInt(start + 1000);

where it will generate a random number between 0 and 'start' .

This is ViewPropertyAnimator rotating your bottle with decreasing speed and your generated random rotation/duration:

bottle.animate() .rotation(toDegrees) .setInterpolator(new DecelerateInterpolator()) .setDuration(duration);

Thats basically all you need, and just to give you an idea of an alternative, and in my opinion, better approach for future Animations.

更多推荐

本文发布于:2023-07-24 00:17:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1239160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:拖动   持续时间   事件   动画   用户

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!