What I am attempting to do is scale an ImageView from it's normal size, to 20% larger and then back. This should be looped. I have done this with the following code but it doesn't quite work right. More below.
anim/scale.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="1000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.2"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
<scale
android:startOffset="1000"
android:duration="1000"
android:fromXScale="1.2"
android:fromYScale="1.2"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false" />
</set>
Then in my code I do
private void scaleAnimation() {
final Animation scaler = AnimationUtils.loadAnimation(this, R.anim.scale);
scaler.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
animation.reset();
animation.startNow();
}
});
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
scale.startAnimation(scaler);
}
}, 2000);
}
I have the handler there so I could see what was happening at the start.
The problem is kind of difficult to explain.. My image appears to get scaled as soon as the animation starts AND THEN it performs the animation. So the image appears, as it should, for 2 seconds. Just as the animation starts it suddenly gets bigger by what appears to be 25% - 50% and then the animation performs properly. Once the animation is over, the image resizes to it's original size really quickly and then gets scaled up again and then the animation starts over.
I've tried with a couple of different images without difference. It is my understanding that fromXScale=1.0 starts the animation with no scaling, i.e. the image as is. Hopefully someone can shed light on what I've done wrong or where I've misunderstood the concepts.
Cheers
If what you're trying to accomplish is an view that scales from 1.0 to 1.2 back to 1.0 constantly, you could make your animation simpler.
You would do the following:
Only define one scale animation (from 1.0 to 1.2)
Set the repeat count to INFINITE
Set the repeat mode to REVERSE
For more info, you can check out the document on the Animation class
In my case, I need to animate my view one time (1.0f -> 0.6f -> 1.0f)
The solution of cheezy works for me changing repeatCount = 1 instead of infinite.
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:duration="600"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatMode="reverse"
android:repeatCount="1"
android:toXScale="0.6"
android:toYScale="0.6" />
</set>
Related
I'm doing a simple animation of an icon in an ImageView that is inside an ExpandableRecyclerAdapter. When clicking on the expansion item, the animation starts but returns to the initial state, presenting a different behavior. It starts to rotate from 0F to 180F, but at the end it returns from where it was as seen below:
ImageView
I'm using AnimationUtils and two xml files -> one to rotate 180 degrees for the up arrow and -180 for it to return;
My rotation function:
fun rotateAnimation(view: View, expanded: Boolean) {
var anim = AnimationUtils.loadAnimation(view.context, R.anim.rotate_view_up)
if (expanded) {
view.startAnimation(anim)
} else {
anim = AnimationUtils.loadAnimation(view.context, R.anim.rotate_view_down)
view.startAnimation(anim)
}
}
My XML animation files are configured as seen below (arrow up):
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:interpolator="#android:anim/cycle_interpolator"
android:toDegrees="-180" />
Arrow down(ony toDegree change):
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:interpolator="#android:anim/cycle_interpolator"
android:toDegrees="180" />
Is there any configuration I missed in the xml set?
I have this simple arrow image rotation animation which works as intended only for the first time. from second time onward It's still do the rotation but without slow animation.
Here's the code in anim xml files
Rotate 180
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:fromDegrees="0"
android:toDegrees="180"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:fillAfter="true"
android:fillEnabled="true"/>
Rotate Revere
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:fromDegrees="180"
android:toDegrees="0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:fillAfter="true"
android:fillEnabled="true"
/>
The image view inside card view.
<ImageView
android:id="#+id/creadit_card_next_image"
android:layout_width="#dimen/next_image_size"
android:layout_height="#dimen/next_image_size"
android:layout_marginEnd="#dimen/static_menu_primary_margin"
android:layout_marginTop="16dp"
android:rotation="-90"
android:src="#drawable/ic_navigate_next"
android:tint="#color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Java code to trigger Animation.
private Animation rotatePlus180;
private Animation rotateMinus180;
private boolean creditDebitCardViewExpanded = true;
rotatePlus180 = AnimationUtils.loadAnimation(this, R.anim.rotate_plus_180);
rotateMinus180 = AnimationUtils.loadAnimation(this, R.anim.rotate_minus_180);
private void onClickCreditDebitCardView() {
creditDebitCardPaymentMethod.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (creditDebitCardViewExpanded) {
expandAnimation(paymentRecyclerView);
creditDebitCardViewExpanded = false;
creditCardNextImage.setAnimation(rotatePlus180);
} else {
collapseAnimation(paymentRecyclerView);
creditDebitCardViewExpanded = true;
creditCardNextImage.setAnimation(rotateMinus180);
CreditDebitLayoutContainer.setPadding(0, 0, 0, padding);
}
}
});
}
Instead of setAnimation use startAnimation
creditCardNextImage.startAnimation(rotatePlus180);
creditCardNextImage.startAnimation(rotateMinus180);
setAnimation seems to be called once you attach the animation to the view/ or when the view is added.
StartAnimation will be called all the time even if the view has already been added.
I want to increase/decrease the text size in text view but not by .setTextSize() method . Like when I click a button the size must change from one to another smoothly and not abruptly. The transition must be visible as it is increasing so that a good UI experience is obtained. I tried to use a loop where the size changes by small-small bits but thats also to quick to be visible. So please someone suggest me a method to do this. I am just a beginner in Android
This could be achieved with a ValueAnimator.
Try this :
final TextView tv = new TextView(getApplicationContext());
Button btnPlay = (Button) findViewById(R.id.btnPlay);
btnPlay.setOnClickListener(MainActivity.this);
final float startSize = 42; // Size in pixels
final float endSize = 12;
final int animationDuration = 600; // Animation duration in ms
ValueAnimator animator = ValueAnimator.ofFloat(startSize, endSize);
animator.setDuration(animationDuration);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float animatedValue = (float) valueAnimator.getAnimatedValue();
tv.setTextSize(animatedValue);
}
});
#Override
public void onClick(View view)
{
if(view == btnPlay)
{
animator.start();
}
}
Use this code in on click listner of button, where you want to achieve this.
You can perform this using View Animation.
You should refer it from here
create one textanim.xml inside tour res/anim folder. (here add anim folder first in res file if not created.)
your textanim.xml should be look like this.
<set android:shareInterpolator="false">
<scale
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<set android:interpolator="#android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" />
</set>
</set>
Moving on to the associated java file (inside your Activity), you have to use this animation like this,
TextView mT = (TextView) findViewById(R.id.yourTextViewId);
Animation myAnim = AnimationUtils.loadAnimation(this, R.anim.textanim);
mText.startAnimation(myAnim);
I have an animation set on an ImageButton that is Invisible, then on a callback gets set to be visible and should start to animate.
I set my animation up like this
showBuildingTapAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.main_button_tap);
and call it like this
if(showBuildingCollectionNavButton.getVisibility() == View.INVISIBLE) {
showBuildingCollectionNavButton.setVisibility(View.VISIBLE);
showBuildingCollectionNavButton.requestLayout();
showBuildingTapAnimation.start();
}
and I have also tried this:
if(showBuildingCollectionNavButton.getVisibility() == View.INVISIBLE) {
showBuildingCollectionNavButton.setVisibility(View.VISIBLE);
showBuildingCollectionNavButton.requestLayout();
showBuildingCollectionNavButton.startAnimation(AnimationUtils.loadAnimation(this.getApplicationContext(), R.anim.main_button_tap));
}
and this
if(showBuildingCollectionNavButton.getVisibility() == View.INVISIBLE) {
showBuildingCollectionNavButton.setVisibility(View.VISIBLE);
showBuildingCollectionNavButton.requestLayout();
showBuildingCollectionNavButton.startAnimation(showBuildingTapAnimation);
}
My animation itself is here:
<scale
android:duration="075"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.09"
android:toYScale="1.09"
android:pivotX="50%"
android:pivotY="50%"
/>
<scale
android:duration="075"
android:startOffset="075"
android:fromXScale="1.09"
android:fromYScale="1.09"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
/>
I am calling requestLayout() as a few of the posts here talked about issues when the asset was gone or invisible that it wasn't updating...
I think the real issue may be with the context that I am passing into the loadAnimation() call - as I am in a FragmentActivity here...
Thoughts ??
You are displaying your animations for 75 + 75 ms . They are animated but you can not observe them (especially a scale that small)
I am applying three animations in an ImageView, one after another. I have a AnimationListener for each animation, so inside the onAnimationEnd, I start the next one, so they dont overlap. The animations are this: scale in, fade out and the last one fade in. The fade in animation will restart the scale in animation again, to these animations will be running "forever". What I am trying to achieve is the same effect Twitter has applied to their new home screen, where they keep changing the pictures.
The problem with my animations is that after scaling in the ImageView and before staring the the fade out animation, the ImageView gets reseted and the scale change is lost, even setting fillAfter in the code or in the xml file. Here is the code for handling the animation events:
mAnimationFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
mAnimationFadeIn.setFillAfter(true);
mAnimationFadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
mAnimationFadeOut.setFillAfter(true);
mAnimationScaleIn = AnimationUtils.loadAnimation(this, R.anim.slow_scale_in);
mAnimationScaleIn.setFillAfter(true);
mAnimationScaleIn.setFillEnabled(true);
mAnimationScaleIn.setFillBefore(false);
mAnimationScaleIn.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.startAnimation(mAnimationFadeOut);
}
});
mAnimationFadeOut.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.setImageResource(mImages[++mImageIndex > 2 ? mImageIndex=0 : mImageIndex]);
mImageView.startAnimation(mAnimationFadeIn);
}
});
mAnimationFadeIn.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.startAnimation(mAnimationScaleIn);
}
});
mImageView.startAnimation(mAnimationScaleIn);
and here are my animations:
scale in:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="9000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50.0%"
android:pivotY="50.0%"
android:toXScale="1.1"
android:toYScale="1.1" />
fade in:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:toAlpha="1.0" />
fade out:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="#android:anim/linear_interpolator"
android:toAlpha="0.0" />
Is there a way to keep the scale transformation before starting the fade out animation?
I have tried all the combinations for setFillAfter, setFillBefore and setFillEnabled and no way I can get the scale transformation to be kept after the scale animation is over.
Many thanks
T
do as given below u have to enable it in set tag and than use in either rotate or scale etc...
<?xml version="1.0" encoding="UTF-8"?>
<set android:shareInterpolator="false"
android:fillEnabled="true"
android:fillAfter="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="1.4"
android:pivotY="50%"
android:fillAfter="true"
android:fillEnabled="true"
android:duration="2000" />
<scale
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillAfter="true"
android:duration="2000" />
</set>