Android ObjectAnimator fill after option? - java

In my android application I am using an ObjectAnimator to translate an imageview like so:
ObjectAnimator transitionX = ObjectAnimator.ofFloat(v, "TranslationY", 190);
Is there an option like fillAfter that will reset the position of the view to the new position, after the animation is complete?

Nope, I'd use the property animation system instead, assuming v is a view:
v.animate().translationY(190).withEndAction(new Runnable() {
#Override
public void run() {
v.setTranslationY(v.getTranslationY()-190);
}
}).start();

Nope, there is no option for that. However you can achieve the same effect using a listener where you can manually change it to the initial position in the onAnimationEnd(). Here is an example for scaling an imageview:
scaleDown.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
//Initial property values
tempIV.setScaleX(1f);
tempIV.setScaleY(1f);
tempIV.setAlpha(1f);
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});

I think the right way to handle this is to use an AnimationSet to merge two animations, one to translate and one to translate back the view.
Something like this
ObjectAnimator translateTo190= ObjectAnimator.ofFloat(v, "TranslationY", 190);
ObjectAnimator translateBack = ObjectAnimator.ofFloat(v, "TranslationY", 0);
AnimatorSet translate= new AnimatorSet();
translate.play(translateTo190).before(translateBack);
translate.start();

I have had a problem like this in writing a card dealing animation where the cards are dealt quickly from a central "deck". After much trial-and-error, the way I've got this working is using the ObjectAnimator in the following way.
I add a single "deck" card at the source of the animation, and then a second card that I'm actually animating. I use the following deal_from_drawpile.xml to animate the card in two parts: the first part returns the card to the source, and the second part scales and rotates the card as it is "dealt":
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="sequentially">
<set android:interpolator="#android:anim/accelerate_interpolator"
android:ordering="together">
<objectAnimator
android:propertyName="translationX"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="translationY"
android:duration="10"
android:valueFrom="0.0f"
android:valueTo="0.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="10"
android:valueFrom="0.75f"
android:valueTo="0.75f"/>
</set>
<set android:ordering="together">
<objectAnimator
android:propertyName="rotation"
android:duration="300"
android:valueFrom="0.0f"
android:valueTo="360.0f"/>
<objectAnimator
android:propertyName="scaleX"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
<objectAnimator
android:propertyName="scaleY"
android:duration="300"
android:valueFrom="0.75f"
android:valueTo="0.5f"/>
</set>
Then in code I add the actual translation which depends on how many hands are arranged in a rough semi-circle. The complete sequence of animations is then added in an AnimatorSet and fired off at the end. Code-snippet;
fullScreenContent.addView(dealtCardView);
for (int iCard=0; iCard<numCards; iCard++) {
for (int iPlayer = 0; iPlayer < numPlayers; iPlayer++) {
dealtCardAnimator = dealtCardAnimator.clone();
dealtCardAnimator.setTarget(dealtCardView);
//offsets where the cards are dealt according to player
ObjectAnimator playerOffsetXAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationX", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationX());
ObjectAnimator playerOffsetYAnimator = ObjectAnimator.ofFloat(dealtCardView, "TranslationY", mGame.getPlayer(iPlayer).getPlayerLayout().getTranslationY());
if (lastDealtCardAnimator == null) dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator);
else dealSet.play(dealtCardAnimator).with(playerOffsetXAnimator).with(playerOffsetYAnimator).after(lastDealtCardAnimator);
//The card is returned to the home point with the first portion of deal_from_drawpile
lastDealtCardAnimator = dealtCardAnimator;
}//end for iPlayer
}//end for numCards
dealSet.start();
I can now tinker with the duration of each step in the XML to get the effect I want. Note that you have to embed the duration in each element , not in the set section (where it is ignored, and some arbitrary default seems to be used instead).

Related

Android continues loop for animation

I have tried several kinds of looping in my animation based on the answers here such as animation.setRepeatCount(Animation.INFINITE); or android:repeatcount="infinite" in the anim.xml file..even tried the while(true) loop on java but none seems to work.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="3000" />
<translate
android:fromXDelta="0.0"
android:toXDelta="0.0"
android:fromYDelta="0.0"
android:toYDelta="100.0"
android:startOffset="3000"
android:duration="3000"
android:repeatCount="infinite"/>
</set>
and the my java is:
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView) findViewById(R.id.img);
animation = AnimationUtils.loadAnimation(this, R.anim.halloweenanim);
img.startAnimation(animation);
animation.setRepeatCount(Animation.INFINITE);
//hallo.setBackgroundResource(R.drawable.halloweenimg);
//animation2 = (AnimationDrawable) hallo.getBackground();
//animation2 = (AnimationDrawable) img.getBackground();
//animation.start();
};
Actually AnimationSet has a buggy code. Even the doc here says
repeatCount, fillEnabled: These properties are ignored for
AnimationSet.
What you can do is remove animation.setRepeatCount(Animation.INFINITE);
and set android:repeatCount="infinite" for each of your animation tag, instead of the parent set tag.
nevermind. i found the solution. the android:repeatCount="infinite" should be placed inside the alpha lol. and no need to add .setRepeatCount inside the java code. XD
Can you please try this and look whether it helps you.
animation.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.halloweenanim);
animation.setAnimationListener(this);
img.startAnimation(animation);
}
});
img.startAnimation(animation);

Set animation YDelta in Java class?

