ViewOverlay与ViewGroupOverlay简介

What’s Overlay

ViewOverlay是存在于API 18+(Android 4.3)内的类,它是位于View视图层顶部的一个附加层,在View所有内容绘制完成后被绘制。ViewGroupOverlay是ViewOverlay的子类,对应于ViewGroup,同样地,这个层在ViewGroup中所有内容(包括childView)绘制完毕后才会被绘制。这个层和我们的View拥有同样的尺寸,可看做浮在View上方的一个二维空间。
Overlay对象可通过View.getOverlay()ViewGroup.getOverlay()方法获得,获得Overlay对象后,就可以通过add、clear和remove方法操作其中的元素,这也是Overlay仅有的几个方法。

Why should I use it

从表面上看,任何ViewOverlay能做到的事情,都可以使用FrameLayout之类来实现,但ViewOverlay是一种更友好的实现方式。其中很重要的一点是ViewOverlay仅仅是可见的。ViewOverlay中容纳的View或Drawable不会响应任何的触摸事件,因此ViewOverlay非常适合用于动画或制作一些不需要直接接受交互的浮层。
利用ViewGroupOverlay可以让某个View在任意Layout区域内播放动画,而不管Layout是否是这个View的Parent。当一个View被add到ViewOverlay内时,如果它的Parent不为null,则它会先被从它的Parent中移除。

Let’s see

ViewOverlay

这里通过一个给View的content、padding和margin区域添加颜色的例子来说明ViewOverlay的用法,各区域的颜色遵循Chrome DevTools内各元素高亮的配色。

创建各区域的高亮对象

由于View的margin区域并不包含在其自身的绘制范围内,要绘制margin区域,必须把View的画布先做扩展。此处我们已经事先获取到了四个方向上的margin值。所有的蒙层区域均通过ColorDrawable对象实现。

@Override
public void draw(Canvas canvas) {
Rect newRect = canvas.getClipBounds();
newRect.inset(-(mMargins.right + mMargins.left), -(mMargins.top + mMargins.bottom));
canvas.clipRect(newRect, Region.Op.REPLACE);
super.draw(canvas);
}

获取View各个方向上的margin和padding值,依次创建四个方向上的ColorDrawable对象。

添加到Overlay
for (HighlightDrawable drawable : drawables) {
drawable.highlightView(view);
view.getOverlay.add(drawable);
}
实现效果

8月-08-2016 16-12-04.gif

ViewGroupOverlay

上文说过,使用ViewGroupOverlay可以让不属于一个ViewGroup的View在其区域内显示,此处演示在parent之外的区域播放动画来说明ViewGroupOverlay的作用。

ObjectAnimator anim = ObjectAnimator.ofFloat(x, "translationX", 0, right.getWidth() * 2);
anim.setDuration(2000);
right.getOverlay().add(x);
anim.start();
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
right.getOverlay().remove(x);
}
@Override
public void onAnimationCancel(Animator animation) {
right.getOverlay().remove(x);
}
});

在调用ViewGroupOverlay.add()方法的时候,View x会从原有的parent中被移除,并添加到目标ViewGroup的Overlay中。

实现效果

8月-08-2016 16-15-11.gif

示例代码

Github