Android SDK - Animation prevents further events on View like OnClick() - android

I have an ImageView which is animated via startAnimation() to slide it into the screen. It is visible and enabled in the XML. When I add a Handler for a delay or an onClick event, nothing happens. When I remove the startAnimation() everything works fine. Except the animation of course.
Heres my code:
balloon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
view.setVisibility(View.GONE);
}
});
Animation dropDown =
AnimationUtils.loadAnimation(context, R.anim.balloon_slide_down);
dropDown.setStartOffset(1500);
balloon.startAnimation(dropDown);
Any ideas why that is? I'm quite frustrated by now...
Thanks,
Ron

Your ImageView probably isn't in the location you think it is. Try setting the offset on the ImageView before the animation.
balloon.offsetTopAndBottom(offset);
//Start Animation from -offset

The animation only give you an animation that the imageview will be slided
but actually the position of the imageview isn't changed
if you want to change it you can move it using layoutparams with looping it in a UIthread

Alright... I thought it was odd that the ÌmageView should not be at the position it is shown. So I figured out that just the setVisibility() is somehow not working.
I changed my code to the following and it works:
balloon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((ViewGroup) balloon.getParent()).removeView(balloon);
}
});

Related

wait for animation to complete before hiding View

I perform some things triggered by a Button click:
private void onSearchPressed() {
title.setVisibility(View.GONE);
etActionSearch.setVisibility(View.VISIBLE);
etActionSearch.requestFocus();
btnActionFavs.setVisibility(View.GONE);
etActionSearch.setAnimation(AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.et_anim_open));
isSearch = true;
}
So basically I just hide some Views and show some others, my EditText is "sliding out" using a simple set Animation.
When the action is cancelled, I reverse the process:
private void onSearchCancelled() {
etActionSearch.setAnimation(AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.et_anim_close));
etActionSearch.setVisibility(View.GONE);
btnActionFavs.setVisibility(View.VISIBLE);
title.setVisibility(View.VISIBLE);
isSearch = false;
}
What I'd like to do is to apply an Animation (opposite direction) to my EditText, so it disappears also with a slide animation. The problem is that all the code is executed immediately, so the EditText is gone BEFORE its animation is complete. I tried some weird things like using an AsyncTask and putting the animation inside the doInBackground() method, setting the Visibility of the Views in onPostExecute() but that didnt change anything.. SystemClock.sleep() also doesn't do anything but a lag impression. Any solutions?
Animations run asynchronously, so you need to use AnimationListener on that animation and put your code that should be executed when animation is over to onAnimationEnd().
See docs: http://developer.android.com/reference/android/view/animation/Animation.AnimationListener.html
Like Marcin Orlowski said, you have to use AnimationListener with your Animation. After the animation is ended it will launch the onAnimationEnd() event where you can do your stuff.
Here's a little example what i could look like:
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.your_specific_animation);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// Do your hiding stuff here
}
});
etActionSearch.startAnimation(animation);

Android fragment animation doesn't actually finish

I encountered this annoying problem, where I have 2 fragments, and I am running 3d flip animation on Fragments getView() component. Problem comes here, when the flip is done, I try to set another view invisible, but nothing happens. It seems that the animation is still on for the view and if I setAnimation(null) or clearAnimation for the view, the whole view is reset to start state.
I also did a little test, with just running alpha animation for the view and after that I cannot change the view visibility anymore. Any solution or hack for this kind of problem?
Thanks.
Here is small code snippet to reproduce problem.
Following code is ran when Fragment onCreateView has been called and button is clicked:
AlphaAnimation fadeHalf = new AlphaAnimation(1, 0.5f);
fadeHalf.setFillAfter(true);
fadeHalf.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
getView().setVisibility(View.GONE);
});
getView().startAnimation(fadeHalf);
So when running the code above, whole fragment view gets translated to 0.5f alpha, but setVisilibity(View.GONE) does nothing.
not sure if this is what you need but you can probably remove the view and add it back on when you do the same animation in the future.

Buttons on an animated view respond to clicks even when off screen?