I am running an animation within my listview, and I wondering how I am able to set the xml attribute, yDelta, within my java class. It is contingent upon the size of the current row, so I can't use a single value. Here is my animation code
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="20%p"
android:toYDelta="20"
android:duration="#android:integer/config_mediumAnimTime"/>
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="#android:integer/config_mediumAnimTime" />
here is my java code
public void updateDataList(ArrayList<HashMap<String, String>> newList){
final ArrayList<HashMap<String, String>> newListAdd = newList;
Animation anim = AnimationUtils.loadAnimation(
liveStreamFragment.getActivity(), R.anim.top_to_down
);
anim.setDuration(2000);
list.startAnimation(anim);
new Handler().postDelayed(new Runnable() {
public void run() {
oslist.clear();
oslist.addAll(newListAdd);
LiveAdapter.this.notifyDataSetChanged();
}
}, anim.getDuration());
}
Accordingly to this documentation you can set it in constructor:
TranslateAnimation translate = new TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
Also check this similar question.

How to hide Images after animation end in android

In my android application I have five imageviews when I click any one of that all images are animating. I set the zoomout and Zoomin animation for all the images. once the animation is finished, the selected image view is invisible. After image invisible, when i click on that imageview location it again start the animation and the image is invisible.
Zoom-In Animation:
<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>
Zoom-out Animation
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="5"
android:toXScale="1"
android:fromYScale="5"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
zoomin =AnimationUtils.loadAnimation(this, R.anim.zoom);
zoomout=AnimationUtils.loadAnimation(this, R.anim.zoomout);
ImageView v2 = (ImageView) findViewById(R.id.image2);
v2.setOnClickListener(new View.OnClickListener()
{
#Override public void onClick(View v)
{
v2.setAnimation(zoomin);
v2.startAnimation(zoomin);
v2.setAnimation(zoomout);
v2.startAnimation(zoomout);
v2.clearAnimation();
}
});
Add this code to your animation objects:
animation.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation) { }
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation)
{
v2.setImageResource(R.drawable.some_transparent_image);
}
});
This issue is occuring because you added
android:fillAfter="true"
in both Animation XML files.
Either remove "android:fillAfter="true" from both XMLs or keep " android:fillAfter="false" in both files.
You could simply change the transparency of the layer.
v2.setAlpha(0f);
you have to handle the animation listener for that animation.
zoomin.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation) { }
#Override
public void onAnimationRepeat(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation)
{
v2.setVisibility(View.GONE);
}
});
You need to use a Transparent Image
All you need to do is when your Animation ends you need to set a transparent Image as background/scr of that image thereby replacing the previous one.
Changing the visibility of view won't solve your problem
v2.setVisibility(View.GONE);
v2.setVisibility(View.INVISIBLE);
As both above lead to make your view non-clickable and you won't be able to click again.
You must first thing use image.clearAnimation() then hide it
image.visibility = View.GONE

fade in\out works too short and too fast in android

I'm trying to apply fade-in\out transition in Android.
Can you please tell me why I see the fading only for a moment and then it returns to original alpha?
I have added setFillAfter(true); to persist the image disappearance.
I have tried:
animation = android.view.animation.AnimationUtils
.loadAnimation(AppService.getAppContext(),
com.waze.R.anim.fade_out);
animation.setInterpolator(new AccelerateInterpolator());
animation.setFillAfter(true);
boxImage_left.startAnimation(animation);
with this:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:repeatCount="0"
android:duration="500"/>
</set>
and also:
AlphaAnimation alpha = new AlphaAnimation(0,1);
alpha.setDuration(600);
animation.setInterpolator(new AccelerateInterpolator());
animation.setFillAfter(true);
vImage_left.startAnimation(alpha);
Let your activity implements AnimationListener, and set visiblity after animation end.
public class YourActivity extends Activity implements AnimationListener
{
#override
onCreate(Bundle x)
{
...
// set animation listener
animFadein.setAnimationListener(this);
animFadeOut.setAnimationListener(this);
}
#Override
public void onAnimationEnd(Animation animation)
{
if (animation == animFadein)
{
view.setVisibility(View.VISIBLE);
}
if (animation == animFadeOut)
{
view.setVisibility(View.INVISIBLE);
}
}
}
And for animation speed modify animation duration and interpolator
Instead of AccelerateInterpolator you can use LinearInterpolator
I know it's too late but will help someone else.

Android java How can I have a animation image move left and STAY there?

So basically I have this when you click on the image the image will move to the right but when the animation is done it will go back to the original position? How can I make it so it will stop at the spot it ends at in the animation? Here's my code
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="70%" android:duration="1000"/>
</set>
This is my slide_in_right.xml
public void sideBar()
{
ImageView sidebar = (ImageView)findViewById(R.id.sidebar);
mSlideInRight = AnimationUtils.loadAnimation(this, R.anim.slide_in_right);
sidebar.startAnimation(mSlideInRight);
}
And this is the code where it slides to the right
Use the Animation setFillAfter(true) method to persist the animation.
AlphaAnimation alpha = new AlphaAnimation(1, 0);
alpha.setDuration(600);
alpha.setFillAfter(true);
Then
someView.startAnimation(alpha);
In your case, code should be
public void sideBar()
{
ImageView sidebar = (ImageView)findViewById(R.id.sidebar);
mSlideInRight = AnimationUtils.loadAnimation(this, R.anim.slide_in_right);
mSlideInRight.setFillAfter(true);
sidebar.startAnimation(mSlideInRight);
}

Categories