I have several ImageViews each with an indefinitely throbbing ScaleAnimation and three attempts that don't make sense to me.
If I set the animation immediately after inflating the animation the animation runs perfectly. This also tells me my helper function to create the animation (used in all three cases) is working fine.
If I set the animation immediately, but with a start time of Long.MAX, and later call icon.getAnimation().start(), that animation starts but the speed is faster than it should be and the scale is not what I set. No matter what I set the animation scale and duration parameters to, it always looks the same, unlike the previous case.
If I call icon.startAnimation(..) with a new Animation object, I get no animation. Digging into Android source, startAnimation(..) calls invalidate(), unlike setAnimation(..). If I call icon.getAnimation().start() followed by icon.invalidate() I get the same (lack of) behavior. This hints to me that the invalidate somehow breaks the animation.
So, given all of the above, is this symptomatic of a mistake I might have made? Is there something I didn't describe that I should be doing?
Finally, I've tried this with both a scale pivot specified both relatively and aboslutely, thinking there might be a bug in event order with respect to View.invalidate() and Animation.reset().
A lot of people are having problems with animation. Working with animation on anything before Honeycomb is a real pain.
I recommend downloading the NineOldAndroids library and using it as imports, that way you can use the Honeycomb animation API on all versions of android (even up to 1.0).
Related
It looks like both Animations and Animators allow me to animate properties (position, opacity, scale, rotation, etc) on objects, and I'm having a hard time differentiating between the use case for both. When should I use an animator versus an animation and vice versa?
Animations are older versions of Animators. Animators where introduced in 3.0 to help overcome some short-coming that Animations have.
Animations only change the visual representation of an object. This is fine if you're just changing opacity, but it causes issues when you translate, rotate, or scale objects. In the old days before Animators, if you translated the object, you had to perform a re-layout with the new coordinates. It could be rather difficult depending on where the object moved.
Animators on the other hand change the physical properties of the objects. This means that if you move a View to a new location, the touch coordinates will be mapped at the new location without any other intervention.
Personally, I don't use Animations much anymore unless I'm developing at API's 2.3 or less. Thankfully that's becoming less of an issue. There are also some old classes that still use Animations API especially when it comes to using xml resources such as the android.support.v4.app.FragmentTransaction class (the normal FragmentTransaction supports Animators instead).
As a side note, the project NineOldAndroids was developed to mimic functionality of Animators but using Animations so you can make apps that work all the way to 1.6.
An Animation object animate the view's image. If you use this for example, to move a button around the screen you will not be able to click on it at the new visible position because it was not truly moved, but only his bitmap representation was translated. You will also not be able to change the proportions of it since you are making modifications to a bitmap. If you use xml files, place them at anim folder.
An Animator object animate the view's property (like the margin or width). If you use this to move a button around the screen you will be able to capture clicks on it in the new visible positions. If you use xml files, place them at animator folder.
If you only need cosmetic effects, like fade in or small appearance translation, using a Animation will be more efficient because it does not call layout() or measure() methods. If you do need to capture actions like click events, use a Animator.
It looks like both Animations and Animators allow me to animate properties (position, opacity, scale, rotation, etc) on objects, and I'm having a hard time differentiating between the use case for both. When should I use an animator versus an animation and vice versa?
Animations are older versions of Animators. Animators where introduced in 3.0 to help overcome some short-coming that Animations have.
Animations only change the visual representation of an object. This is fine if you're just changing opacity, but it causes issues when you translate, rotate, or scale objects. In the old days before Animators, if you translated the object, you had to perform a re-layout with the new coordinates. It could be rather difficult depending on where the object moved.
Animators on the other hand change the physical properties of the objects. This means that if you move a View to a new location, the touch coordinates will be mapped at the new location without any other intervention.
Personally, I don't use Animations much anymore unless I'm developing at API's 2.3 or less. Thankfully that's becoming less of an issue. There are also some old classes that still use Animations API especially when it comes to using xml resources such as the android.support.v4.app.FragmentTransaction class (the normal FragmentTransaction supports Animators instead).
As a side note, the project NineOldAndroids was developed to mimic functionality of Animators but using Animations so you can make apps that work all the way to 1.6.
An Animation object animate the view's image. If you use this for example, to move a button around the screen you will not be able to click on it at the new visible position because it was not truly moved, but only his bitmap representation was translated. You will also not be able to change the proportions of it since you are making modifications to a bitmap. If you use xml files, place them at anim folder.
An Animator object animate the view's property (like the margin or width). If you use this to move a button around the screen you will be able to capture clicks on it in the new visible positions. If you use xml files, place them at animator folder.
If you only need cosmetic effects, like fade in or small appearance translation, using a Animation will be more efficient because it does not call layout() or measure() methods. If you do need to capture actions like click events, use a Animator.
I am working on a game for the Android platform. The layout consist elements which should move without stopping from top to bottom. I decided to use an Handler and I set handler.postDelayed(this, 10).
the animation "step" is 5px (It's actually not px but doesn't matter for the discussion).
The thing is, the animation frequently twitching and isn't smooth. With every call of the handler, I make some simple checks and use setX(), setY() to change the elements position.
What should I do to make the animation smooth? Should I tweak the numbers mention above? Also, I've understood the method setWillNotDraw(boolean b) might be useful - How to use it wisely?
I'd be glad if you could guide me what should I do (Kind of "Do and Don't").
Thank you!
As pskink suggests ViewPropertyAnimator is much friendlier than animating Views yourself. If you want/need to manage it manually, consider View.postOnAnimation instead of Handler.postDelayed to run your update with new animation frames.
Regardless of how you move objects, be wary of how many views you have on the screen. Moving one view can force the entire view hierarchy to redo its layout -- this can definitely kill animation speeds. Try animating a single view in an otherwise empty layout.
Profiling is very helpful for tracking down performance issues.
I have a pretty complex android-application. Already flattened view-hierarchies as far as possible, but I still have lags in the application. For example there is a menu with entries that collapse/expand by having their height set by a ValueAnimator. Typically the animation runs with a bit of a lag the first time, and smooth after this first pass.
I noticed that when i call "requestLayout()" on the Menu-Item, Android seems to do a layout-pass and multiple measure-passes through the entire hierarchy.
Since i know that although the Menu-Item(View) changes height, the Menu(View) itself doesn't, is there some way to tell this to the application?
Can i somehow perform this first pass that seems to lag myself so that it occurs after application start-up and not at the first touch-input?
Here's a sketch of the animation I'm doing:
I am not sure why a layout is being triggered in your animation but I am going to answer your question abstractly.
If you are calling requestLayout (either directly or indirectly) in your animation you are doing it WRONG.
requestLayout, for correctness and safety, does a full view traversal on the view hierarchy b/c conceptually changing bounding box of a node in the view hierarchy can result in change in the bounds of any other node. Not always the case but in general it could, thats why requestLayout is a full traversal.
All of this is just another way of saying requestLayout will eat away time from your 16.6 ms frame time slot and make your animation choppy. This is especially bad for deep and complex hierarchies with many RelativeLayouts which internally does two passes per level (thus potentially causing exponential passes on a subtree)
Now, if you want to animate change in dimension use setScale in a hardware layer. And at the end of the animation merrily call requestlayout and also destroy the layer (to free up memory).
Because its a layer, repeatedly calling setScale in your animation results in change of the texture on the GPU and as a result totally bypass the traversal mechanism of the view hierarchy. This should make it buttery smooth.
Your question looks like mine: Only relayout children and not all the tree
First, you can try to avoid complex view hierarchy for your view. If possible, explode views on views that doesn't depend on another one.
When an animation is performed, avoid any layout request. Start your animation with a delay if a layout request is pending.
Use hardware layers for animation if possible (maybe Android use it by default with ValueAnimator)
Without going into too much detail, I want to be able to 'slide' elements in a ListView similar to the 'slide to archive' feature in GMail. I'm fine with the onTouchListener and all that, my question is regarding the slide animation.
The first two things that come to mind are..
view.setPadding(slideOffset, 0, 0, 0);
and..
view.setX(slideOffset);
The former is very buttery, even on the emulator.
The latter is a bit janky on my Galaxy Nexus.
My questions:
* Regardless of what I've tried, what's the correct way to do this?
Why is setX less smooth than setPadding?
Does one approach conform to Android best practices more than the other?
Are tweened translation animations an option? If so, can you provide a brief example to point me in the right direction please?
Edit:
To be clear, I am attaching an image of the effect I am trying to emulate.
I'm pretty sure the setX() is slower because it affects its parents. When changing the X of a view, it calls the onLayout/onMeasure of the parent every time you update the value. That's because the X value of the child may cause other items on the parent to move, therefor the parent needs to redraw itself.
You can test this easily by extending the ViewGroup and writing to the log on those methods. Then, you can use both approaches, padding vs. setX, and see what happens.
Are you trying to animate the item? Or do you want the user to move it like on Gmail? You can use the ObjectAnimator to handle the "X" value of your item. Combined with a "hardware layer" for your item, it will create a smoother experience. You can find more details about how to do that here: http://developer.android.com/guide/topics/graphics/hardware-accel.html
Yeah, if you're targeting higher APIs, ViewPropertyAnimator is probably a great solution. If you have to support lower APIs, my thought process for implementation would be (and I haven't implemented this myself personally, but this should be good for performance) to:
In your touch handler, once you've determined that the user is "sliding", set the View's visibility to INVISIBLE, and store the drawing cache into a separate bitmap (Bitmap bmp = myView.getDrawingCache();)
Draw that bitmap in the same place as the view, and use the Canvas translate methods to shift the position according to the x-position of the user's touch point.
After the user lets go, translate back (preferably smoothly with an animation), recycle the bitmap, and set the view back to VISIBLE.
Check out the 3 devBytes posted on AndroidDev:
https://www.youtube.com/watch?v=8MIfSxgsHIs&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=12
https://www.youtube.com/watch?v=NewCSg2JKLk&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=11
https://www.youtube.com/watch?v=NewCSg2JKLk&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=11
https://www.youtube.com/watch?v=YCHNAi9kJI4&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=4
https://www.youtube.com/watch?v=PeuVuoa13S8&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=3