我目前正在开发一个应用程序,其中我想指出一个带箭头的路径(它就像一个指南针)。
为了将箭头移动到正确的方向,我使用RotateAnimation
类。它工作得很好但是当初始度数位置远离最终度数位置时,旋转不会选择更快的方式。
在此视频中,您可以看到行为:https://youtu.be/vypZni_1s3I
这里是用户点击按钮时执行的代码" 02" :
RotateAnimation rotateAnimation = new RotateAnimation(355f, 8f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);
这里是用户点击按钮" 03" :
RotateAnimation rotateAnimation = new RotateAnimation(8f, 350f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);
正如您在视频中看到的那样,旋转不会选择更快的方式。在第一个动画中,更快的方法是顺时针旋转(但系统选择逆时针旋转),在第二个动画中,更快的方法是逆时针旋转(但系统选择顺时针旋转)。
是否有解决方案或技巧迫使系统选择更快的方式从A点旋转到B点?
答案 0 :(得分:6)
如果参数toDegrees
大于参数fromDegrees
,RotationAnimation对象将顺时针转动。你必须自己处理这样一个事实:你不想从355f
到8f
,而是从355f
到368f
(这是360度加8度) )。
所以在这里你可以改变你的两段代码如下:
RotateAnimation rotateAnimation = new RotateAnimation(355f, 368f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);
和
RotateAnimation rotateAnimation = new RotateAnimation(368f, 350f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(3000);
rotateAnimation.setFillAfter(true);
test.startAnimation(rotateAnimation);
但我建议你,如果你愿意使用API 14+创建一个应用程序来使用animate()
这样的View
方法:
test.animate()
.rotationBy(13f)
.setDuration(3000)
.setInterpolator(new LinearInterpolator())
.start();
rotationBy(offset)
方法会将您的视图 - 中心枢轴 - 旋转offset
度,如果偏移为正,则顺时针旋转,否则逆时针旋转。
答案 1 :(得分:2)
+1 @MaximeClaude,但答案可以大大缩短:
//declarations
private static final int HALF_CIRCLE = 180;
private static final int WHOLE_CIRCLE = 360;
private float currentAzimuth = 0f;
public void rotate(float rotationDegrees, View... views) {
float from = currentAzimuth;
float to = rotationDegrees;
float min = Math.min(from, to);
if (Maths.abs(to - from) > HALF_CIRCLE) {
if (min == from) {
from += WHOLE_CIRCLE;
} else {
to += WHOLE_CIRCLE;
}
}
currentAzimuth = rotationDegrees;
Animation anim = new RotateAnimation(from, to, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setFillAfter(true); //make the arrow stay at its destination (after rotation)
anim.setDuration(200);
for (View view : views) {
view.startAnimation(anim);
}
}
并使用android.view.OrientationEventListener
设置视图方向:
mOrientationEventListener = new OrientationEventListener(context) {
@Override
public void onOrientationChanged(int orientation) {
rotate(orientation, arrowView);
}
};
答案 2 :(得分:0)
对于后来问过的人来说,这是一个受@David Fournier的答案启发的一般案例:
//declarations
private static final int HALF_CIRCLE = 180;
private static final int WHOLE_CIRCLE = 360;
private float azimuth = 0f;
private float currenttAzimuth = 0f;
/**
* "will set rotation from " + currentAzimuth + " to " + azimuth
*/
public void rotate(Double bearing){
if(bearing != null) {
azimuth = (float)bearing.doubleValue();
float min = Math.min(azimuth,currenttAzimuth);
float tempAzimuth = 0.0f;
float tempCurrentAzimuth = 0.0f;
Animation rotateAnim = null;
if(Math.abs(azimuth - currenttAzimuth) > HALF_CIRCLE) {
if(min == currenttAzimuth) {
tempCurrentAzimuth = currenttAzimuth + WHOLE_CIRCLE;
tempAzimuth = azimuth;
}
else {
tempCurrentAzimuth = currenttAzimuth ;
tempAzimuth = azimuth + WHOLE_CIRCLE;
}
rotateAnim = new RotateAnimation(tempCurrentAzimuth, tempAzimuth,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
}
else {
rotateAnim = new RotateAnimation(currenttAzimuth, azimuth,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
}
currenttAzimuth = azimuth;
rotateAnim.setFillAfter(true); //make the arrow stay at its destination (after rotation)
rotateAnim.setDuration(500);
arrowView.startAnimation(rotateAnim);
}
}
答案 3 :(得分:0)
每次箭头都以不同的方式旋转。您可以选择其他角度。别忘了负角也是可用的。
您可以像这样使用animate()
:
if (view==button1) {
arrowImage.animate().rotation(0).start();
} else {
arrowImage.animate().rotation(-90).start();
}