I have a LinearLayout, I'm applying a translation animation to it. I'm filling the animation before and after. Visually it works fine. The animation ends by translating the view off screen. But if I click an x,y coordinate on screen that happens to be where the view was at some point during its animation, a button on the view has its click listener fire.
The only solution I've found is to add an animation listener, and when the animation ends, mark the buttons on the (now out of view) layout to visibility=gone, enabled=false. This seems bizarre - the view is no longer on screen, but it's still responding to click events. Is this a known thing, I'm probably not setting the animation up correctly?
Thanks
----- Update --------
I refactored my animation a little. Instead of using animation.setFillAfter(true), I set the layout's visibility to GONE when the animation is complete. Now it doesn't register clicks when off-screen. Still interested to know if this is a known thing, as it'd be easier to simply not have to add an animation listener etc.
Translate Animations on lower level API( below honey comb) changes where the button is drawn, but not where the button physically exists within the container. So, you are on your own to handle this situation. For more information about this you can refer to this link. One way is to actually change the location of the button in the layout(not by animation). Here is how you can achieve this:
params = (LayoutParams) mBtn.getLayoutParams();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 400);
animation.setDuration(2000);
animation.setAnimationListener(mAnimationListener);
mBtn.startAnimation(animation);
....
....
private AnimationListener mAnimationListener = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
params.topMargin = params.topMargin + 400;
mButton.setLayoutParams(params);
}
};
Here by changing the layout params we are changing the physical position of the button.
In your case as view is going off the screen so you just need to change the visibility of the button(View.GONE) on animation end.

animation not starting!! (android)

can anyone tell me why this animation isn't starting? i've tried putting code in the onAnimationStart listener and it is never called! there are no errors, it just never happens.. i've been staring at this for hours!!!
Animation bRegisterAnimation = fadeView(1,0,0);
bRegisterAnimation.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
public void onAnimationEnd(Animation arg0) {
bRegister.clearAnimation();
bRegister.setVisibility(View.INVISIBLE);
}
});
bRegister.setAnimation(bRegisterAnimation);
and here is the fadeView function:
public Animation fadeView(float startA, float endA, int delay) {
Animation animation = new AlphaAnimation(startA,endA);
animation.setDuration(1000);
animation.setStartOffset(delay);
return animation;
}
thanks!
You need to call bRegister.startAnimation(bRegisterAnimation). Also, you don't need to call setAnimation(). If you're trying to make a simple fade animation, you might try using this instead:
bRegister.startAnimation(AnimationUtils.loadAnimation(
getBaseContext(), android.R.anim.fade_in));
I guess bRegister is your view over which you want your animation to work. IF this is so, you have correctly set the animation with this view using bRegister.setAnimation(bRegisterAnimation);
but you haven't started the animation using startAnimation(). Try it once
I had a similar experience when trying to implement animations on my Android device, which was one that I borrowed from my sister. I tried getting animation to work on it for a whole day until I finally gave up. Days later was when I realized...... all animations had been turned off in the settings -_- lol so to avoid wasting your time like me it might be wise to check your settings first.

android animation is not finished in onAnimationEnd

