Thanks Romain. I'm certainly well aware that the problem is my code
and not in ViewGroup, and that one of the individual child Views will
certainly not receive a scaled Canvas if it is invalidated. I think
the reason for my confusion here -- and this will be down to my lack
of knowledge about what goes on behind the scenes between invalidate()
being called and the View's onDraw() subsequently being invoked -- is
that I thought that the invalidation of a child View was somehow
always cascaded down from the ViewGroup. My reason for thinking this
is that, when a child view has invalidate() called, I can see that the
ViewGroups's dispatchDraw() gets invoked first, prior to the child
View's onDraw().

Furthermore, when I zoom in, I can see that the parts of the child
Views that are being redrawn on the screen are always being drawn to
the correct scale; it's just as though the clipping isn't being
scaled. This was a further reason why I've perhaps mistakenly thought
that the child View was aways being provided a scaled Canvas from my
ViewGroup to draw on each time it was called to onDraw() following
invalidate() being called on that child.

Perhaps I'll just have to have my child Views all reference the parent
View's zoom scale factor variable and individually scale themselves,
perhaps having the ViewGroup and child Views all implementing an
Interface that provides methods to delegate down the scale factor. No
big deal in doing that; I was perhaps just trying to be too clever in
my first approach, certainly too ambitious considering my Java /
Android inexperience.

Thanks,

Trev



On Jun 17, 2:22 am, Romain Guy <[email protected]> wrote:
> You are scaling the Canvas and not the View itself, the children have
> absolutely no knowledge that you are doing so. When invalidate() is
> invoked on the children, how could they know that you intend to scale
> them? They can't (unless you use Android 3.0+ and the new scale()
> method.) The problem is not in ViewGroup, it's in your code: you need
> to take the scale factor into account when you invalidate the children
> (call invalidate(left, top, right, bottom) on the parent instead.)
>
>
>
> On Thu, Jun 16, 2011 at 6:08 PM, Trev16v <[email protected]> wrote:
> > 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
>
> --
> Romain Guy
> Android framework engineer
> [email protected]
>
> Note: please don't send private questions to me, as I don't have time
> to provide private support.  All such questions should be posted on
> public forums, where I and others can see and answer them

-- 
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

Reply via email to