Hello,
In my application I need to have a floor plan diagram which can be
panned and zoomed. On this diagram are to be a series of small
markers. Those little marker Views need to have invalidate() called
frequently on them because the graphics drawn to their Canvas is being
animated. I have been trying to implement an extended RelativeLayout,
which I call ZoomableRelativeLayout, which would enable me to perform
simultaneous zooming on all child Views of the ViewGroup. That is, the
large floor plan graphic and its markers, all of which are child
Views, will simultaneously zoom and pan together.
In my ZoomableRelativeLayout, I have attempted to perform scaling
(zooming) to the Canvas within the overridden dispatchDraw() method,
like this:
protected void dispatchDraw(Canvas canvas){
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
}
The mScaleFactor is manipulated by a ScaleListener in the same class.
It does actually work. I can pinch to zoom the ZoomableRelativeLayout,
and all of the views held within properly rescale together.
Except there's a problem. When the scale is 1, the animated child
views are seen to redraw periodically perfectly fine. However, when
the scale is other than 1, (e.g. when zooming in), those animated
child views are only seen to update in a small clipped portion of
their area - or not at all - depending on the zoom scale.
The problem appears to be that the 'invalid area', or clipping area,
for each view seems to remain as if no scaling had been applied to the
Canvas in dispatchDraw(). If for example my ZoomableRelativeLayout
were to contain a single, simple View that draws a filled rectangle,
and it animated by flipping its colour every second via invalidate()
and onDraw(), then at a zoom of 1 it'll appear as it should do.
However, begin to gradually zoom in, the size of the square expands
and moves away from its original position. The only part of the square
that animates is whatever part of it still sits underneath that
square's original 'area'.
I have tried looking over the source for ViewGroup to see if I could
spot any solution to this problem, and the best thing I could spot was
to clear the FLAG_CLIP_CHILDREN via setClipChildren(false). Inspection
of the source of ViewGroup seemed to suggest that clipping would no
longer be applied, but unfortunately this change has had no visible
effect and the problem persists.
Probably worth mentioning is the fact that whenever I am actually
zooming in and out, or when I'm panning the ViewGroup, all of the
marker child View graphics *do* periodically redraw properly. So, for
example, when I'm panning the floor plan around or zooming, my markers
are seen to properly animate. Now when I'm zooming, invalidate() is
being called on the ViewGroup itself, obviously; and presumably calls
to scrollBy() to perform my panning lead to an invalidate() on the
ViewGroup too. It seems that invalidation of the ViewGroup leads to an
entire redraw which draws the child views with the clipping bounds
scaled as well, so that the child Views' graphics are properly updated
on the display. Calling invalidate() on the individual child Views
still causes a call to the ViewGroup's dispatchDraw(), but for some
reason the clipping area is then 'unscaled'.
Am I on a bit of a loser with my zoomable ViewGroup strategy?
Thanks,
Trev
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en