Custom View with LAYER_TYPE_SOFTWARE clips view
Asked Answered
C

1

6

I've created a custom view which extends TextView. I want to use a BlurMaskFilter on an oval, however, unless I use LAYER_TYPE_SOFTWARE, the oval isn't blurred as expected. Using LAYER_TYPE_SOFTWARE will blur the view correctly, however now it is clipped to its bounds which I want to avoid as I am trying to create a colored shadow effect.

Bizarrely I only have this issue on API's 21-27 (min API is 21). On API's 28+ BlurMaskFilter works correctly with hardware acceleration and also has no issues drawing outside the view bounds.

LAYER_TYPE_HARDWARE

LAYER_TYPE_SOFTWARE

LAYER_TYPE_HARDWARE API 28+ (Desired effect)

I've tried setting clipChildren=false on all the views in the hierarchy, with no luck.

I also tried increasing the canvas.clipRect using negative values as per this post: https://mcmap.net/q/399054/-can-i-draw-outside-the-bounds-of-an-android-canvas however this only seemed to work when using positive values to decrease the drawing area, and had no effect when using negative values to draw outside the view bounds.

I can somewhat get around the issue by increasing the view bounds in onMeasure() and then only painting inside those view bounds, however, this isn't ideal as I now have to account for this extra space when positioning my views in the layouts. Furthermore, the problem becomes inconsistent to account for as different views might have different elevations and shadow/blur sizes.

init block for the custom view:

 init {
        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
        setWillNotDraw(false)
...

onDraw for the custom view:


override fun onDraw(canvas: Canvas?) {

...

    if (elevation > 0f) {
        circleShadowBackgroundPaint.maskFilter = circleBlurMaskFilter
        canvas?.drawOval(circleBlurBackground, circleShadowBackgroundPaint)
    }

...

Any help would be appreciated!

Chapatti answered 4/8, 2019 at 17:51 Comment(1)
did you solve your issue?Torque
W
2

If you set this View's LayerType to LAYER_TYPE_SOFTWARE,the clipCHildren and clipToPadding will no longer has anly effect on this View.You should setLayerType on its Parent(or parent's parent ,if the parent is as large as the size of this View).

You can try (View (getParent())).setLayerType(View.LAYER_TYPE_SOFTWARE, null)

Whittier answered 2/6, 2021 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.