I have an ImageView and I do a simple scale animation to it. Very standard code.
My scale_up.xml:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.2"
android:toYScale="1.2"
android:duration="175"/>
</set>
My animation code:
Animation a = AnimationUtils.loadAnimation(this, R.anim.scale_up);
((ImageView) findViewById(R.id.circle_image)).startAnimation(a);
The problem:
When the image scales it doesn't scale from the center, but from the top left corner. In other words, the scaled version of the image doesn't have the same point as the center, but it has the same top-left point.
Here's an image that explains what I mean:
The first image is how the animation scales and the second image is how I want it to scale. It should keep the center point the same.
I have tried setting up gravity on the image, on the container, aligning left or right, it always scales the same.
I'm using RelativeLayout for the main screen and ImageView is located into another RelativeLayout, but I tried other layouts, no change.
50% is center of animated view.
50%p is center of parent
<scale
android:fromXScale="1.0"
android:toXScale="1.2"
android:fromYScale="1.0"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:duration="175"/>
The answer provided by #stevanveltema and #JiangQi are perfect but if you want scaling using code, then you can use my answer.
// first 0f, 1f mean scaling from X-axis to X-axis, meaning scaling from 0-100%
// first 0f, 1f mean scaling from Y-axis to Y-axis, meaning scaling from 0-100%
// The two 0.5f mean animation will start from 50% of X-axis & 50% of Y-axis, i.e. from center
ScaleAnimation fade_in = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
fade_in.setDuration(1000); // animation duration in milliseconds
fade_in.setFillAfter(true); // If fillAfter is true, the transformation that this animation performed will persist when it is finished.
view.startAnimation(fade_in);
Forget the additional translation, set android:pivotX, android:pivotY to half the width and height and it will scale from the center of the image.
You can use the translate animation in your set to offset that. You'll probably need to tweak the toXDelta and toYDelta values to get it right so it keeps the image centered.
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.2"
android:toYScale="1.2"
android:duration="175"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-20%"
android:toYDelta="-20%"
android:duration="175"/>
</set>
Related
Am confused with XScale and XDelta
android:fromXDelta="0%p"
vs
android:fromXScale="1.0"
what are the core differences between them
XScale comes inside <scale> tag it is a resizing animation.
The below code is a slide down animation
<scale
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="0.0"
android:toXScale="1.0"
android:toYScale="1.0" />
Where,
XDelta comes inside <translate> tag its is for vertical and/or horizontal motion its supports the following attributes in any of the following three formats: values from -100 to 100 ending with "%", indicating a percentage relative to itself; values from -100 to 100 ending in "%p", indicating a percentage relative to its parent; a float value with no suffix, indicating an absolute value.
The code below is a animation to move from origin to right
<translate
android:fromXDelta="0%p"
android:toXDelta="75%p"
android:duration="800" />
What I'm doing now is a sound wave and to do it I have created an animation that increase the height
please see this picture
so my problem is that the animation works and it increase the height however I wanted to make it reverse grow
Hope you can help me thank you
So my code is here
<scale
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.0"
android:fromYScale="1.0"
android:toYScale="0.5"
android:duration="2000"
android:fillAfter="false"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
Animation animation = AnimationUtils.loadAnimation(context, R.anim.sound_wave);
view.setAnimation(animation);
view.animate();
animation.start();
I do not know of a way to solve your problem while continuing to use an animation resource. I would instead use ObjectAnimator.
Here's how to build your same animation using ObjectAnimator:
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.5f);
anim.setDuration(2000);
anim.setRepeatMode(ValueAnimator.REVERSE);
anim.setRepeatCount(ValueAnimator.INFINITE);
anim.start();
You also have to add an attribute to your View in whatever layout file defines it. In my case, I made my view 400dp tall, so I added this:
android:transformPivotY="400dp"
This will cause the scale animation to be anchored at the bottom of the view (since its pivot is equal to its height).
I'm trying to make an image view to grow and reduce only on the x axis, yes, I want to deformate it.
It is actually the shadow of a bouncing ball. I'm trying to achive it with the scale animation, but it translate. Anyone that can help?
Here's the code of the animation that I'm using.
shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator" >
<scale
android:duration="10000"
android:fromXScale="1.1"
android:fromYScale="1.0"
android:toXScale="0.1"
android:toYScale="1.0" />
<alpha
android:duration="10000"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
I tested your code out and here is what i found:
The code that you have provided initially scales the object in X axis to 1.1 directly(i.e without any animation).
Next, the object is scaled down in X axis to 0.1 while the alpha goes down. The scaling takes place about the upper left corner of the object(i.e the pivot is set to default).
If you want the scaling to happen about any other point,you can specify that as
android:pivotX="x%"
android:pivotY="y%"
I am trying to do some simple image zooming and panning with Android and I have two simple questions.
First, when I call the animation using scale, it zooms using the upper left-hand corner of the image as the origin but I would like it to zoom from the center of the image.
The second question is once the animation is done, it resets the image to the original state and I would like it to stay at the final state.
Here is the xml I have for the scale:
<scale android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="2.0"
android:toYScale="2.0"
android:detachWallpaper="true"
android:duration="3000"></scale>
and in my code:
a = AnimationUtils.loadAnimation(this, R.anim.set);
a.reset();
ImageView iv = (ImageView) findViewById(R.id.imageView1);
iv.clearAnimation();
iv.startAnimation(a);
For scaling a image from center you have to set the pivotX and pivotY
try this code for scaling from center and retaining the state after scaling,
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:toXScale="5"
android:fromYScale="1"
android:toYScale="5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
Thanks...
I'd like to grow a view with each click using a ScaleAnimation. I've managed the effects of the animation persist after it has finished with the fillAfter, but the problem now is, the animation always starts from state 0 (as the View is defined in the XML) - on click the view resets and animates back to the state it was just after the first animation.
The animation is defined in an XML:
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1"
android:toXScale="1.5"
android:fromYScale="1"
android:toYScale="1.5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true"
/>
I solved the issue by not resorting to animation defined in the XML, but rather doing
anim = new ScaleAnimation(from, to, from, to, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
and adjusting from/to each time I needed to expand it. I'm not so sure that's a good thing regarding performance, but it works nicely.
How exactly is the animation defined?
When defining ScaleAnimation with Java code, you can set fromX/fromY (look here) starting scaling factors, so I assume you can do the same with XML attributes.