I have the following code that puts some text at the top of an image:
val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.WHITE
paint.textSize = 40f //* context.resources.displayMetrics.density
paint.typeface = Typeface.DEFAULT_BOLD
//paint.textAlign = Paint.Align.
paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY)
val teststr = "Hello World Hello World Hello World Hello World"
val canvas = Canvas(bitmap)
val textLayout = StaticLayout(teststr, paint, canvas.width ,Layout.Alignment.ALIGN_CENTER, 1f, 0f, false)
textLayout.draw(canvas)
However, in reality, I want the text to be at the bottom of the image. How can I align the StaticLayout with the bottom of the Bitmap, so the text appears at the bottom of the image.
This turned out to be the correct answer. Subtract the height of the StaticLayout from the height of the canvas.
val paint = TextPaint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.WHITE
paint.textSize = 40f //* context.resources.displayMetrics.density
paint.typeface = Typeface.DEFAULT_BOLD
//paint.textAlign = Paint.Align.
paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY)
val teststr = "Hello World"
val canvas = Canvas(bitmap)
val textLayout = StaticLayout(teststr, paint, canvas.width ,Layout.Alignment.ALIGN_CENTER, 1f, 0f, false)
canvas.save()
canvas.translate(0f,canvas.height - textLayout.height - 0.0f)
textLayout.draw(canvas)
canvas.restore()
Related
I'm developing a function to draw a rounded button in my android application. The problem is that the final results is rectangular instead of something rounded on the corners. What am I missing?
fun draw(canvas: Canvas?) {
canvas?.let {
if (strokeColor != -1) {
shaderBorderPaint.color = strokeColor
shaderBorderPaint.shader = null
} else {
shaderBorderPaint.shader = shaderFactory.resize(it.width, it.height)
}
val cornerRadius = 8f
val halfStrokeSize: Float = shaderBorderPaint.strokeWidth / 2
val rect = RectF(halfStrokeSize, it.height - halfStrokeSize, it.width - halfStrokeSize, halfStrokeSize)
it.drawRoundRect(rect, cornerRadius, cornerRadius, shaderBorderPaint)
}
}
Try this instead.
val corners = floatArrayOf(
80f, 80f, // Top left radius in px
80f, 80f, // Top right radius in px
0f, 0f, // Bottom right radius in px
0f, 0f // Bottom left radius in px
)
val path = Path()
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas.drawPath(path, mPaint)
or this,
public static void makeRoundCorner(int bgcolor,int radius,View v,int strokeWidth,int strokeColor)
{
GradientDrawable gdDefault = new GradientDrawable();
gdDefault.setColor(bgcolor);
gdDefault.setCornerRadius(radius);
gdDefault.setStroke(strokeWidth, strokeColor);
v.setBackgroundDrawable(gdDefault);
}
because val cornerRadius = 8f. try to set cornerRadius = heightRect / 2
In Android app , I want to draw a button in canvas , like the image exactly the below image
I tried some stack overflow answers but can't get the exact output , particularly the light shadow below . My worst code is below
val corners = floatArrayOf(
80f, 80f, // Top left radius in px
80f, 80f, // Top right radius in px
0f, 0f, // Bottom right radius in px
0f, 0f // Bottom left radius in px
)
val path = Path()
val rect = RectF(550f, 500f, 100f, 300f)
paint.style = Paint.Style.FILL;
paint.color = Color.WHITE;
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas?.drawPath(path, paint)
paint.style = Paint.Style.STROKE;
paint.color = Color.BLACK;
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas?.drawPath(path, paint)
paint.setColor(Color.RED)
paint.setStyle(Paint.Style.FILL)
val paint2 = Paint()
paint2.setColor(Color.GREEN)
paint2.setTextSize(50f) //set text size
val w: Float = paint2.measureText("VIEW CAMPSITE MAP") / 2
val textSize: Float = paint2.textSize
canvas?.drawText("VIEW CAMPSITE MAP", 300f, 300f ,paint2);
Also I can't set text in correct position
I also need a gradient to show bulging state like a real material button
And also need an click listener in the canvas / paint
I need it in pure canvas and paint not in any views
please help me
Here is one of the ways. Dont forget to move all variables like text, textSize, etc in custom attributes. Also I didnt get what do you mean by "click listener in the canvas"
class CustomView #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
//constants. move them all to custom attributes
private val boxRadius = convertDpToPixel(10f)
private val boxColor = Color.parseColor("#52618e")
private val boxBackgroundColor = Color.WHITE
private val boxShadowSize = convertDpToPixel(2f)
private val boxStrokeWidth = convertDpToPixel(1f)
private val textColor = Color.parseColor("#21a207")
private val fontSize = convertDpToPixel(30f)
private val text = "View Campsite Plan"
private lateinit var boxShadow: RectF
private lateinit var boxBackground: RectF
private lateinit var boxShadowPaint: Paint
private lateinit var boxBackgroundPaint: Paint
private var textWidth = 0f
private var textSmallGlyphHeight = 0f
private lateinit var textPaint: Paint
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
boxShadow = RectF(0f, 0f, w.toFloat(), h.toFloat())
boxBackground = RectF(boxStrokeWidth, boxStrokeWidth,
w.toFloat()-boxStrokeWidth, h.toFloat()-boxStrokeWidth-boxShadowSize)
boxShadowPaint = Paint().apply { color = boxColor }
boxBackgroundPaint = Paint().apply { color = boxBackgroundColor }
textPaint = Paint().apply {
color = textColor
textSize = fontSize
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
textWidth = measureText(text)
textSmallGlyphHeight = fontMetrics.run { ascent + descent }
}
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawRoundRect(boxShadow, boxRadius, boxRadius, boxShadowPaint)
canvas?.drawRoundRect(boxBackground, boxRadius, boxRadius, boxBackgroundPaint)
val textStartPadding = (width - textWidth)/2f
val textTopPadding = (height - textSmallGlyphHeight)/2f
canvas?.drawText(text, textStartPadding, textTopPadding, textPaint)
}
private fun convertDpToPixel(dp: Float) =
dp*(resources.displayMetrics.densityDpi/DisplayMetrics.DENSITY_DEFAULT)
}
I faced the following problem: I need to show the contour of the human face over bitmap. I have coordinates of the face contour points. Here's my code:
private fun detectContours(
it: FirebaseVisionFace,
icon: Bitmap
) {
val faceContour = it.getContour(FirebaseVisionFaceContour.FACE)
val mutableBitmap = icon.copy(
Bitmap.Config.ARGB_8888, true
)
val canvas = Canvas(mutableBitmap)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.parseColor("#99ff0000")
val path = Path()
path.moveTo(faceContour.points[0].x, faceContour.points[0].y)
faceContour.points.forEach {
path.lineTo(it.x, it.y)
}
path.close()
canvas.drawPath(path, paint)
binding.ivPhoto.setImageBitmap(mutableBitmap)
}
Here I use path.moveTo(...) and I expect that mutableBitmap will look like a face with the contour. But when I run the app I see the following result:
So, why the path is filled with the colour. Thanks in advance, I will appreciate any help
Fixed by changing path.drawline to canvas.drawLine
val faceContour = it.getContour(FirebaseVisionFaceContour.FACE)
var startX = faceContour.points[0].x
var startY = faceContour.points[0].y
val initialX = faceContour.points[0].x
val initialY = faceContour.points[0].y
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.parseColor("#ff0000")
faceContour.points.forEach {
canvas.drawLine(startX, startY, it.x, it.y, paint)
startX = it.x
startY = it.y
}
canvas.drawLine(startX, startY, initialX, initialY, paint)
I want to draw transparent bitmaps on a background in a game. However, the bitmap is not transparent, it still has white color in the background. Here is my code
inner class Canvass(context: Context) : View(context) {
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val frame_paint: Paint = Paint()
frame_paint.style = Paint.Style.FILL
frame_paint.isAntiAlias = true
val framegame = BitmapFactory.decodeResource (resources, R.drawable.frame)
canvas.drawBitmap (framegame, 0f, 0f, frame_paint)
canvas.drawPath(mPath, mPaint)
val tennis_paint: Paint = Paint()
tennis_paint.style = Paint.Style.FILL
tennis_paint.color = Color.TRANSPARENT
tennis_paint.isAntiAlias = true
val tennis = BitmapFactory.decodeResource (resources, R.drawable.tennis_ball)
canvas.drawBitmap (tennis, 50f, 200f, tennis_paint)
}
}
I found this code, it works for me.
val tennis_paint: Paint = Paint()
tennis_paint.style = Paint.Style.FILL
tennis_paint.isAntiAlias = true
val tennis = BitmapFactory.decodeResource (resources, R.drawable.tennis_ball)
var bitmap = transparent_bitmap(tennis)
canvas.drawBitmap (bitmap, 50f, 300f, tennis_paint)
fun transparent_bitmap(bmp:Bitmap):Bitmap{
var bitmap: Bitmap = Bitmap.createBitmap(
bmp.width,
bmp.height,
Bitmap.Config.ARGB_8888
)
bitmap.setHasAlpha(true)
for (x in 1..bmp.width-1){
for (y in 1..bmp.height-1){
var pixel = bmp.getPixel(x,y)
val redValue = Color.red(pixel)
val blueValue = Color.blue(pixel)
val greenValue = Color.green(pixel)
if ((redValue==255)and(blueValue==255)and(greenValue==255)){
bitmap.setPixel(x,y,Color.argb(1,0,0,0))
}else {
bitmap.setPixel(x,y,Color.rgb(redValue,greenValue,blueValue))
}
}
}
return bitmap
}
How to use canvas to draw a selected field of transparent color with blue background?
In official documentation i find smth like this .
But there is still a question of how to implement it.
Also for example, i tried to draw line:
private fun someFun(canvas: Canvas, parent: RecyclerView) {
val radius: Float = parent.context.resources.getDimension(R.dimen.dimen_12)
val paint = Paint()
paint.color = ContextCompat.getColor(parent.context, R.color.primary)
paint.style = Paint.Style.FILL
val path = Path()
path.moveTo(0f, 0f)
path.lineTo(0f, radius)
path.arcTo(RectF(0f, 0f, radius * 2, radius * 2), 270f, -90f)
path.close()
canvas.drawPath(path, paint)
}
And get smth like this:
Decided to the next way:
private fun drawRoundedCorners(canvas: Canvas, parent: RecyclerView) {
val radius: Float = parent.context.resources.getDimension(R.dimen.dimen_12)
val paint = Paint()
paint.color = ContextCompat.getColor(parent.context, R.color.primary)
paint.style = Paint.Style.FILL
val path = Path()
path.moveTo(0f, 0f)
path.lineTo(150f, 0f)
path.arcTo(RectF(0f, 0f, radius * 2, radius * 2), 270f, -90f)
path.moveTo(parent.width.toFloat(), 0f)
path.lineTo(parent.width.toFloat(), 0f)
path.arcTo(RectF(parent.width.toFloat() - radius * 2, 0f, parent.width.toFloat(),
radius * 2), 270f, 90f)
path.close()
canvas.drawPath(path, paint)
}