javaandroidcanvasandroid-canvasjava-canvas

How to increase Opacity/Strength of Shadow in canvas android?


I am trying to get a shadow effect on a text in canvas. The problem I am facing is the shadow that is being created is very dim and showing weird shapes. I am trying to overcome these problems. I am open to suggestions where I can create Images and save to disk without using canvas.

Code:

class MainActivity : AppCompatActivity() {

    private lateinit var canvasIV: ImageView
    private lateinit var imgBitmap: Bitmap
    private lateinit var canvas: Canvas

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        canvasIV = findViewById(R.id.canvasIV)

        val displayMetrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(displayMetrics)
        val height = displayMetrics.heightPixels
        val width = displayMetrics.widthPixels


        imgBitmap =
            Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
        canvas = Canvas(imgBitmap)

        canvas.drawBitmap(imgBitmap, 0f, 0f, null)

        val shadowPaint = Paint()
        shadowPaint.isAntiAlias = true
        shadowPaint.color = Color.parseColor("#F897B9")

        val tSize = 80.0f

        shadowPaint.textSize = tSize
        shadowPaint.strokeWidth = 20.0f
        shadowPaint.style = Paint.Style.FILL
        shadowPaint.alpha = 0x100
        //shadowPaint.setShadowLayer(20.0f, 5f, 5f, Color.parseColor("#F897B9"))
        shadowPaint.setShadowLayer(tSize, 5f, 5f, Color.GREEN)


        canvas.drawText("Sayok Dey Majumder", 50f, 200f, shadowPaint)
        //canvasIV.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
        canvasIV.setImageDrawable(BitmapDrawable(resources, imgBitmap))


    }
    fun convertToPixels(context: Context, nDP: Int): Float {
        val conversionScale: Float = context.getResources().getDisplayMetrics().density
        return (nDP * conversionScale + 0.5f)
    }


    fun getTextWidth(text: String, paint: Paint): Int {
        val bounds = Rect()
        paint.getTextBounds(text, 0, text.length, bounds)
        return bounds.left + bounds.width()
    }

    fun getTextHeight(text: String, paint: Paint): Int {
        val bounds = Rect()
        paint.getTextBounds(text, 0, text.length, bounds)
        return bounds.bottom + bounds.height()
    }


}

What I am getting is:

enter image description here

What I am trying to achieve:

enter image description here


Solution

  • The Bitmap with config Bitmap.Config.ARGB_8888 don't support Alpha channel.

    Use this instead:

    imgBitmap =Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    

    also the following line don't do anything:

    canvas.drawBitmap(imgBitmap, 0f, 0f, null)
    


    Better Solution:

    Also, shadow layer has limited capacity and I recommend to draw the shadow manually.

    val shadowPaint = Paint(defaultPaint)
    // ... here customize shadow paint
    canvas.drawText("your text", x, y, defaultPaint);
    canvas.drawText("your text", x, y, shadowPaint);
    

    Also, you could extend TextView and override the onDraw function. Here I create customView that add shadow. you could adjust it.

    import android.content.Context;
    import android.graphics.BlurMaskFilter;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.text.TextPaint;
    import android.util.AttributeSet;
    
    
    public class ShadowTextView extends androidx.appcompat.widget.AppCompatTextView {
        private TextPaint normalPaint;
        private int color;
        TextPaint shadowPaint;
        public ShadowTextView(Context context) {
            super(context);
            init();
        }
    
        public ShadowTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public ShadowTextView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            normalPaint=new TextPaint(getPaint());
            shadowPaint=new TextPaint(getPaint());
            shadowPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            shadowPaint.setStrokeCap(Paint.Cap.ROUND);
            shadowPaint.setStrokeJoin(Paint.Join.ROUND);
            shadowPaint.setStrokeWidth(30);
            shadowPaint.setMaskFilter(new BlurMaskFilter( 10, BlurMaskFilter.Blur.NORMAL));
        }
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            this.savePaint();
            getPaint().set(shadowPaint);
            setTextColor(Color.argb(100,255,0,0));
            super.onDraw(canvas);
            this.restorePaint();
        }
    
    
        public void savePaint() {
            normalPaint.set(getPaint());
            color=getCurrentTextColor();
        }
    
        public void restorePaint() {
            getPaint().set(normalPaint);
            setTextColor(color);
        }
    }
    

    enter image description here