Android:onDraw不断调用或动画弹回到原始位置
所以,我的问题有点类似于这两个问题:
我有一个自定义类扩展我将 RotateAnimation 应用于 ImageView。动画使用输入的 x 和 y 坐标来执行从上一个角度到下一个角度的旋转,以便用户可以根据需要将 ImageView 从 -360 度旋转到 360 度。当我将这段代码用于 onDraw() 时,屏幕上的一切看起来都很完美(动画设置如下面的代码所示):
@Override
protected void onDraw(Canvas canvas) {
Log.d(TAG, "It is drawn again!");
this.setAnimation(anim);
super.onDraw(canvas);
}
问题在于,与提到的其他帖子中相同的方式,动画调用 onDraw可能通过 RotateAnimation 类中的 invalidate() 调用动画等。这是正确观察的吗?输出是完美的,因为 ImageView 始终保持在当前计算的角度,但动画计算因此继续进行,消耗大量的电力和容量。
为了解决这个问题,我尝试在计算动画参数的方法中移动 this.setAnimation(anim) (请忽略 isClockWise()、calculateAngleToMove() 和其他非 android 的东西,它们按预期工作):
private void turnWheel(){
float angle = 0;
if ( isClockWise() ){
angle = calculateAngleToMove();
anim = new RotateAnimation(current_angle, angle, center_x, center_y);
anim.setFillAfter(true);
anim.setFillEnabled(true);
current_angle += angle;
}
else{
angle = - calculateAngleToMove();
anim = new RotateAnimation(current_angle, angle, center_x, center_y);
anim.setFillAfter(true);
anim.setFillEnabled(true);
current_angle += angle;
}
if ( current_angle > 360 ){
current_angle = current_angle - 360;
}
if ( current_angle < -360 ){
current_angle = current_angle + 360;
}
this.setAnimation(anim);
this.invalidate(); //Calls onDraw()
}
这解决了onDraw 不断被调用的问题,但它又产生了另一个问题:当用户推动、按住并旋转 ImageView 时,它会在零角度和当前角度之间来回捕捉。当用户放开 ImageView 时,它会恢复到零角度。希望 ImageView 始终以变量 current_angle 旋转,即使在用户不提供输入时也是如此。
我尝试过不同版本的 anim.setFillAfter(true)、anim.setFillEnabled(true)、invalidate() 和 this.startAnimation(anim),但它们似乎对这个问题没有任何影响。
调用 this.setAnimation(anim) 的最佳位置在哪里?
So, my question is somewhat similar to these two questions:
Custom View onDraw is constantly called
android: onDraw is called constantly
I have a custom class extending ImageView which I apply a RotateAnimation to. The animation uses input x- and y-coordinates to perform a rotation from the last angle to the next so the user can turn the ImageView as wanted, from -360 degrees to 360 degrees. When I use this code for onDraw() everything looks perfect on screen (the animation is set as in the code further below):
@Override
protected void onDraw(Canvas canvas) {
Log.d(TAG, "It is drawn again!");
this.setAnimation(anim);
super.onDraw(canvas);
}
The problem with this is that, in the same manner as in the other posts mentioned, the animation calls onDraw which calls animation and so forth, probably through invalidate() in the RotateAnimation class. Is this correctly observed? The output is perfect since the ImageView always stays at the current calculated angle, but the animation calulations thus keep on going, consuming lots of power and capacity.
To fix this I tried to move the this.setAnimation(anim) in the method where the parameters for the animation are calculated (please ignore isClockWise(), calculateAngleToMove() and other non-android stuff, they work as intended):
private void turnWheel(){
float angle = 0;
if ( isClockWise() ){
angle = calculateAngleToMove();
anim = new RotateAnimation(current_angle, angle, center_x, center_y);
anim.setFillAfter(true);
anim.setFillEnabled(true);
current_angle += angle;
}
else{
angle = - calculateAngleToMove();
anim = new RotateAnimation(current_angle, angle, center_x, center_y);
anim.setFillAfter(true);
anim.setFillEnabled(true);
current_angle += angle;
}
if ( current_angle > 360 ){
current_angle = current_angle - 360;
}
if ( current_angle < -360 ){
current_angle = current_angle + 360;
}
this.setAnimation(anim);
this.invalidate(); //Calls onDraw()
}
This solves the problem with onDraw constantly being called, but it creates another: when the user pushes, holds and turns the ImageView, it snaps back and forth between zero angle and the current angle. When the user then lets go of the ImageView, it snaps back to zero angle. It is wanted to always have the ImageView rotated at the variable current_angle, also when the user doesn't provide input.
I have tried different versions of anim.setFillAfter(true), anim.setFillEnabled(true), invalidate() and this.startAnimation(anim), but they never seem to have any effect on this problem.
Where is the best place to call this.setAnimation(anim)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我可能建议不要使用
Animation
框架将静态转换应用于视图,这样您就不必在每次应用新的Animation
时处理因重置而导致的问题时间。如果您希望旋转的内容仅包含图像,请考虑将图像包装在
RotateDrawable
中,并将其设置为ImageView
的内容。这样,您可以通过设置其级别值来控制可绘制对象的旋转方式(Drawable.setLevel()
或ImageView.setImageLevel()
应该可以解决问题),并且转换将戳。如果您需要在一段时间内自动执行动画,您可以简单地调用Handler
内部的级别设置代码,该代码会经常发布更新。另一种选择是创建自定义
ViewGroup
并使用getChildStaticTransformation()
方法将旋转应用于任何子视图(请务必启用它或覆盖已经存在的子类)已启用)。Transformation
也是Animation
框架用来修改视图外观的方法。在这种情况下,当用户输入更改时,您可能仍然需要调用invalidate()
以强制重新绘制。如果您想定期自动执行更改,则将应用相同的Handler
规则。RotateDrawable 示例
假设您要旋转的图像位于 res/drawable/wheel.png,请在 res/drawable/wheel_rotate.xml 创建一个简单的 XML 文件:
将图像包装到
可旋转绘制
。然后,在 Java 代码中将该可绘制对象设置为ImageView
的内容:默认情况下,级别范围为 0 到 10,000。因此,这映射到 0 level = fromDegrees 和 10,000 level = toDegrees。
华泰
I might recommend not using the
Animation
framework to apply static transformations to views so that you don't have to deal with the issues caused by resetting when you apply a newAnimation
each time.If the contents you wish to rotate just includes imagery, consider wrapping your image(s) in a
RotateDrawable
and set that as the content of yourImageView
. With this you can control how the drawable rotates by setting its level value (eitherDrawable.setLevel()
orImageView.setImageLevel()
should do the trick) and the transformation will stick. If you have a need to automate the animation for a period, you can simply call the level setting code inside of aHandler
that posts the updates every so often.Another option would be to create a custom
ViewGroup
and use thegetChildStaticTransformation()
method to apply the rotation to any child view (be sure to enable it or override a subclass that already has it enabled).Transformation
is what theAnimation
framework uses to modify view appearance as well. In this case, you would likely still need to callinvalidate()
when the user input changed in order to force the re-draw. The sameHandler
rule would apply if you wanted to automate the changes periodically.RotateDrawable Example
Let's say the image you are wanting to rotate is at res/drawable/wheel.png, create a simple XML file at res/drawable/wheel_rotate.xml:
To wrap your image into a
RotateDrawable
. Then, in your Java code set that drawable as the content of anImageView
:By default, a level ranges from 0 to 10,000. So that maps to 0 level = fromDegrees and 10,000 level = toDegrees.
HTH