Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my layout completely redrawing when I invalidate one of it's views?

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?

like image 632
Simon Avatar asked Feb 16 '23 04:02

Simon


1 Answers

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.

like image 123
Dmitry Zaytsev Avatar answered May 04 '23 17:05

Dmitry Zaytsev