So I decided to dig and to try to reproduce this effect by myself. I also remembered that our graphic designer at LevelUp Studio asked us many months ago if it was possible to achieve Yahoo weather iOS application design. You can take a look at this video to understand.

Here is the result:

Introduction

After some researches I found this Stackoverflow post explaining how to blur a Bitmap object. This script is really great to blur images but has one default : the processing time.

To blur a 720×1600 image, it takes around 3 seconds (Thanks to Romain Guy advice, it only takes 200ms now, 85ms on JellyBean 4.2 with RenderScript). So the real time processing was impossible to implement. That was the moment to thinks about how to trick!

Yahoo weather effect

I decided to start with the Yahoo Weather effect. If you look at it, there are two effects on the image during the scroll :

The image seems to be blurred in real time

The image has a small parallax effect

To achieve this, I just add a ListView on an ImageView. I also add a header to the ListView and make the image move by the half of the header top position:

When entering my Activity, I verify that an image exists in the internal memory. If not, the standard image is loaded in a Bitmap and blurred in a thread (to avoid freezing the UIThread). For the example, all the views are visible during this time, but, depending on what you want, you may just have an empty view displayed during the processing time.

When all is ready, I put this Bitmap in my ImageView and set its alpha property to 0 so it’s invisible for now.

To fake the real time blur effect, I just modify the alpha of this ImageView during the scroll. The code above is now changed to:

Optimizations

The perfectionists right there will at this point say that this implementation isn’t optimized at all. I couldn’t agree more. My point was to show how to implement it really quickly, not to make it as light as possible.

However, I can give some hints to improve these effects. Let’s see the overdraw of this Activity.

As you can see, there are many areas that are displayed in red. This is because many views are stacked on each other.

I see two ways to reduce this overdraw:

Merge the two ImageViews. By crafting a custom view that would render the addition of the original image and the blurred image (and its alpha), it would display one less layer.

Cut this new custom view by the size of the header and put it below it. So the image would give the illusion that it slides underneath it.

Merge the ImageView and the TextView in the header. There would also be one less layer on the top of the screen.

I didn’t have time to implement it, but as my code is open-sourced, feel free to send me pull requests on Github!

Limitations

Graphical limitation

You may say that I chose a horrible image for my demo. That’s completely right! And it’s done on purpose.

Remember that you may not have the control on the image displayed by this way. So you will have to take care about the readability of your content. Avoid fully transparent background to give some contrast to your content.

API limitation

As you can see in the Manifest file, the minimum API is set to 13.

This limitation is due to the Switch widget I used. Without it, you could set it to 11.

And by implementing tricks to set the alpha values to your views, it may be set to a lower version.

Pre-processing

The unavoidable pre-process is a hard limitation. 5 seconds is long to wait for a user. It’s up to you to find a way to make him wait during this time or to process when your user don’t use your app. It may be a good idea to see if Renderscript or OpenGL could have a better render time on this part.

As Romain Guy says on my Google Plus post, the process time could be drastically reduced by working on a scaled down version of the image. He also confirmed that using RenderScript is a good idea to reduce this time even more.

Conclusion

I completely agree with Romain Guy when he says:

Graphics is all about tricks and illusions.

I tried to show you how to fake an effect that is impossible to render natively and I hope I succeeded. When I showed this Proof of Concept to some developers at the Droidcon Paris earlier this week, they were really astonished that it could be possible, so I guess I have.

But now, our graphic designer won’t trust me when I say something is not possible to do…

Finally, if a developer of the Path application stumble upon this post, maybe it’s time to solve this 😉

42 Comments

The pre-processing step does not have to take so long. When blurring an image, a very common technique is to work on a downsampled version of the bitmap.

You first create a bitmap that’s 50% or 25% (or less) the size of the original bitmap, using bilinear filtering to create the smaller version. You can then blur this smaller version using a smaller radius (since you’ve already blurred the image a bit.) And at draw time you can simply scale the image back up, still using bilinear filtering to blur it even further. Not only is this solution faster but it also uses a lot less memory since you only keep a smaller version of the bitmap in RAM. You could also use multiple threads on multi-core devices.

You could (and should) also use Renderscript to do the blurring when you’re running on Android 4..0+. You’ll easily get an order of magnitude or two faster.

It offers a higher-quality Gaussian blur but with the likelihood of being more performant. I haven’t actually profiled anything or tracked allocations, but it seems logical. If nothing else, I use it in my application without any notable drops in performance and the effect looks better in my opinion.

There’s a slight flaw/bug to consider. When the device’s orientation is rotated, the blur effect (on content text) resets and this shouldn’t be so. It should carry over the scroll position and alpha data over when orientation is changed.

Thanks a lot for this implementation.
Can you suggest something on this:
I want to have a Yahoo Weather like information instead of the ListView we are using. I wanted display some information, maps, etc.
Any suggestions?

Hi,
Sorry for the late answer.
The “Yahoo Weather effect” will work on any ScrollView, as the effect works on a ScrollListener.
Be careful to avoid OutOfMemory crash if your activity allows orientation change.

Im attempting to take this and implement it into a Dialog, to achieve the new iOS 7 look. How would i go about using the java.io.Files and being able to access the getFilesDir and all the other methods that i now cannot access because I’m using extends Dialog and not a extends Activity like your MainActivity does… any workaround? Basically im getting a bunch of “Cannot resolve methods”

Great effect and solution. But I can’t find out how to use it when I want make blur effect in my Dialogs? Here You use blur image, but have can I blur all background if there are to make ImageViews and Buttons ?

If I understand well, you want all the background below the dialog to be blurred?
If so, take a look at this code: https://github.com/ManuelPeinado/GlassActionBar
Somewhere, it takes a snapshot of the Activity content. Then, you will be able to blur it and to use it as your dialog background.

But I have visualizer’s view, it’s draw dynamic views like winamp or some other player and I want that background view were blur and draw visualizer’s view blur too.
I can send some screenshots to explain, because my English is not so perfect.

Please lookup how to us “a” and “an” in a sentence, and when you should use one over the other.. You’ve used the wrong one several times in this page, and it totally throws people off when you use the wrong one.
thanks

As far as I know, this doesn’t cause any problem. But the article wasn’t about the parallax effect and I dig not dig really hard. Maybe a translation would be better even if only available for API 11+.

Thank you for your hard work, this is extreamly helpful! but i have another question: is it possible to implement that code to make the notification panel blured? i have no problems to make it transparent or with a custom picture, but blured..?

Hi Nicolas, very nice work man! Thanks for your imagination and skill.
May I ask you, how do I move the Bluried to the bottom of the image?
I want to make an effect like:
[image]
[bluried image bar]
[textview scrollable*]

If i put that inside a fragment and put inside a pager will the parallax work horizontally?