我现在在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.
更多推荐
发布评论