Is there a way to add glow effect to a view, for example button or image view?

Viewed 441

For example, this button:

enter image description here

I want to make him glow like this:

enter image description here

How can I do this without using an external library button?
Also, I would really like to know how to do this on an ImageView as well. All I could find is using external buttons and image views from libraries which is not suitable in my case.

Big thanks in advance!

Button XML code:

<com.google.android.material.button.MaterialButton
    android:id="@+id/btAddMyCard"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/add_another_my_card"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="24dp"
    android:layout_below="@id/topAppBar"
    style="@style/Widget.App.Button.OutlinedButton" />
1 Answers

Although the new Material widgets are quite functional, they are locked down so it is not easy to customize them in non-prescribed ways. I can show you one way to accomplish what you need.

I use the foreground to draw a rounded rectangle that is a composite of two rounded rectangles: A non-blurred rectangle and a blurred one using a BlurMaskFilter. I let the button draw a transparent rounded rectangle of a specified with so it shows nothing, but I use the stroke width to draw the rounded rectangle although this value really should be specified in a custom attribute for the custom view.

You may need to do some tweaking for your situation.

enter image description here

If you can't really see the glow, here is a magnification:

enter image description here

This image was produced from a custom view based upon MaterialButton.

class MyMaterialGlowButton @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : MaterialButton(context, attrs) {
    private val mPaddedRect = RectF()
    private val mBlurRadius = strokeWidth.toFloat() * BLUR_RADIUS_FACTOR

    private val mLinePaint = Paint().apply {
        isAntiAlias = true
        strokeWidth = this@MyMaterialGlowButton.strokeWidth.toFloat()
        style = Paint.Style.STROKE
        color = ROUNDED_RECT_COLOR
    }

    private val mBlurPaint = Paint().apply {
        isAntiAlias = true
        strokeWidth = this@MyMaterialGlowButton.strokeWidth.toFloat()
        style = Paint.Style.STROKE
        color = ROUNDED_RECT_COLOR
        maskFilter = BlurMaskFilter(mBlurRadius, BlurMaskFilter.Blur.NORMAL)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        val halfStrokeWidth = strokeWidth.toFloat() / 2f
        mPaddedRect.left = halfStrokeWidth + mBlurRadius
        mPaddedRect.top = halfStrokeWidth + mBlurRadius
        mPaddedRect.right = w.toFloat() - halfStrokeWidth - mBlurRadius
        mPaddedRect.bottom = h.toFloat() - halfStrokeWidth - mBlurRadius
    }

    override fun onDrawForeground(canvas: Canvas?) {
        super.onDrawForeground(canvas)
        val corners = cornerRadius.toFloat()
        canvas?.drawRoundRect(mPaddedRect, corners, corners, mBlurPaint)
        canvas?.drawRoundRect(mPaddedRect, corners, corners, mLinePaint)
    }

    private companion object {
        const val ROUNDED_RECT_COLOR = 0xFF2b86e6.toInt()
        const val BLUR_RADIUS_FACTOR = 1.0f
    }
}

The XML used:

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.blurredline.MyMaterialGlowButton
        android:id="@+id/btAddMyCard"
        style="@style/Widget.App.Button.OutlinedButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:textAllCaps="false"
        android:insetLeft="4dp"
        android:insetRight="4dp"
        android:text="@string/add_another_my_card"
        app:cornerRadius="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

The insets prevent the ripple from extending outside the bounded area. You may need to adjust these values.

And the style. I wasn't sure what your values were, so I used these:

<style name="Widget.App.Button.OutlinedButton" parent="Widget.MaterialComponents.Button.OutlinedButton">
    <item name="strokeColor">@android:color/transparent</item>
    <item name="strokeWidth">4dp</item>
    <item name="android:textColor">#FF2b86e6</item>
    <item name="cornerRadius">16dp</item>
    <item name="textAllCaps">false</item>
    <item name="fontFamily">sans-serif-light</item>
</style>

I may prefer a RadialGradient for the glow, but that would be much more difficult to implement.

Related