Search code examples
androidcanvasandroid-mapviewmaskingclipping

Clipping/Masking a MapView on Android


I am trying to show a MapView as a circle on Android just like that:

protected void onDraw(Canvas canvas) {
    Path path = new Path();
    path.addCircle(400,200,100,Direction.CW);
    canvas.clipPath(path);
    super.onDraw(canvas);
}

Unfortunately the MapView (v2: com.google.android.gms.maps.MapView) component seems to ignore that and instead just taking the bounds/rect of that circle to draw the map :(

I've been searching the web for a while now, not finding a nice solution for that.

Is this even possible? (The Blundell solution is not working for me because I want the background to be visible around the map)

Thanks!


Solution

  • Android supports a hardware acceleration since API level 11. The problem is that not all drawing operations are supported when hardware acceleration is turned on. And Canvas.clipPath is one of them. Complete list of unsupported operations can be found here

    You can try to implement what you want without using clipPath or just disable hardware acceleration.

    To disable hardware acceleration on application level make sure you have targetSdkVersion 11 or higher and use hardwareAccelerated tag in the AndroidManifest:

    <application android:hardwareAccelerated="false" ...>
    

    You can disable hardware acceleration only for the particular view using the following method.

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void enableHardwareAcceleration(View view, boolean enabled) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            if (enabled) {
                view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            } else {
                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }
        }
    }
    

    Note that you have to use TargetApi annotation and check if device android version is Honeycomb or higher, otherwise Eclipse may produce an error.

    If code from your question isn't working try to replace it with this:

    @Override
    protected void dispatchDraw(Canvas canvas) {
        Path path = new Path();
        int count = canvas.save();
    
        path.addCircle(400,200,100,Direction.CW);
    
        canvas.clipPath(path);
        super.dispatchDraw(canvas);
        canvas.restoreToCount(count);
    }