更新:2013年11月20日:这仍未解决。
我正在尝试在自定义视图中设置圆圈的动画。我想为圆周的创建设置动画 - 在动画开始时有一个圆弧,在动画结束时,圆圈就完成了。
我按照以下答案成功完成了此操作 - https://stackoverflow.com/a/11168363/2442638 - 只需添加重复Handler
即可增加sweepAngle
并致电invalidate();
然而,由于我无法设置完成圆圈的持续时间,因此无法按照我希望的方式工作。
这是我目前的代码:
Path mOuterCirclePath = new Path();
final RectF mOval = new RectF();
int mSweepAngle = 0;
int mStartAngle = -90;
@Override
protected void onDraw(Canvas canvas) {
mOval.set(0, 0, mBorderRect.right, mBorderRect.bottom); //mBorderRect is the outside border of my view
mOuterCirclePath.arcTo(mOval, 0, 0, true);
canvas.drawArc(mOval, -mStartAngle, mSweepAngle, false,
mOuterCirclePaint);
}
public void drawOuterCircle() {
startUpdateOuterCircle();
}
Runnable mCircleInvalidator = new Runnable() {
@Override
public void run() {
if (mSweepAngle <= 360) {
mSweepAngle++
}
invalidate();
mHandler.postDelayed(mCircleInvalidator, 20);
}
};
void startUpdateOuterCircle() {
mCircleInvalidator.run();
}
void stopUpdateOuterCircle() {
mHandler.removeCallbacks(mCircleInvalidator);
}
主要问题是:如何设置动画的持续时间?我希望这很容易改变,就像在动画师课程中一样。
P.S。据我所知,我不能使用任何动画师,例如'{1}}'ObjectAnimator'。如果我错了,请纠正我!
答案 0 :(得分:1)
使用处理程序,您的邮件无法保证准时到达,因此动画可能看起来很奇怪。
如果您想使用drawArc代码,可以使用PropertyAnimation。在onAnimationUpdate()方法上,您将使视图无效。 请注意,invalidate既不是同步保证。如果动画非常快,它可能会跳过一些帧。
您有另一个解决方案Drawable Animation。你将有无聊的任务来创建动画所需的图像,但它很容易实现。
答案 1 :(得分:1)
要使用自定义对象动画属性,您需要按照此Stackoverflow答案中的说明创建getter和setter方法:
就我而言,我有一个CircleView
类和sweepAngle
作为变量,如下所示:
public class CircleView extends View
{
public float sweepAngle = 0.0f; // start at 0 degrees
...
// ---------------------------------------------------
// getter and setter method to turn "sweepAngle"
// into a property for ObjectAnimator to use
// ---------------------------------------------------
public float getSweepAngle()
{
return sweepAngle;
}
public void setSweepAngle(float angle)
{
sweepAngle = angle;
}
// ---------------------------------------------------
// animation method to be called outside this class
// ---------------------------------------------------
public void animateArc(float fromAngle, float toAngle, long duration)
{
sweepAngle = fromAngle;
invalidate();
ObjectAnimator anim = ObjectAnimator.ofFloat(this, "sweepAngle", fromAngle, toAngle);
anim.setDuration(duration);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
// calling invalidate(); will trigger onDraw() to execute
invalidate();
}
});
anim.start();
}
}
以上具体示例是Hithredin建议使用ObjectAnimator的演示。
我建议你不要在下面使用这个代码块,但是如果你想知道我是如何进行我自己的自定义实现的话,我会把它包括在内,我发现它是8毫秒,只允许线性插值(不容易) /缓出),它就像上面的代码,但略有不同:
public void animateArc(float fromAngle, float toAngle, long duration)
{
sweepAngle = fromAngle;
invalidate();
// ---------------------------------------------------------------
// Note: might want to change use absolute value for totalAngle
// in case you want the animation to play backwards
// ---------------------------------------------------------------
float totalAngle = toAngle - fromAngle;
updateArc(totalAngle, duration);
}
public void updateArc(final float totalAngle, final long durationInMilliSeconds)
{
final long stepMilliseconds = 1;
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
// ------------------------------------------------
// 17790.0 is a number I fine tuned and came out
// with on my Android phone to get the animation
// as close as possible to the animation
// duration specified
// ------------------------------------------------
double stepAngle = totalAngle / 1000.0 * (17790.0 / durationInMilliSeconds);
sweepAngle += stepAngle;
animationTime += stepMilliseconds;
invalidate();
if(animationTime < durationInMilliSeconds && sweepAngle < totalAngle)
{
updateArc(totalAngle, durationInMilliSeconds);
}
else
{
// --------------------------------------------------------
// time duration reached, stop incrementing/decrementing
// angle and reset animation time back to 0
// --------------------------------------------------------
animationTime = 0;
}
}
}, 0);
}