使用 ColorMatrix 实现界面整体饱和度渐变

Updated on with 0 views and 0 comments

1.序言

Android 原生手机熄屏的时候可以看到屏幕饱和度会减低变灰,然后有一个缩放的动画再关闭屏幕。我一直很好奇这个饱和度变低的效果到底是如何实现的。今天决定来尝试用自己的方法实现一下类似的效果。

先上效果图

gif20190516170046.gif

2.思路

第一反应也是最容易想到的方法就是使用ValueAnimator在UpdateListener 里面遍历所有window.decorView下的子View,依次改变其饱和度。但是不用想都能知道这个方法有很大的问题。如果界面的控件有很多的话,那光跑这个效果就足以榨干手机的性能了。编写Android 里面的动画效果其实有两个很重要的点。1.用尽量少的性能实现相同的效果 2.不要用物理的思维去实现(比如有些悬浮粘附效果其实只是两个View交替显示的障眼法)既然依次遍历不可行,那我是否可以只改变一个View来实现这个效果呢?

3.实现

首先随便写一个带按钮的布局

image.png

关键是必须在最外层有一个match_parent大小的ImageView可以覆盖住整个布局
设置按钮的点击事件

 btn.setOnClickListener {

            val bitmap = Bitmap.createBitmap(
                relative.width,
                relative.height, Bitmap.Config.ARGB_8888
            )
            val canvas = Canvas(bitmap)
//            window.decorView.draw(canvas)
            relative.draw(canvas)
            img_screen.setImageBitmap(bitmap)
            val valueAni = ValueAnimator.ofInt(100, 10)
            valueAni.duration = 1000
            valueAni.addUpdateListener {
                val i = it.animatedValue
                cMatrix.setSaturation(((i) as Int).toFloat() / 100)
                img_screen.colorFilter = ColorMatrixColorFilter(cMatrix)
            }
            valueAni.start()
        }

就这么简单就实现这个整体饱和度渐变的效果了。
relative是最外层的布局,通过relative.draw方法将当前布局截图到bitmap,使用ValueAnimator 计算 1 - 0.1的饱和度,然后通过设置ImageView 的colorFilter 实现截图的遮罩效果。

End

虽然很简单的实现了饱和度变化的效果,但是这个方法局限性特别大,因为最外层的ImageView会遮挡到后面的View,因此需要配合的隐藏和显示这个ImageView,仅仅作为一个思路或者用于某些特殊场景(例如弹出PopurWindow时让背景变化)。