How to translate a group of views efficiently? - android

I have a base layout that holds several views. I need to translate them along the x axis. Basically there are 2 types of translations happening the one that follows the finger all the way and the one that stops after certain threshold which gives a nice parallax-like effect.
So is it better to put the group of views that share same translation logic inside another container and translate the container or translate each view individually?
I know this might sound weird but Google always recommends to use flat view hierarchy because nested layouts are expensive to redraw, so does it mean that keeping just one layer of nesting and translating each view by hand is better?
Also this translation is applied to all the views in the RecyclerView, not just one.

I think you should keep a flat layout as Google recommends, and translate each view individually. I would create a custom view were you can set a threshold. And once set, you can simply pass the x position of the finger to them all, and they'll decide if they should move or not.

How to implement it requires more input or requirements before giving any suggestion. Besides performance problem, code maintainable should be considered too.
Base on my experience. With high-end phone and high API level (about >= 21), they have better hardware, effective way to manage memory and background task. The problem expensive to redraw you mentioned seems not too important with some simple animation. In this situation, code maintainability has higher priority, I will decide to have an extra FrameLayout container, wrap the View which have the same animation because you have less code => less logic. 0 or 2 FrameLayout have no noticeable difference in performance in this case
About low-end devices, if you want to target lower API users, performance becomes a top priority. Now both cases you mentioned have the effect on performance, one requires more memory to store more View and one requires more CPU to run animation. It's time for a trade-off. In your case when you have 2 translate animations run on any item in RecyclerView, I prefer to create 2 separate animations run on 2 View. This way I can save a bunch of extra containers => save memory, the animation is not run for all of the items so it only affects the CPU for a small amount of time during animation.
So to sum up, You have a different approach for each case, choose a top-priority for the case you choose, improve it, sacrifice the others that have less effect on the overall problem. No solution is 100% perfect, trade-off situation always happens when coding

Related

Choice of drawing and animation technique for an animated music staff

I'm working on an app where I must have on a part of the screen an animated music staff. That's:
5 static lines
A dozen of music notes (each one is basically an oval and a line)
A few additional symbols (clefs)
I must have a precise control of the size of each element, and have to smoothly animate position and alpha of the notes and clefs so the notes are moving right to left (disappearing when on the left of the screen, and appearing when on the right, hence the alpha). I also have to change sometimes the color of the notes.
I think I can't use standard "Animations" class, as it's an endless animation with the speed and the notes depending on real time factors.
So what is/are the best way(s) to do that and to achieve a smooth animation?
Different Views? (VectorDrawables?) Single SurfaceView where I manually draw each shape at each frame? (or TextureView?)
(Note: minimum API is set to 15)
Thank you for helping me choosing the right technique.
So you're wrong about the Animations class being infinite. It doesn't need to be. However EVERYTHING in Android will depend on real life factors- Android is not a RTOS (real time OS), there is no guarantee of execution time.
However, if you absolutely need total control, I would just jump to total control- hook the Choreographer so you get a call every 1/60th of a second, and each frame invalidate your view(s) that need to change and redraw them. If the phone is running slow for some reasons like other apps you may drop a frame or run slightly slower than 1/60th of a second, but this is as close as you can get (and what Animation classes use behind the scenes).
With animators you can animate smoothly around 5 different views on average phone. So in your case (with dozen of notes and so on) it will have around 10fps. So slightly better will be SurfaceView and handdrawing all that you want. Maybe GLSurfaceView worth considering.
In order to test this I recommend you to create some test app first, where will be 10 views flying around, and look at performance.

Animation is too slow

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.

Applying physics to Android View objects

I currently have an android application that utilises the native android views for the UI (e.g. imageviews/buttons etc)
Although this app is not a game, nor requires any heavy graphics or OpenGL, I would like to incorporate a little physics-related interaction. Nothing too significant but maybe display minor collisions/bounces, deceleration/acceleration or possibly friction.
Is this possible to simulate either within the android framework or using an external physics library like jbox2d without having to utilize an entire game engine (like andengine, libgx etc).
P.S. this is for API 15+
Thanks all.
As long as you can set/update the position of the UI elements every frame (e.g. with View.setTranslationX()), you can do it.
Animating the UI by hand would mean keeping a mapping between the UI elements and the physical (e.g. jbox2d) bodies that correspond to them. Then you update the respective positions of the UI elements to what the simulated bodies have each frame (such as body.getPosition()).
In event-driven apps, something like a Timer object is useful for scheduling the physics updates.
The easiest way (not that flexible) is using ViewPropertyAnimator.
With it you can animate properties even in parallel. Maybe you want to change a view margin from the parent left. You can change that margin there, setting up the time to move and else. Some examples on this blog
ValueAnimator is other alternative, which uses the AccelerateDecelerateInterpolator by default and you have to provide the code that changes the property you need. This official guide may suffice to get them working.
what you want is quite impossible - your options are:
you may fake stuff like bounces with animations
you can implement a whole new ui lib
you use openGL what i would do
I think this can be achieved, at least at some point.
You have access to a pretty complete Animations API. This last, together with some view bounds, distance, and probably device orientation calculations, can be used to simulate almost all the cases you mentioned.
You can create Accelerate/Decelerate, form change... and almost whatever animation you want.
How you can achieve what you are asking for:
Having different animations, one after another, creating and applying them dynamically depending on the view item state. And by state, I mean the "physical state": falling, collisioning, in touch with another view, and so on...

Performance: How to prevent requestLayout() from laying out entire hierarchy

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)

android - Slide ListView with setX, setPadding, or tween animation?

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

Categories

Resources