Java 动态更改自定义视图上的动画速度

Java 动态更改自定义视图上的动画速度,java,android,android-animation,Java,Android,Android Animation,首先,谈到android,我不是一个神童。把它拿出来 我需要一个图像不断旋转,当我提供输入时,更新旋转速度。目前,每次单击按钮时,我都会创建一个新的ObjectAnimator。这将从文本字段中获取一个值,并将其作为持续时间应用于ObjectAnimator。这确实有效,但它会在每次单击按钮时重置动画。我需要动画平滑地改变速度,每次我点击 我觉得在这里使用ObjectAnimator可能是错误的,但我不知道还有什么更好的选择 需要注意的一点是,我的API最大值为18 public class S

首先,谈到android,我不是一个神童。把它拿出来

我需要一个图像不断旋转,当我提供输入时,更新旋转速度。目前,每次单击按钮时,我都会创建一个新的ObjectAnimator。这将从文本字段中获取一个值,并将其作为持续时间应用于ObjectAnimator。这确实有效,但它会在每次单击按钮时重置动画。我需要动画平滑地改变速度,每次我点击

我觉得在这里使用ObjectAnimator可能是错误的,但我不知道还有什么更好的选择

需要注意的一点是,我的API最大值为18

public class SpinActivity extends Activity {

  private CustomView customView;
  private Button button;
  private EditText input;


  @Override
  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.spin_activity);

        //Init Variables
        customView = (CustomView) findViewById(R.id.spinner_custom_view);
        button = (Button) findViewById(R.id.spinner_button);
        input = (EditText) findViewByIdR.id.speed);

        //Set up the button to animate the custom view
        button.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                    float fSpeed = Float.parseFloat(txtSpeed.getText().toString());

                    customView.animateBitmap(fSpeed);
              }
        });
  }
}//末端脊柱活动

公共类CustomView扩展了视图{

  private static final String TAG = CustomView.class.getSimpleName();

  private Bitmap dialSpeedOuter;
  private Context context;
  private FrameLayout activityFrame;


  public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
  }


  @Override
  protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (dialSpeedOuter == null) {
              BitmapFactory.Options vmOptions = new BitmapFactory.Options();
              vmOptions.inDensity = 800;
              vmOptions.inJustDecodeBounds = false;
              dialSpeedOuter = BitmapFactory.decodeResource(context.getResources(), R.drawable.spinner, vmOptions);
        }
  }

  public void animateBitmap(long speed) {
        long spinDuration = speed; //sets duration in ms

        ObjectAnimator spin = ObjectAnimator.ofFloat(this , "rotation", 0.0f, 360.0f);
        spin.setRepeatMode(ObjectAnimator.RESTART);
        spin.setRepeatCount(ObjectAnimator.INFINITE);
        spin.setInterpolator(new LinearInterpolator());
        spin.setDuration(spinDuration);

        spin.start();
  }

}//end CustomView

对象animator将比使用画布手动处理视图旋转更易于使用

为了简单起见,我在默认的Android应用程序项目(最新的一个有这个片段的项目)中编写了自己的小演示,其中时间减少了1/2。您应该能够根据需要调整代码。(你也不需要把它放在集合中。我只是把它放在那里,因为我从其他代码中复制了一些代码,但在测试之前忘了把它拿出来)


除了我的评论之外,还有一些类似的东西:

public class CustomView extends View {

  private static float ROATION_ANGLE_INCREMENT = 1;
  private static float ROATION_SPEED_INCREMENT = 10;

  private Thread animationThread; 
  private long sleepTime = 100;
  private float rotationAngle = 0; 

  public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
  }

  @Override
  protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.rotate(rotationAngle, canvas.getWidth()/2, canvas.getHeight()/2));
        super.onDraw(canvas);
        canvas.restore();
  }

  public void startRotation(){
      isActive = true;
      animationThread = new Thread(new Runnable(){
          public void run() {
              while(isActive){
                  try{
                      rotationAngle = (rotationAngle + ROATION_ANGLE_INCREMENT) % 360;
                      CustomView.this.postInvalidate();
                      Thread.sleep(sleepDelay);
                  }
                  catch(Exception e){ }
              }
          }
      });
      animationThread.start();
  }

  private void onIncreaseSpeed(){
      sleepTime -= ROTATION_SPEED_INCREMENT;
  }     

  private void stop(){
      try{
          isActive = false;
          animationThread.stop();
      }
      catch(Exception e){}
  }        
}
我在没有测试或编译器的情况下就这么做了,所以你肯定要对它和所有默认值进行一些调整,以匹配你想要的结果


您可能还希望使其扩展布局,而不是视图,并使视图位于其中,以便图像不会被切断。

您可以使用动画可绘制,它允许您提供帧图像+帧间动画所需的时间纠正我的错误,但动画可绘制不是仅用于帧动画吗?我只需要旋转一个图像。听起来像是一个图像在旋转,而不是一组图像,所以这不适用于。。。您是否尝试过不使用任何动画对象,并通过视图的onDraw方法手动处理旋转(即使用画布旋转显示的可绘制对象),然后使用单独的线程处理“动画”(即通过减少无效调用之间的睡眠时间来增加动画速度)有一个帖子,一个家伙抱怨说,这种类型的动画在屏幕旋转时做了奇怪的事情。在画布上绘制了多幅图像。在android中,你永远不应该睡眠线程。您应该改为使用具有延迟后操作的处理程序。另外,在执行run方法之前(调度另一个处理程序),您必须检查活动是否正在完成,因为如果正在完成,可能会导致崩溃-该方法是“isFinishing()”@LenaBru您能告诉我您在哪里读到“android中的从不睡眠线程”,因为这听起来很可笑。是的,使用处理程序的postDelayed函数是一种选择,但这并不意味着它是唯一的选择,也不是最好的选择。在这种情况下,Thread.sleep()可以正常工作。至于你读到的另一篇文章,其中画了多幅图像:这与画布无关,与错误使用画布的人有关。
public class CustomView extends View {

  private static float ROATION_ANGLE_INCREMENT = 1;
  private static float ROATION_SPEED_INCREMENT = 10;

  private Thread animationThread; 
  private long sleepTime = 100;
  private float rotationAngle = 0; 

  public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
  }

  @Override
  protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.rotate(rotationAngle, canvas.getWidth()/2, canvas.getHeight()/2));
        super.onDraw(canvas);
        canvas.restore();
  }

  public void startRotation(){
      isActive = true;
      animationThread = new Thread(new Runnable(){
          public void run() {
              while(isActive){
                  try{
                      rotationAngle = (rotationAngle + ROATION_ANGLE_INCREMENT) % 360;
                      CustomView.this.postInvalidate();
                      Thread.sleep(sleepDelay);
                  }
                  catch(Exception e){ }
              }
          }
      });
      animationThread.start();
  }

  private void onIncreaseSpeed(){
      sleepTime -= ROTATION_SPEED_INCREMENT;
  }     

  private void stop(){
      try{
          isActive = false;
          animationThread.stop();
      }
      catch(Exception e){}
  }        
}