Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
234 views
in Technique[技术] by (71.8m points)

java - Transparent blurry view which blurs layout underneath

I've got a Linearlayout which I've made transparent, and now I'm looking for a way to give it a Blur effect, so what's ever underneath it gets blurry. Just like the Windows 7 Aero look (see screenshot).

I know you can do a blur effect like this:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

But this only applies to like blurring the background when a dialog appears.

I've been googling for almost an hour, and I can't find anything. Does anyone have any suggestions on how to do this?

Thanks

Windows 7 Aero effect

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Blurring in real time on android is still a hurdle. Here's a comprehensive comparison between some of the viable mechanisms:

StackBlur (already listed in the answer by Onur under the moniker fastBlur):

How it looks (at radius 20):

enter image description here

Logged time(ms) to generate each BitmapDrawable:

I/(10266): Total time taken: 35
I/(10266): Total time taken: 54
I/(10266): Total time taken: 48
I/(10266): Total time taken: 36
I/(10266): Total time taken: 48
I/(10266): Total time taken: 39
I/(10266): Total time taken: 49
I/(10266): Total time taken: 50
I/(10266): Total time taken: 35
I/(10266): Total time taken: 47

Average => ~ 44.1 ms => 22 drawables per second

RenderScript:

ScriptIntrinsicBlur provides a consistently fast blur. Its available api 8 onwards using the support library.

What it looks like (at radius 20):

enter image description here

Logged time(ms) to generate each BitmapDrawable:

I/(9342): Total time taken: 14
I/(9342): Total time taken: 16
I/(9342): Total time taken: 13
I/(9342): Total time taken: 28
I/(9342): Total time taken: 14
I/(9342): Total time taken: 12
I/(9342): Total time taken: 14
I/(9342): Total time taken: 19
I/(9342): Total time taken: 13
I/(9342): Total time taken: 13

Average => ~ 15.6 ms => 64 drawables per second

RenderScript (radius = 3) + Scaling (20%):

This is another way of getting a decent(?) but fast blur. What we do is scale the bitmap to a fraction of its size - say 20% - and apply the blur algorithm on the scaled down version. Once that is done, we scale the bitmap to its original size. Results are not as good as using the blur algorithm on the original, but they are passable. Also notice that the radius value shouldn't be too high or the resulting bitmap will be indiscernible.

What it looks like:

enter image description here

Logged time(ms) to generate each BitmapDrawable:

I/(11631): Total time taken: 5
I/(11631): Total time taken: 19
I/(11631): Total time taken: 3
I/(11631): Total time taken: 7
I/(11631): Total time taken: 7
I/(11631): Total time taken: 5
I/(11631): Total time taken: 7
I/(11631): Total time taken: 17
I/(11631): Total time taken: 5
I/(11631): Total time taken: 4

Average => ~ 7.9 ms => 126 drawables per second

StackBlur (radius = 3) + Scaling (20%):

Same concept as #3 above. Reduce size to 20% and apply stackblur on the scaled bitmap.

enter image description here

I/(12690): Total time taken: 4
I/(12690): Total time taken: 20
I/(12690): Total time taken: 4
I/(12690): Total time taken: 4
I/(12690): Total time taken: 5
I/(12690): Total time taken: 5
I/(12690): Total time taken: 4
I/(12690): Total time taken: 21
I/(12690): Total time taken: 3
I/(12690): Total time taken: 4

Average => ~ 7.4 ms => 135 drawables per second

Tests carried out on Nex4. Bitmap size - 200px x 200px

Another tip: methods buildDrawingCache() and getDrawingCache() themselves take a long time. An alternative to this is to create a Bitmap using the dimensions of the view you need to blur:

Bitmap toDrawOn = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);

// Create a canvas - assign `toDrawOn` as an offscreen bitmap to it
Canvas holdingCanvas = new Canvas(toDrawOn);

// Now, let the view draw itself on this canvas
yourView.draw(holdingCanvas);

The view is now drawn on toDrawOn and you can use it however you please.

This, in my experience is much faster than generating and accessing a view's drawing cache.

If you need help implementing any of the 4 methods listed above, let me know in comments.

Do keep in mind that the gifs above have been downscaled and whatnot. If you'd like to see original screen-capture (mp4) files - check this Link.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...