简体   繁体   中英

In Android how to use ObjectAnimator to move to point x along a curve

I have an image view "stone" and am moving it from its current position to a X,Y position. I want it to move along a curve. Please let me know how I can do that(i have set the min api as 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();

The answer by Budius seems perfectly useful to me.

Here are the animator objects I use:

Purpose: Move View "view" along Path "path"

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

Similar to: Android, move bitmap along a path?

you have two options:

both needs a Path object that defines your curve:

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

if using Lollipop only (API 21) use ObjectAnimator.ofFloat(...path) like this:

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

if that's not an options, you use an AnimatorListener to receive updates about the each animator frame and use the PathMeasure to get the values on that point, like this:

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

Play around with the interpolators. For example set 2 different Interpolators for x and y :

moveX.setInterpolator(new AccelerateDecelerateInterpolator());

moveY.setInterpolator(new DecelerateInterpolator());

Theres more (LinearInterpolator, AccelerateInterpolator...) but I think this should be the combination you want.

Thanks for the answers, but I found my own answer.Just added some extra x,y positions in the Objectanimator stmt. It went to those positions before coming to the final one and traced a path!

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] );

The Path class has methods for creating non-straight lines of several types; arcs, circles, ovals, rectangles, cubic & quadratic bezier curves, which you can then animate your object along.

As Budius points out, you do need to code for API 21 (Lollipop) or later to use paths with object translation. It is now over two years old.

On the other hand, there does seem a dearth of anything-more-than-very-simple examples of using paths "in the wild", so perhaps there's a reason they've not caught on yet.

Check this link for 3 ways of animating several properties of a View in parallel: https://developer.android.com/guide/topics/graphics/prop-animation#view-prop-animator

The 1st way of doing it is using AnimatorSet.

Below is the 2nd way:

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

The API doc describes this constructor for ObjectAnimator as:

"This variant should be used when animating several properties at once with the same ObjectAnimator , since PropertyValuesHolder allows you to associate a set of animation values with a property name."

Example:

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

The example above moves view2animate in both x and y axis at the same time.

The 3rd way is to use ViewPropertyAnimator .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM