在Android中,如何使用ObjectAnimator沿着曲线移动到点x?

5

我有一个名为“stone”的图像视图,并将其从当前位置移动到X,Y位置。我希望它沿着曲线移动。请告诉我如何做到这一点(我已将最小API设置为11)。

ObjectAnimator moveX = ObjectAnimator.ofFloat(stone, "x", catPos[0] );
ObjectAnimator moveY = ObjectAnimator.ofFloat(stone, "y", catPos[1] );
AnimatorSet as = new AnimatorSet();
as.playTogether(moveX, moveY);
as.start();

使用PathMeasure,它可以让你在任何想要的路径上移动。 - pskink
6个回答

9

我认为Budius的答案非常有用。

这里是我使用的动画对象:

目的:沿着路径“path”移动视图“view”

Android v21+:

// Animates view changing x, y along path co-ordinates
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "x", "y", path)

安卓v11及以上版本:

// Animates a float value from 0 to 1 
ValueAnimator pathAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);

// This listener onAnimationUpdate will be called during every step in the animation
// Gets called every millisecond in my observation  
pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

float[] point = new float[2];

@Override
    public void onAnimationUpdate(ValueAnimator animation) {
        // Gets the animated float fraction
        float val = animation.getAnimatedFraction();

        // Gets the point at the fractional path length  
        PathMeasure pathMeasure = new PathMeasure(path, true);
        pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null);

        // Sets view location to the above point
        view.setX(point[0]);
        view.setY(point[1]);
    }
});

类似于:Android,如何沿着路径移动位图?


1
这并没有提供问题的答案。如果想要批评或请求作者澄清,请在他们的帖子下方留言——你总可以在自己的帖子下评论,并且一旦你有足够的声望,你就能够评论任何帖子 - qwerty_so
感谢您的反馈。我已经添加了我的解决方案中的可工作代码,以使其成为完整的答案。希望这可以帮助! - Dileep P G
这个几乎可以工作,但似乎当动画完成时值会重置(ValueAnimator示例)。 - Matt Foley
你在这里犯了两个错误。首先,正如@MattFoley所提到的,ValueAnimator会在动画结束时重置值,因此您需要在PathMeasure构造函数中传递false而不是true。其次,您需要通过调用setTranslationX()setTranslationY()方法来平移视图,而不是通过调用setX()setY()方法来更改其位置。实际上,您下面有正确的答案,由@Budius编写。 - nullbyte

4

你有两个选择:

两者都需要一个定义你的曲线的Path对象:

Path path = new Path();
path. // define your curve here

如果仅使用Lollipop (API 21),请使用ObjectAnimator.ofFloat(...path),示例如下:

ObjectAnimator.ofFloat(stone, View.X, View.Y, path).start();

如果那不是一个选项,你可以使用AnimatorListener来接收每个动画帧的更新,并使用PathMeasure获取该点上的值,如下所示:

PathMeasure pm;
float point[] = {0f, 0f};

private final ValueAnimator.AnimatorUpdateListener listener = 
       new ValueAnimator.AnimatorUpdateListener(){

   @Override
   public void onAnimationUpdate (ValueAnimator animation) {
        float val = animation.getAnimatedFraction();
        pm.getPosTan(pm.getLength() * val, point, null);
        stone.setTranslationX(point[0]);
        stone.setTranslationY(point[1]);
   }
}

// and then to animate
pm = new PathMeasure(path, false);
ValueAnimator a = ValueAnimator.ofFloat(0.0f 1.0f);
a.setDuration(/* your duration */);
a.setInterpolator(/* your interpolator */);
a.addUpdateListener(listener);
a.start();

3

尝试使用插值器。例如,为x和y设置2个不同的插值器:

moveX.setInterpolator(new AccelerateDecelerateInterpolator());

moveY.setInterpolator(new DecelerateInterpolator());

还有更多的插值器(如LinearInterpolator、AccelerateInterpolator等),但我认为这些应该是你想要的组合。


巧妙,如此聪明 - Daniel Pína

2

感谢回答,但我已经找到了自己的答案。只需在Objectanimator语句中添加一些额外的x、y位置即可。它会在到达最终位置之前到达那些位置并跟踪路径!

ObjectAnimator moveX = ObjectAnimator.ofFloat(stone, "x", catPos[0]-20,catPos[0]-10,catPos[0] );

ObjectAnimator moveY = ObjectAnimator.ofFloat(stone, "y",catPos[1]-20,catPos[1]-10, catPos[1] );

当我尝试通过曲线移动ImageView时,我遇到了NPE。 path = new Path(); path.moveTo((float)(maxX/2)+(maxX/4),maxY/4); path.quadTo((float)(maxX/2)+(maxX/4),maxY/4, (float)(maxX/2)+(maxX/4)+30,maxY/2); ObjectAnimator animator = new ObjectAnimator(); animator.ofFloat(img,View.X,View.Y,path); animator.setDuration(1000); animator.setStartDelay(600); animator.start();异常是:java.lang.NullPointerException: Attempt to get length of null array - Rakesh

0

Path类有多种方法可以创建非直线的图形,例如弧线、圆形、椭圆形、矩形、三次和二次贝塞尔曲线,您可以沿着这些路径动画对象。

正如Budius所指出的那样,您需要编写API 21(棒棒糖)或更高版本的代码才能使用对象平移的路径。现在已经超过两年了。

另一方面,在“野外”使用路径的“不止非常简单”的示例似乎很少,因此也许还没有流行起来的原因。


0

点击此链接查看三种同时对View的多个属性进行动画处理的方法: https://developer.android.com/guide/topics/graphics/prop-animation#view-prop-animator

种方法是使用AnimatorSet。

以下是第种方法:

public static ObjectAnimator ofPropertyValuesHolder (Object target, 
            PropertyValuesHolder... values)

API文档描述了ObjectAnimator的此构造函数:

"当使用相同的ObjectAnimator同时动画化多个属性时,应该使用此变体,因为PropertyValuesHolder允许您将一组动画值与属性名称关联起来。"

例如:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);

PropertyValuesHolder transX = PropertyValuesHolder.ofKeyframe("translationX", kf0, kf1, kf2);
PropertyValuesHolder transY = PropertyValuesHolder.ofKeyframe("translationY", kf0, kf1, kf2);

ObjectAnimator transAnim = ObjectAnimator.ofPropertyValuesHolder(view2animate, transX, transY);
            transAnim.setDuration(5000);
            transAnim.start();

上面的示例同时在x和y轴上移动view2animate

3种方法是使用ViewPropertyAnimator


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接