Prevent all views redraw - android

I have an FrameLayout which contains many child view. Each child view implements the onDraw() method to draw some shapes it maintains. Whenever I change something on a child view, I see that all other child-views will be invoked to re-draw itself. This makes the application runs slowly. Is there any way to re-draw only current child-view?

Related

Determine if view was invalidated (changed)

How I can determine if a view was invalidated? I see that the View class has isDirty() method but it doesn't seem to work in my case.
I'm making a custom layout that can animate blurring of it's content. It extends FrameLayout. So at first the layout draws it's first child to a bitmap, and than displays the bitmap instead of actual view. Also it starts AsyncTask that creates blur animation steps.
So I need to know when the child view was changed so I can redraw the bitmap and restart AsyncTask.
I've found that this can be implemented using ViewTreeObserver.OnPreDrawListener

Animating a group of children in a viewgroup

I'm working on a custom ViewGroup.
This ViewGroup has a bunch of children. I need to animate a few and change their position. I understand that Android animations move just the bitmap and not the real object. I've been trying to MOVE them by following various resources but have failed.
What I'm doing with ViewGroup so far:
Measure children and the ViewGroup
Position children in onLayout
What I'm trying to do further
Use a custom animation to move a small subset of the children. I'm using a custom Animation object because I need to move a bunch of Views and I'm applying translationX on all of them together. The other option that I know is to start a separate Animation on all of them and the thought of which makes me think it's gonna be unoptimized.
Problem
Views animate fine, but their real position remains unchanged. So the next time I'm trying to do the same kind of animation, but on the new co-ordinates, it doesn't work. Because, their positions haven't updated.
What did I try
Use onAnimationEnd to layout each of the children to the new left, top, right and bottom position. All views vanished
On onAnimationEnd, reset translationX to zero and then start re-positioning the views. No effect of calling view.setTranslationX(0f)
Can someone please help me with the correct way of doing this? Thanks
when animating call layout() on your child Views

Custom parent view entirely redrawn when part of custom child view is invalidated?

I have just started making custom views in Android, so I am yet to learn all the facts about the paint (draw) cycles for view hierarchies, and the effective use of View methods invalidate and onDraw. But I have come across a puzzling behaviour.
I have a custom viewgroup, extending the RelativeLayout class. That is my parent view. Within that, as children, I have several custom child views. From time to time, in response to user actions, I need to redraw various parts of these views, both parent and childen.
Typically this is the sequence of events. From within a child view class I invalidate a small area of it, by calling invalidate(rct) where rct is the Rect that delimits the area I need to update.
The puzzling thing is that this very localised action provokes a truly excessive and global response. It seems - from the evidence of my LogCat trace output - that:
(1) the entire parent view undergoes a complete redraw
followed by:
(2) every child view undergoes a complete redraw
Admittedly, if response (1) happens then (2) should indeed follow, as all child views would then need complete repainting. But why does (1) happen at all?
Is that the normal behaviour for the paint cycle of a view hierarchy? If so, it seems so wrong! I would have expected, instead, that only a small area of the parent might need to be redrawn, directly underlying the rectangle marked dirty in the child view that is to be redrawn. And, further, even that small area of the parent should need redrawing only if the overlying child is not fully opaque in that area.
The evidence for this seemingly nuke-the-lot wholesale redrawing activity is that in each onDraw method body for each of my custom views, I have a LogCat trace statement as follows:
#Override
protected void onDraw(Canvas c) {
Rect rct = new Rect();
Boolean doDraw = c.getClipBounds(rct);
Log.v(LOGTAG, "onDraw Entry doDraw=" + doDraw + " rct=" + rct);
....
}
The LogCat output makes it clear that each onDraw call is for the entire surface of the view.

Confused with removeAllViewsInLayout(), postInvalidate() and refreshDrawableState()

I am really confused with this three functions: removeAllViewsInLayout(), postInvalidate() and refreshDrawableState().
removeAllViewsInLayout()
When I use removeAllViewsInLayout() in my program, all views were gone. But when trigger postInvalidate() to refresh, nothing. I think removeAllViewsInLayout() deletes all of my views. Is there a way to clear all things in my view but not delete it?
postInvalidate()
I want to refresh my view. But with refreshDrawableState(), I can do only once, why?
If you call postInvalidate() (or just call invalidate() if on the UI thread), the system will schedule a redraw of your view. Your onDraw() method can then do whatever it wants, including just drawing a blank canvas.
If you call removeAllViewsInLayout() it will do just that -- remove every view, including your custom view. You probably don't want to do that. (EDIT: removeAllViewsInLayout() is intended to be called only as part of layout calculations for a ViewGroup. A typical use would be by a ViewGroup that "owns" a large number of views but during onLayout() processing decides to display only those children that actually fits on the screen. If you are not in the process of computing the view layout, you should call removeAllViews() instead.)
Calling refreshDrawableState() is only useful if your view is using a Drawable object that is sensitive to the state of the view. For example, a Button will use this so that the background drawable changes color when the button is pressed. For what you are doing, you don't need to bother with this method, either.

Rendering absolutely positioned sprites over a regular Android layout

I've got a standard RelativeLayout laying out my Buttons and TextAreas. What I want to do now is be able to draw various sparks, flying cows etc. at arbitrary places on the screen on top of the whole thing. What's the best way to do this? Should I override onDraw() on the containing View and draw after calling super.onDraw()? Or is there some better way of drawing a layer on top?
You'll probably want to put your Relative layout and a custom view which isn't focusable and doesn't consume motionevents inside a FrameLayout, then override OnDraw in that custom view. That way you can call invalidate() on that view without making Android redraw everything else.

Categories

Resources