28

I've been trying to create a custom view which has blurred shapes under text. The problem is that the BlurMaskFilter has no effect on any shape that I draw on the canvas. Here is how I'm initialising the Paint objects in the constructor:

paint = new Paint(0);
paint.setColor(0xffffffff);
paint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));

mShadowPaint = new Paint(0);
mShadowPaint.setColor(0xff333333);
mShadowPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));

And I'm calling the functions like this in onDraw():

canvas.drawOval(mShadowBounds,mShadowPaint);
canvas.drawText("hello", x, y, paint);

But this is what I see.

The Oval is not blurred yet the text is blurred.

Using android 4.0 sdk and testing on a 4.0.4 galaxy nexus device (UK). I'm wondering if this is a bug in 4.0.4 as I did test it on the emulator with 4.0 and 4.0.3 and it did blur perfectly well on them, unless I'm doing something completely wrong?

EDIT: Here is the extended View code to test it on other platforms.

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

public class BlurTestView extends View{

    private Paint paint;
    private Paint mShadowPaint;
    private int size = 100;
    private RectF mShadowBounds = new RectF();

    public BlurTestView(Context context) {
        this(context, null, 0);
    }

    public BlurTestView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BlurTestView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        paint = new Paint(0);
        paint.setColor(0xff333333);
        paint.setTextSize(size);
        paint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));

        mShadowPaint = new Paint(0);
        mShadowPaint.setColor(0xff333333);
        mShadowPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));

        mShadowBounds.top = size;
        mShadowBounds.bottom = mShadowBounds.top+(size /2);
        mShadowBounds.left = 0;
        mShadowBounds.right = (int)paint.measureText("hello");
    }

    @Override
    public void onDraw(Canvas canvas)
    {
        canvas.drawOval(mShadowBounds,mShadowPaint);
        canvas.drawText("hello", 0, size, paint);
    }

}
fasih.rana
  • 1,645
  • 1
  • 14
  • 27
  • 2
    I'm seeing the same thing on a Galaxy Nexus running 4.0.4, only text is blurred, nothing else. Running the same test app on my Gingerbread Incredible properly blurs all shapes and text. – Josh Jul 06 '12 at 18:20

3 Answers3

42

Looks like a bug to me. I reported it to the Android team; we'll see what they say.

It renders correctly if you set android:hardwareAccelerated="false" on your Activity in AndroidManifest.xml.

Here is the official word from the Android graphics team: "BlurMaskFilter is not supported with hardware acceleration." (As of July 10, 2012)

Sparky
  • 8,437
  • 1
  • 29
  • 41
  • Yes it does render correctly if hardware acceleration is set to false. But unfortunately I can't do that as the application uses hardware acceleration. Thank you for your reply though. – fasih.rana Jul 11 '12 at 11:43
  • I think it is reasonable to use mostly hardware rendering but force software rendering on specific Activities that have trouble, as long as the performance is good. – Sparky Jul 11 '12 at 12:01
  • 17
    You can disable HW acceleration on the VIEW level: myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); – Zsolt Safrany Dec 14 '12 at 15:10
  • 1
    @chester1000 It's not in the public bug list, sorry. But Romain Guy provided the answer, directly in response to this SO topic. – Sparky Jan 11 '13 at 13:00
  • @Sparky: I was just wondering if I can "star" sth, to be notified on the status change. I solved my problem already using RadialGradient's :). Thanks for quick answer! – meeDamian Jan 11 '13 at 13:20
  • 1
    As of 2015, this fixed the issue for me. – locrizak May 18 '15 at 04:21
  • Is this still an issue? So if we want to use both PorterDuff.Mode.CLEAR and blur, we can't? – mitsest Jun 25 '18 at 12:42
5

If you can not disable hardware acceleration in your activity (for example it uses TextureView which require hardware acceleration) you can just call setLayerType with first parameter LAYER_TYPE_SOFTWARE and the second parameter null for your view.

Like this

public class BlurTestView extends View {

    public BlurTestView(Context context) {
        this(context, null, 0);
    }

    public BlurTestView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BlurTestView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        // Disable hardware acceleration for this view
        setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

        // Perform other initialisation 
    }

    // Other methods and so on...
}

More info about mask filters, effects and shaders you can find here.

Sergey Pekar
  • 8,555
  • 7
  • 47
  • 54
1

I had the same issue while adding a filter to a path. I noticed that setting the target to 13 or below allows the filters to work. 14 and up they didn't.

android:targetSdkVersion="13" 
a54studio
  • 965
  • 11
  • 11