DecorView真会玩

/ 0评 / 4

前言

一个Activity持有一个PhoneWindow,PhoneWindow中就有我们今天的主角-DecorView,通过下图可以很明白的看到其地位。总的来说,DecorView就是我们设置的布局的最外层的布局,我们通过setContentView设置的布局只是DecorView的子布局而已。当然不同的手机以及不同的Android版本可能具体的层级不同,但是大致为这样。

DecorView是啥

DecorView只是一个普通的ViewGroup,继承自FrameLayout,既然他是一个ViewGroup那么我们可不可以在里面添加View呢?

final ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
decorView.post(new Runnable() {
    @Override
    public void run() {
        View tv = LayoutInflater.from(MainActivity.this).inflate(R.layout.decor_layout, decorView, false);
        decorView.addView(tv);
    }
});

通过上面的代码可以看到我们添加的TextView已经添加到DecorView中了,并且由于DecorView是一个FrameLayout,我们的TextView在最顶层。

上面有一点需要注意的,我使用的是View.post()方法去延时添加View,这么做的原因是如果我们在onCreate中直接去添加View,可能后面的流程中系统会添加statusBar等,这样一来我们的视图就会被遮挡一部分。比如下面直接在onCreate中添加

@Override
protected void onCreate(Bundle savedInstanceState) {
    ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    View tv = LayoutInflater.from(MainActivity.this).inflate(R.layout.decor_layout, decorView, false);
    decorView.addView(tv);
}

可以看到,我们的视图被遮挡了一部分,因为系统后面又添加了一个statusBar,当然我们也可以在需要的使用使用View.bringToFront()/ViewGroup.bringChildToFront()去将添加的布局层级提升到最上面!

玩法一:程序闪屏页

一般的程序启动的时候都有一个闪屏页面,虽然我们能够通过自定义style的方式去添加一个闪屏页,但是如果当程序比较小,启动速度较快,那么闪屏页面的时间不容易控制,如果采用普通的方案,跳转到一个单独的Activity然后延时跳转到主界面,这样也不是不可以,但是总觉得不够优雅,当我们知道decorView可以添加布局以后我们能够想到什么呢!!!!直接跳转到主界面,然后添加闪屏界面到最上面,延迟销毁即可。

/**
 * 加载闪屏页
 */
private void loadSplashView() {
    final ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
    final View view = LayoutInflater.from(this).inflate(R.layout.activity_splash_view, decorView, false);
    //这里直接添加的原因是应为项目是全屏的,没有statusBar!!!
    decorView.addView(view);
    //延迟1.5s销毁
    decorView.postDelayed(new Runnable() {
        @Override
        public void run() {
            decorView.removeView(view);
        }
    },1500);
}

这样做的优点,如果我们没有使用ProgressDialog等去做加载等待的话,那么当我们的闪屏页显示出来的时候程序也能提前加载主页的数据,而且也稍微提升一点性能。# 玩法二:用户操作引导

类似于下图的效果,我们可以将一个View直接全屏添加在DecorView中,然后进行绘制,这样一来引导页面就完全脱离了具体的ui布局,实现了代码上面的解耦。具体可以参考
https://github.com/huburt-Hu/NewbieGuide

玩法三:使用View的Dialog

对于这种玩法只能说一句佩服,具体可以查看XPopup这个库,作者直接将布局添加到DecorView中,然后将其做各种动画,几乎以假乱真,首先添加进去的布局就是一个ViewGroup,Dialog显示的布局则直接添加到这个ViewGroup中,这样一来,就可以对Dialog的View进行各种动画了!!!再具体的可以自己查看这个库的demo以及源码,可以实现很多厉害的特效!!!

其他

当我们知道可以往decorView中添加View以后,其实我们还可以想到很多其他的玩法,比如点击图片放大,可以直接添加一个View去做动画等等。其实还有一个布局则是Window.ID_ANDROID_CONTENT,也是一个FrameLayout,我们通过setContentView设置的布局就是其唯一的子View,所以我们也可以通过如下代码去添加子视图,视图在Activity的界面之上,不包含状态栏等

final ViewGroup contentView =findViewById(Window.ID_ANDROID_CONTENT);
View tv = LayoutInflater.from(MainActivity.this).inflate(R.layout.decor_layout, contentView, false);
contentView.addView(tv);

https://github.com/huburt-Hu/NewbieGuidehttps://github.com/li-xiaojun/XPopup

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注