It seems that an android animation is not truly finished when the onAnimationEnd event is fired although animation.hasEnded is set to true.
I want my view to change it's background drawable on the end of it's ScaleAnimation which it does, but you can clearly see that it is changed some miliseconds before it finishes. The problem is, that it flickers because the new background appears (=is) scaled for a short time until the animation really finishes.
Is there a way to get either the real end of the animation or just prevent the new background from beeing scaled this short period of time?
Thank you!
//EDIT: I'm using an AnimationListener to get the following call:
#Override
public void onAnimationEnd(Animation animation)
{
View view = (MyView) ((ExtendedScaleAnimation) animation).getView();
view.clearAnimation();
view.requestLayout();
view.refreshBackground(); // <-- this is where the background gets changed
}
Here is the actual bug related to this issue http://code.google.com/p/android-misc-widgets/issues/detail?id=8
This basically states that the onAnimationEnd method doesn't really work well when an AnimationListener is attached to an Animation
The workaround is to listen for the animation events in the view to which you were applying the animation to
For example if initially you were attaching the animation listener to the animation like this
mAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation arg0) {
//Functionality here
}
});
and then applying to the animation to a ImageView like this
mImageView.startAnimation(mAnimation);
To work around this issue, you must now create a custom ImageView
public class MyImageView extends ImageView {
and then override the onAnimationEnd method of the View class and provide all the functionality there
#Override
protected void onAnimationEnd() {
super.onAnimationEnd();
//Functionality here
}
This is the proper workaround for this issue, provide the functionality in the over-riden View -> onAnimationEnd method as opposed to the onAnimationEnd method of the AnimationListener attached to the Animation.
This works properly and there is no longer any flicker towards the end of the animation.
I was abe to resolve this by calling clearAnimation() on the view being animated inside onAnimationEnd, that took away the flicker
Its weird why would anyone have to do that, as onAnimationEnd callback should have been called only if the animation has already ended. But I guess the answer lies in the depth of Framework on how view/layout handles animation callback.
For now take it as a hack-free solution, that just works.
animation.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation anim) {
innerView.clearAnimation(); // to get rid of flicker at end of animation
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams
(innerBlockContainer.getWidth(), innerBlockContainer.getHeight());
/* Update lp margin, left/top to update layout after end of Translation */
ViewGroup parent_ofInnerView = (ViewGroup)innerView.getParent();
vp.updateViewLayout(innerBlockContainer, lp);
}
public void onAnimationRepeat(Animation arg0) {}
public void onAnimationStart(Animation arg0) {
}
});
innerView.startAnimation(animation);
I had same issue and solved it using
view.clearAnimation();
before
view.startAnimation(anim);
I had a similar problem and I used Soham's solution with custom view class.
It worked fine, but at the end, I've found a simpler solution that worked for me.
After calling the view.StartAnimation(animation), and before the next step in my program, I've added a short delay that will be long enough to let the animation finish, but short enough to be unnoticeable by the user:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
nextStepInMyProgram();
}
}, 200);// delay in milliseconds (200)
For some reason the onAnimationStart works properly, and the onAnimationEnd doesnt. So heres how I originally did it and what I changed:
Attempt 1 (flicker):
a) Move image from 0px to 80px
b) In onAnimationEnd, set the image's location to 80px
Attempt 2 (no flicker):
a) In onAnimationStart, set the image's location to 80px
b) Move the image from -80px to 0px
Hope that made sense. Basically I flipped the way I did it
Try to use getAnimation() from your object:
public void onShowListBtnClick(View view)
{
rightPanel.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.slide_left));
rightPanel.getAnimation().setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// write your code here
}
});
}
An easy fix is to add one line to AnimationListener.onAnimationEnd():
#Override
public void onAnimationEnd(Animation a) {
a.setAnimationListener(null);
…
}
annimation can be also stopped on screen rotation. in this case onAnimationEnd() is not being called. my workaround:
animation.setDuration(animationDuration);
animation.setAnimationListener(new AnimationListenerAdapter() {...});
view.startAnimation(animation);
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(!animation.hasEnded()) {
// here you can handle this case
}
}
}, animationDuration + 100);
I had this issue because my Animation was not started in the main thread.
This resulted in a duration of 0.
However , the Animation did play correctly - it just called onAnimationEnd() immediately after execution.
If you are using repeat count as infinite, then onAnimationEnd would not get called. Check the documentation link
You can also use setUpdateListener, then check the current fraction of the animation progress and act accordingly.
Here's a Kotlin example for a fade-out animation which eventually makes the view gone from the layout:
view.animate()
.alpha(0f)
.setDuration(duration)
.setUpdateListener { animation ->
if (animation.animatedFraction > 0.99f) {
view.visibility = View.GONE
}
}
.start()
This worked for me:
#Override
public void onAnimationUpdate(ValueAnimator animation) {
if (Float.compare(animation.getAnimatedFraction(),1.0f)) {
// animation ended;
//do stuff post animation
}
}

Categories

Resources