I want to mimic the animation on 4 Pics 1 Word, wherein the user taps a letter and flies somewhere in the screen. This letter can be a Button or an ImageView. Please refer to the image below:
Is this only possible with Corona SDK / Lua? How will I do it in Java? I'm just a beginner so I don't know how to start this so please don't ask any code that I already tried.
You can use ObjectAnimator class for performing animations on Android views. For example, if you have to animate the y property of the view mView you can write:
float finalValue = 10f;
ObjectAnimator yAnimator = ObjectAnimator.ofFloat(mView, View.Y, finalValue);
yAnimator.start();
For animating more than one property you can write:
float finalX = 20f;
float finalY = 30f;
ObjectAnimator xAnimator = ObjectAnimator.ofFloat(mView, View.X, finalX);
ObjectAnimator yAnimator = ObjectAnimator.ofFloat(mView, View.Y, finalY);
new AnimatorSet().playTogether(xAnimator, yAnimator);
Related
I am trying to figure out how to animate an image from left to right, and then from right to left.
For example imagine the following image:
At full resolution, the width of the image would exceed the width of the screen. So initially, only the left side of the image should be visible, but as the animation is running, slowly the right side becomes visible, eg.:
Once the right side of the image was fully uncovered, the animation starts in reverse:
Any ideas how to achieve this?
Android APIs or any techniques would be of great help.
Using ObjectAnimator.
Well, I didn't really know, how to size image in without cropping, so I made view's width 1000dp.
Here is solution:
ImageView imageView = findViewById(R.id.imageView);
imageView.post(() -> {
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
float width = imageView.getMeasuredWidth();
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0, -(width - point.x));
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.setDuration(10000);
objectAnimator.start();
});
Let me explain.
First, I get size of device.
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
Then, I get width of view and creating ObjectAnimator
float width = imageView.getMeasuredWidth();
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 0, -(width - point.x));
First argument is a view, that will be animated. Second argument tells objectAnimator what method (in this case setter) to use. We use translationX, so objectAnimator use setTranslationX().
All other arguments tells objectAnimator from where to where it should animate.
We substracting point.x from width for animation stops when edge of image is shown. Else, imageView will slide to the left until image disappears.
For example:
ObjectAnimator.ofFloat(imageView, "translationX", 0, 200, 100, 300);
says that image should go by axis X to the point 0, then 200, then 100 and in the end 300.
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
tells that after animation done, do it again, but in reverse.
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
tells that animation must repeat itself infinitely.
objectAnimator.setDuration(10000);
Duration of the animation in milliseconds.
Try with TranslateAnimation:
First, you have to know how big is the view:
ImageView picture = findViewById(R.id.picture);
int pictureWidth = picture.getWidth();
private void animation(View view, float pictureWidth) {
Animation offSet = new TranslateAnimation(0, - moveTo, 0, 0);
offSet.setInterpolator(new AccelerateDecelerateInterpolator()); // just to make a smooth movement
offSet.setDuration(durationInMillis);
}
The code above will move to the left showing the right side of the image,
you can add something similar to reverse the movement.
There are for sure better and more complete solutions, this is just (I think) the easier.
I am trying to play animation (like drop or bounce) on placing of an 3D object (.sfb in my case), but I don't have any idea how can I do that.
I have tried to use ValueAnimator that is working fine for changing its color value, but that's not I wanted.
val alphaAnimator = ValueAnimator.ofFloat(0.0f, 1.0f, 0.0f)
alphaAnimator.addUpdateListener { animation ->
val animatedAlpha = animation.animatedValue as Float
modelRenderable.material.setFloat4(
MaterialFactory.MATERIAL_COLOR,
Color(0.0f, 0.0f, 1.0f * animatedAlpha, animatedAlpha)
)
}
alphaAnimator.repeatCount = ValueAnimator.INFINITE
alphaAnimator.duration = 1000
alphaAnimator.start()
val animatorSet = AnimatorSet()
animatorSet.playSequentially(
ObjectAnimator.ofFloat(modelRenderable, "translationY", 0.0f)
ObjectAnimator.ofFloat(modelRenderable, "translationY", 1.5f)
ObjectAnimator.ofFloat(modelRenderable, "translationY", 0.0f)
)
animatorSet.duration = 600
animatorSet.start()
But this is giving me an error "Could not find property setter method setTranslationY on com.google.ar.sceneform.rendering.ModelRenderable".
You should animate the node where the renderable is attached to and not the model itself. The node has a setLocalPosition(Vector3) method which you can use for the ObjectAnimator. So to animate for example the position of your model you should do something like this:
ObjectAnimator nodeAnimator = ObjectAnimator.ofObject(
yourNode,
"localPosition",
new Vector3Evaluator(),
Vector3.zero(), new Vector3(0f, 1f, 0f));
Then you can set the duration, repeat count, mode etc. You can also scale and rotate the model over a animation.
I have 4 image view I want to move image 1 to position of image 2 with move and scale animation.
[
What I have tried for scaling
ObjectAnimator scaleX = ObjectAnimator.ofFloat(img1, "scaleX", (float) img2.getWidth());
ObjectAnimator scaleY = ObjectAnimator.ofFloat(img1, "scaleY", (float) img2.getHeight());
scaleX.setDuration(2000);
scaleY.setDuration(2000);
AnimatorSet scale = new AnimatorSet();
scale.play(scaleX).with(scaleY);
scale.start();
You can save a lot of code with ViewPropertyAnimator plus you can combine multiple animations in one line :
img1.animate()
.scaleX(toX)
.scaleY(toY)
.translationX(toX)
.translationY(toY)
.setDuration(2000);
There are also methods :
.scaleXBy(byX)
.translationYBy(byY)
that scale/translate the methods BY the given value
For the translation you have to keep in mind that :
img2.getX();
img2.getY();
only gives you the coordinates of the upper left corner of the view img2 .
You probably want to animate to the center of img2 which would be
img2.getX() / 2;
img2.getY() / 2;
All combined something like this should work :
img1.animate()
.scaleX(...)
.scaleY(...)
.translationX(img2.getX() / 2)
.translationY(img2.getY() / 2)
.setDuration(2000);
EDIT : I found this page on the developer training site you can check out :
Zooming a view
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.
I'm trying to use a simple translation in which I have a button and I want to move it to a position where another button is. The thing is the button just disappears from the screen right away when the translation starts, it doesn't even move.
my code:
Button poli1 = checkPosPoli1();
TranslateAnimation animpoli1 = new TranslateAnimation(checkPosPoli1().getLeft(),checkBtn().getLeft() , checkPosPoli1().getTop(), checkBtn().getTop());
animpoli1.setDuration(10000);
animpoli1.setFillAfter( true );
poli1.startAnimation(animpoli1);
Both checkPosPoli1() and checkBtn return a button and I have printed both their values in console and it's ok.
Take a look at the documentation of TranslateAnimation: http://developer.android.com/reference/android/view/animation/TranslateAnimation.html . The constructor you are using is this one: TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) which means you want the first and third parameters to be 0 if the view is already in its starting position otherwise you are moving the view way off right at the beginning of the animation.
TranslateAnimation animpoli1 = new TranslateAnimation(0, targetX - currentX, 0, targetY - currentY);
if you want it to be relative to the parent, you can use the second constructor:
TranslateAnimation animpoli1 = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, currentX, targetX, Animation.RELATIVE_TO_PARENT, currentY, targetY);