【问题标题】:In Android how to use ObjectAnimator to move to point x along a curve在Android中如何使用ObjectAnimator沿曲线移动到点x
【发布时间】:2015-05-08 05:35:02
【问题描述】:

我有一个图像视图“石头”并将其从当前位置移动到 X、Y 位置。我希望它沿着曲线移动。请让我知道我该怎么做(我已将 min 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,它会让你在任何你想要的路径上移动

标签: android


【解决方案1】:

Budius 的回答对我来说似乎非常有用。

这是我使用的动画对象:

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

Android v21+:

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

Android 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, move bitmap along a path?

【讨论】:

  • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post
  • 感谢您的反馈。我已经从我的解决方案中添加了工作代码,以使其成为一个完整的答案。希望这会有所帮助!
  • 这几乎可以工作,但似乎动画完成时值最终会重置(ValueAnimator 示例)
  • 你在这里犯了两个错误。首先,正如@MattFoley 提到的,ValueAnimator 在动画结束时重置值,因此您需要将false 而不是true 传递给PathMeasure 构造函数。其次,您需要通过调用setX()setY() 方法来转换视图而不是更改其位置。使用setTranslationX()setTranslationY() 方法。事实上,您在下面有正确的答案,由@Budius 撰写。
【解决方案2】:

你有两个选择:

两者都需要一个定义曲线的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...),但我认为这应该是您想要的组合。

    【讨论】:

    • 别出心裁,太聪明了
    【解决方案4】:

    感谢您的回答,但我找到了自己的答案。只是在 Objectanimator stmt 中添加了一些额外的 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.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 动画师 = new ObjectAnimator(); animator.ofFloat(img,View.X,View.Y,path);动画师.setDuration(1000); animator.setStartDelay(600);动画师.start();例外是:java.lang.NullPointerException:尝试获取空数组的长度
    【解决方案5】:

    Path 类具有创建多种类型的非直线的方法;圆弧、圆形、椭圆形、矩形、三次和二次贝塞尔曲线,然后您可以沿着这些曲线为您的对象设置动画。

    正如 Budius 指出的那样,您确实需要为 API 21 (Lollipop) 或更高版本编写代码才能使用带有对象转换的路径。现在已经两年多了。

    另一方面,似乎确实缺乏“在野外”使用路径的非常简单的例子,所以也许他们还没有流行起来是有原因的。

    【讨论】:

      【解决方案6】:

      查看此链接以了解 3 种方法可以同时为 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

      第三种方式是使用ViewPropertyAnimator

      【讨论】:

        猜你喜欢
        • 2011-08-06
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-16
        • 2013-04-20
        • 1970-01-01
        • 2023-02-04
        相关资源
        最近更新 更多