So there are a few questions about animations not ending when using cancel() on them. You also need to call clearAnimation on the view. Can someone explain why is that? It's also very strange to me, that the View needs to know about what animates it.
You call clear animation to reset the transformation matrix that the view is using to transform its canvas during the animation. The main problem is that old Android animation system is a crap since it relied on animating a "snapshot" of the actual view.
As for the cancel, when you invoke cancel what happens is that you stop the runnable that is applying the steps of your Animation. Of course you cannot be sure in which state your animation is getting stopped
To be clear:
The View Animation Framework , a.k.a "old animation framework", only animates the translations of the view, and not the actual properties. So lets say you animate the view's location on the X dimention: the value of the view's X property remains the same.
In relevance to your question, this means that canceling the animation draws the view back in its original position. So it doesnt matter when did the animation was canceled.
Object animation, introduced in Android 3.0, animates the actual properties. This means that when you cancel the animation, the view remains in its relevant position. So you might not know exactly WHEN was the animation canceled, but you can clearly find out WHERE is it drawn right now.
If you need object animation for older versions of Android, and frankly why go any other way, you can use the 9OldAndroids library.
Mor on the difference between the animation frameworks here.
Related
I tried searching around and found that you have to set a listener to change the actual position of the view when the animation ends. But the thing is, I don't know how I can get the end values from the ObjectAnimator I am using.
Isn't there an easy way to do this aside from setting listeners to all of my Animators, there are like 9 of them. Something like a setFillAfter(true) I always see that but I can't seem to find what Animator object uses it.
It turns out you have to have an AnimatorListener attached to the Animators that will do this for you. But that is too much for me because I have multiple Animators. So what I did, I positioned them on the layout in what they would be after the end animation, then I made the Animator to animate from the start position to their end position. That way I don't have to fret over the actual positions of the views
I am using animators (ObjectAnimator) to animate few properties (scale, rotate) of a view.
Target view is animating properly when ObjectAnimators are set to it.
But there is an added requirement to get view to the original position (reset) after a while.
I tried to cancel() the animator but it only cancels the animation and doesn't reset the view.
Possible solution : creating another animator that does just opposite of the initial animator.
Is there any other way to reset it ?
See the solution I came up with as I had a similar issue with animations inside views in a recycler view, so I had to find a way to reset them:
Trying to reset values from Property Animator to be used in recycler view
Good news in Android O these will be better supported
I met the same problem, because I animate the view use ViewPropertyAnimator, addView() and removeView() again and again for not creating new view, but a view can be shown once, when you remove the view, you call addview() again, it is no show, but you see the property visibility is visible and animationListener also be called. it is strange.
I had the Same problem with my views . so I came over this problem with this trick .
So We assume we have a view that applying an animate after clicking on it .
viewLayout.arrow_back.setOnClickListener {arrow ->
arrow.animate().rotationXBy(50F) // this is a just simple anim not so usefull
.start()
arrow.isEnabled = false
}
I hope it'll Help someone .
Both ObjectAnimator.cancel() and ObjectAnimator.end() don't cancel the effects the animation had on the animated object, but rather just cancel its execution at the point in which the methods were called (see ValueAnimator's documentation for more details).
Now, I can think of three main ways to accomplish what you wanted:
Put a listener on the ObjectAnimator, and when OnAnimationEnd/OnAnimationCancel is called, manully reset the properties of the view.
If the properties of the view you want to reset are those given to it in the XML file, you can re-inflate it. For more details, check out this answer.
Use the ObjectAnimator.reverse() method to reverse the execution of the animation, effectively reseting the properties of the view. Preferably, you would want to call start the reverse when the animation ends, so you'd probably need to put a listener on the animator and check when OnAnimationEnd with the animtor to reverse is called.
Do you mean stop a running animation? If so, call clearAnimation() to remove animations from the views that you called startAnimation();
If what you mean is to reset the view to its original appearance after the animation is over, always setFillAfter(false); to the animations.
I have an activity which starts with a number of invisible views. I then use handler.postDelayed to make every view visible again with a slide animation and the BeginDelayedTransition method. Normally all the views should slide in, one after another. Anyway i noticed that depending on the time interval between each runnable and even depending on the device i test the app on, some of the animations are totally skipped and the view just appears without any transition. I think it may be related to the time it takes to beginDelayedTransition to calculate the changes in the visibility thus instantiating the correct animation.
Is anyone experiencing the same problem? Is there any workaround for this, other than calling a TranslateAnimation every time?
Thanks in advance!
I am making a game in which I have 5 buttons, looking like clouds, falling from the "sky".
That means that when my activity starts, 'clouds' cannot be seen, since the marginTop is set to -100dp.
From that position they start falling down untill they get lost on the bottom side of the screen.
The thing is, I need those buttons to be clickable, during the process of animation.
So far, I found some documentation about how I can make the buttons clickable AFTER the animation ends. But I don't need that. I need to be able to click on the buttons through the animation time itself.
NOTE: I need something that works with versions before 3.0.
Anybody has any link to documentation or some example or anything ?
After doing some research, I found out that there are two types of animations:
View Animation and Property Animation.
The view animation can only animate View objects. It also lack a variety of animations, since it can do only stuff as scale, rotate, move... It cannot change background color, for example.
Also, the disadvantage of the View Animation is that it only change the position of where the View object is DRAWN. Physically, it still stays in the same position.
That's why the button is un-clickable, after the View Animation is finished upon it.
Property Animation, in the other hand, can animate both View and non-View objects and it doesn't have constraints as the View Animation.
When objects are moved, for example, with the property animation, they are not just drawn on some other position on the screen, but they are actually MOVED there.
Now, Property Animation is a lot more complex to write than the View Animation, so if you don't really need all the advantages of the Property Animation, it is suggested to use View Animation.
Source:
Property vs View Animation
Tutorial and SupportLybrary up to API 1:
nineoldandroids
You can change the buttons to imageViews and then do
imageView.setOnClickListener(myListener)
then set myListener to do whatever you previously wanted to happen on the buttons onClick. Your activity will have to implement OnClickListener
Added bonus: you can make the images look like clouds :)
I have a complex frame layout containing several custom views. The main view is a graph.
Overlaying the graph is a custom view which represents a cross hair pointer that the user can drag around the graph to read off detailed information about a particular data point.
The frame layout captures all touch events, calls "hit test" methods on each of it's child views to determine if the touch was on that view then dispatches the touch event to the appropriate view.
When the user touches the cross hair and drags it, I pass the touch event to the cross hair which it uses to update it's position and invalidate itself.
Everything is working except...
All views in the layout are redrawing when I invalidate any of these child views. I know this as I have turned on "show screen updates" in developer options. At no point do I invalidate the containing FrameLayout - or at least, not knowingly.
Certainly, the Activity handling the layout does not invalidate it and I do not have any references to the parent in the child views.
I haven't posted code since a) I don't know if this might be normal behaviour, b) there's a lot of it! and c) if it's not normal behaviour, I don't know which part of the code is problematic. Of course, I'm happy to give anything that might be requested.
My minimum API is 2.3.3 and my target is 4.0. This happens on both of those versions so I suspect my code is the problem but where to start?
Any clues as to what might be going on?
There is no way for View to draw "just itself", since it depends on it's parent (which provides it's clipped and translated Canvas via dispatchDraw method). Invalidation requires whole view tree to be invalidated - this is the answer that you're looking for :)
If you'll check out the source of ViewGroup, you'll find there two important methods: dispatchDraw (which responsible for dispatching draw event down to it's childs) and drawChild (which called by dispatchDraw and let's you specify how childs will be drawn). Note, that there is no check on which View starts invalidation, although there is a RectF that specifies invalidation region. As far as I understand - you need to make sure that your invalidating View (cross) doesn't takes the whole screen, so redrawn will be only that part that it actually takes.
If understand you right, the lines of the cross-hair view cover the whole screen, i.e. one vertical line from top to bottom and one horizontal from left to right.
Now if you change the center of the cross-hair and the other views would not be redrawn, your screen would soon be cluttered with old lines from previous cross-hair positions. You would not want this, so you can be glad that the other views redraw itself too.
If you want, you can specify a 'dirty' rectangle and call invalidate(Rect dirty), which would not redraw Views that are completely outside that rectangle. Though it's up to you in that case, not to change anything outside that rectangle.
try this:
setDrawingCacheEnabled(true);
Enabling drawing cache for view will make view not be redrawn if view not changed
Take a look : Android Invalidate() only single view
May be my answer so simple, but I resolved this problem with help:
this.invalidate()
Run it for each canvas-view, and it will updating one by one (not all at once)