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

时间:2014-07-18 20:10:35

标签: java android android-animation

首先,关于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);
              }
        });
  }

} //结束SpinActivity

公共类CustomView扩展了View {

  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();
  }

} //结束CustomView

2 个答案:

答案 0 :(得分:1)

对象动画制作者比使用画布手动处理视图的旋转更容易使用。

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

public static class PlaceholderFragment extends Fragment {
    Button btn_B;
    TextView hello;
    ObjectAnimator mAnimation;
    AnimatorSet transSet;
    Float valuefrom=0f;
    Float valueto=-360f;
    long speed= 500;

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);
        btn_B= (Button) rootView.findViewById(R.id.button2);
        hello= (TextView) rootView.findViewById(R.id.textView1);


        btn_B.setOnClickListener(new OnClickListener() 
        {         
            public void onClick(View v) 
            {
                Float save = (Float) mAnimation.getAnimatedValue();
                Log.d("TAG", "Value" +save);
                valuefrom= save;
                valueto= save-360;
                speed= speed/2;
                transSet.cancel();
                doObjectAnimator();
            }
        });
        doObjectAnimator();
        return rootView;
    }

    public void doObjectAnimator(){
        mAnimation= ObjectAnimator.ofFloat(hello, "rotation", valuefrom, valueto);
        mAnimation.setInterpolator(new LinearInterpolator());
        mAnimation.setDuration(speed);
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.RESTART);
        transSet= new AnimatorSet();
        transSet.play(mAnimation);
        transSet.start();
    }
}

答案 1 :(得分:1)

在我的评论中添加一些内容:

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){}
  }        
}

我在没有测试或编译器的情况下做到了这一点,所以你肯定要调整它以及所有默认值以匹配你想要的结果...

您可能还想让它扩展布局,而不是视图,并让视图在其中生效,这样图像就不会被切断。