Blur effect to views using Cloudy

hongbeom
3 min readJan 27, 2021

If you look at the iOS app, you can see a view with a blur effect in many parts.

Photo by Brett Jordan on Unsplash

However, it is not easy to apply the blur effect to Android apps. While I was looking into the blur effect, I saw some algorithms that process the blur effect on Android. Among them, I thought the blur effect using the stack blur algorithm was the fastest, so I used it to create a library. (For a detailed description of Stack Blur, see the link.)

Of course, there is a good library called Blurry.

However, I hoped that there would be a function that can be applied to all views as well as image views. The results were as follows.

cloudy ☁️

It can freely adjust the radius of the blur and also detect scroll events. and all views can also be targeted.

🧐 How Implement

Because the display on a typical Android device renews the screen at a injection rate of 60 Hz, a single frame must be blurred and drawn within 16.6 ms.

The implementation process is as follows:

Gets the bitmap of the source view and stores it in a local variable.

Pull out a bitmap from the view.

First, create one bitmap with the size of the source view. After creating a canvas and setting the filter, call layout and draw to the view to apply it.

In the past, the bitmap could be imported using view’s setDrawingCacheEnabled() and getDrawingCache, but it was not used because it was now deprecated.

To speed up the blur, we cache the bitmap in the pullBitmap.

Blur the bitmap stored in the variable using the Stack blur algorithm to store it in another local variable.

This reduces the process of importing bitmap, which can double the speed of events such as radius changes.

Cut and apply the blurred bitmap to the size of the target view.

This part is a little important. Because we have to respond to scroll events. To respond to scroll events, you must ensure that the calculated x and y values do not exceed the size of the bitmap, respectively. Then create a new bitmap to fit the size of the targetView and cache it as well.

Now, when a scroll event occurs, you just need to call cropAndBlur. Of course, we should distinguish between vertical and horizontal.

Usage

First, specify the source view and the target view.

val cloud = Cloudy.with(this) // context
// source view (any view)
// isPreBlur If you specify true, it starts immediately.
.from(imageView, isPreBlur = true)
// recommend argb (@ColorInt)
.color(Color.parseColor("#50ffffff"))
// set radius
.radius(200f)
// target view (any view)
.into(textView)

And I simply use it like this.(lazy)

cloudy.blur() // start blur

Other options are as follows.

cloud.apply {
color(Color.parseColor("#50ffffff")) // @ColorInt
radius(25f) // range is 0f .. 200f
}

Available by registering with the scroll change listener.

// vertical
verticalScrollView.setOnScrollChangeListener { _ , _, scrollY, _, _ -> cloud.onVerticalScroll(scrollY)
}
// horizontal
horizontalScrollView.setOnScrollChangeListener { _, scrollX, _, _, _ -> cloud.onHorizontalScroll(scrollX)
}

Conclusion

Initially, I implemented blurring using RenderScript, but the result of Stack blur was faster, so I modified the code.

I hope it will be useful to implement blurring, and I would appreciate it if you could leave feedback through the issue. 🙌

References

--

--