Thursday, July 25, 2013

New in Android 4.3: ViewOverlay

Since we just released Android 4.3 yesterday, I thought I'd wax poetic about one of the features I worked on in the release: Overlays.

Android devs
Come out to play:
Use the new
ViewOverlay.

There are many ways to get custom graphics (drawables) to appear in a view. You can set a background drawable if that's what you want, or you can use an ImageView, or you can create a custom View subclass and override onDraw(). Or if you want to draw them over the children in a layout, you can override the layout and override dispatchDraw() to draw them after all of the children (after a call to super.dispatchDraw()). But sometimes you just want something simpler: ViewOverlay.

Here's how it works:

You call View.getOverlay(), which returns a ViewOverlay object. Then you call add(Drawable) on that overlay object... and that's it. You can also call remove(Drawable) to get rid of the drawable or clear() to get rid of everything in the overlay, but that's the entire API. The only other detail is that you need to set the bounds on your drawables (as you would if you were drawing them manually in onDraw()); the overlay doesn't do any positioning or sizing, it simply draws everything you tell it to, in the order in which the objects are added.

Oh, and one other thing: you can also add View objects to an overlay if you get that overlay from a ViewGroup. That is, ViewGroup overrides getOverlay() to return a ViewGroupOverlay, which is a subclass of ViewOverlay that also deals with views in addition to drawables. Once again, the API is simple: there's an add(View) method and a remove(View) method. And once again, you are responsible for positioning/sizing the views where you want them in the overlay; the overlay does not do any layout.

Essentially, the overlay is a container for drawables (and sometimes views) that is the exact size of its host view. It doesn't do layout; it just draws the stuff its told to, after it's drawn everything else in its host view (including any children of that host view, if the view is a ViewGroup).

Important caveat, especially with respect to ViewGroupOverlay: The overlay is intended for temporary display of views, not for any long-term or functional use for views. In particular, the views there are not laid out by the container (as noted above) and do not participate in focus or input events. Overlays were created to be a visual-only mechanism, for things like transient animations. Think about things like fading out a view. This can be tricky in some situations where removing it immediately removes it from the view hierarchy and makes it tough to have it drawn while it's fading out. Now you can pop it into the overlay of its parent while it's going away.

Here's another interesting thing to ponder: you can add drawables/graphics anywhere in the view hierarchy that makes sense for your situation. So, for example, if you wanted to fade out a view or some drawable while sliding it off the screen, or up-scaling it, outside of its parent container, this might normally be a problem because parent containers like to clip their children to their bounds by default. Now you can add the object into an overlay anywhere up the tree, to give you the flexibility to move/resize it as you see fit without worrying about the clipping constraints of that original parent.

Anyway, I'm sure you can find interesting things to do with overlays. So go ahead!

18 comments:

Eduard said...

Hi Chet,

After reviewing the ViewOverlay docs at http://developer.android.com/reference/android/view/ViewOverlay.html it seems there's a little mistake in your post (or may be in the doc!): should be add(Drawable) and remove(Drawable) instead of addDrawable() and removeDrawable().

In my discharge I have to say that I enjoy all your posts and videos (and even your sense of humor!)

Best regards,
Ed PC

Chet Haase said...

@Eduard: Good catch, I've fixed the error. The post was quickly written (and quickly mis-typed).

Rohit Reddy said...

@Chet Are overlays part of global changes on the view tree?

Chet Haase said...

@Rohit: I don't understand the question. ViewOverlay is simply an additional API/feature that works with the existing view API/hierarchy/functionality.

AK said...

Where is a sample for ViewOverlay?

David Bauer said...

Hello, is this new change the reasson why setting android:windowContentOverlay in the styles doesn't work anymore with Andriod 4.3 ?

Chet Haase said...

@David: Unrelated. I'm not aware of a problem with windowContentOverlay. Example?

Rohit Reddy said...

@Chet Wanted to know if the overlay is parented to the host view or not. Source code helped answer my question.

Chet Haase said...

@David: I think this is the bug you're referring to: https://code.google.com/p/android/issues/detail?id=58280. As I said, it's unrelated to ViewOverlay.

@Rohit: The overlay is parented, but it's not an official 'child' of the host view, it's a special item that is drawn after all other content in that view. But then, you must know that from the source code already.

Sorang Kang said...
This comment has been removed by the author.
Sorang Kang said...

Hi Chet,

I had tried this like developer site...but it didn't work.
I found one problem in ViewOverlay... parent.mAttachInfo.
mAttachInfo has null value and this makes remove view only.
I don't have idea for this.
How can I solve this problem?

Chet Haase said...

@Sorang: I'm not sure I understand your question. If mAttachInfo is null, this means that that view is not in the view hierarchy (it has been removed or not yet been added). So dealing with the overlay for that host view is irrelevant since it won't show up anyway.

Flavien Laurent said...
This comment has been removed by the author.
Flavien Laurent said...

Hi Chet,

I played with Overlays and here is the result on my blog

Best Regards,

FL

Chet Haase said...

@Flavien: Nice! I'm posting a couple of small comments on your blog, but it looks good.

Ignasi Busquets said...

Hi Chet,

I've posted an example here some days ago, can you check it, please?

Thanks a lot!

Anonymous said...

Chet, is this class going to be ported over to the support library?

Anonymous said...

Chet, ViewOverlay doesn't seem to work for VideoView. Any idea if support for VideoView is in the future?

Thanks