Image animation move and scale together - android

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

Related

How to rotate ImageVector’ pathData in Compose

I am trying to implement similar animation like this, with Jetpack Compose
figure: https://dribbble.com/shots/4762799-Microinteraction-Exploration-002
For the play icon’s transformation (from a triangle to a rectangle) , it not difficult to get it done by using path morphing animation.After reading some gist, I found that I can build an ImageVector by supplying the pathData , that's new to me~
While for ****the part on the right, the rotation of the cube object. Well, maybe I should call that a rolling-over or whatever, because the cube changed its pivot after -90 degrees.
I'm wondering that wether I can create a VectorGroup for the cube’s pathData and animate it by updating its group parameters.
re: androidx.compose.ui.graphics.vector.ImageVector.Builder#addGroup
ImageVector.Builder(defaultWidth = 100.dp, defaultHeight = 100.dp, viewportWidth = 100, viewportHeight = 100)
.addGroup(name = "CubeRotation", rotate = params.rotate, pivotX = params.pivotX, pivotY = params.pivotY,)
.addPath(pathData = pathData, fill = SolidColor(Color.LightGray))
.clearGroup()
.build()
Here I trying to update the pivotX halfway through the animation, so I divide it into two section:
// rotate -90 degrees twice with different pivot
val rotate = if (fraction <= 0.5f) {
lerp(0f, -180f, fraction)
} else {
lerp(0f, -180f, fraction - 0.5f)
}
// change the pivotX
val pivotX = if (fraction <= 0.5f) 52f else 30f
GroupParams(
pivotX = pivotX,
pivotY = 100f,
rotate = rotate,
)
Frustratedly, after rotating by the first -90 degrees, the transformation that this rotation performed will NOT persist, -or- its transformation NOT being applied after the half time of the transition.
fraction: 0~0.5
fraction: 0.5~1
The code sample I've uploaded: IndicatorDrawable.kt
Can I implement the rotate transformation by just updating the pathData ?
For me, the VectorGroup in ImageVector looks like creating AnimatedVectorDrawable in xml, or maybe I should try some traditional way like ObjectAnimationSet in View system ?

How to animate an image from right to left, and left to right of the screen

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.

How do I make a smooth animation with ValueAnimator?

I am wanting to hide an extended fab when it is clicked using an Animation. I want to scale the button down from original height and width to 0/gone. It disappears in the corner but the animation is laggy in the middle.
private fun animateHideScoreFab(){
val animX = ValueAnimator.ofInt(editScoreFab.measuredWidth, 0).apply {
duration = 1000
}
val animY = ValueAnimator.ofInt(editScoreFab.measuredHeight, 0).apply {
duration = 1000
}
animX.addUpdateListener {
val value = it.animatedValue as Int
editScoreFab.layoutParams.width = value
editScoreFab.requestLayout()
}
animY.addUpdateListener {
val value = it.animatedValue as Int
editScoreFab.layoutParams.height = value
}
AnimatorSet().apply {
this.interpolator = AccelerateDecelerateInterpolator()
play(animX).with(animY)
start()
}
}
Result:
Using AccelerateDecelerateInterpolator https://developer.android.com/reference/android/view/animation/AccelerateDecelerateInterpolator says
An interpolator where the rate of change starts and ends slowly but accelerates through the middle.
So in the middle the rate of change is faster than the start which could make it look laggy
Try another Interpolator like LinearInterpolator https://developer.android.com/reference/android/view/animation/LinearInterpolator.html which has a constant rate of change.
Update
For AccelerateDecelerateInterpolator if you look at the table in https://developer.android.com/guide/topics/graphics/prop-animation.html#interpolators between 400ms and 600ms the the value jumps 45.5% of the distance you and animating
The other factor of smoothness is not to use an Int but use a Float e.g. ValueAnimator.ofFloat so it has intermediate steps,
Update2
Re-laying out an item is expensive as it has to be measured and redrawn.
It should be faster and smoother just to scale the already drawn image as this is usually done by the GPU and thus faster and smoother. Also scaling a view takes a Float
example of scaling a Fab to top right onClick (Note using ObjectAnimator as it is simpler to implement)
Sorry in Java not Kotlin
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AnimatorSet animationSet = new AnimatorSet();
// Set point to scale around to top right
view.setPivotY(0);
view.setPivotX(view.getMeasuredWidth());
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,"scaleY", 1f, 0f);
scaleY.setDuration(1000);
// Optional as AccelerateDecelerateInterpolator is the default
scaleY.setInterpolator(new AccelerateDecelerateInterpolator());
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,"scaleX", 1f, 0f);
scaleX.setDuration(1000);
// Optional as AccelerateDecelerateInterpolator is the default
scaleX.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.playTogether(scaleX, scaleY);
animationSet.start();
}
});
There's a scaleX and scaleY property in Views that you can interpolate from 1 to 0, this will give the effect of the View shrinking and not the container.
Second, for a scale animation work to the top if your parent layout params doesn't do for you, you have to set the pivot to the rightXtop corner with: view.pivotX = view.width; view.pivotY = 0
Also, if you using propertyListener and updating it yourself you can use only one ValueAnimator and do the calc yourself plus consider replacing editScoreFab.requestLayout() with editScoreFab.invalidate()

Object Animator in Android

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

android translateAnimation setDuration() doesn't work

I'm trying to create a translate animation to an imageView. The animation works but not according to the value I'm putting in the setDuration()
This is the code
/* flipping the images out of the screen */
float outOfScreenX = currentImageLocationX * DRAG_ACTION_SCREEN_BOUNDS_THREASHOLD;
float outOfScreenY = currentImageLocationY * DRAG_ACTION_SCREEN_BOUNDS_THREASHOLD;
translate = new TranslateAnimation(0, outOfScreenX, 0, outOfScreenY);
long velocity = Math.max(Math.abs((int) vTracker.getXVelocity()), Math.abs((int) vTracker.getYVelocity())) / 10;
velocity = (long) Math.min(velocity, 200);
translate.setDuration(velocity);
translate.setFillAfter(true);
mDragView.clearAnimation();
mDragView.startAnimation(translate);
imageStack.removeView(mOriginator);
The value of "velocity" derived from the vTracker, the speed of the user's touch on the view. It's always between 200-600 proximately, but the view moves much faster than this(and also a little flickering but this is another topic).

Categories

Resources