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:
What I am trying to achieve:
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)
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);
}
}