0

Following up with my problem I describe here i'm trying to draw some shapes to a canvas that isn't associated with any view/layout (it's totally in memory & never drawn to the screen) and then use the bitmap I drew in my activity.

The problem: It seems like my draw method never gets called. I have some log messages within it and I never see them print, and when I view the bitmap during runtime in Android Studio's debugger its always blank.

I've read various posts about having to call setWillNotDraw(false) to get the onDraw() method in a custom view to trigger, but because i'm never going to render this canvas to the screen my custom class extends Drawable() instead of View(context which doesn't include that method. This seems like a good choice since View includes lots of logic for user touches and other actions that my no-UI, background-generated drawable won't use.

That being said I still only saw blank bitmaps and no log messages from onDraw() when I extended View instead of Drawable and called setWillNowDraw(false) in the classes' constructor.

What's causing my canvas to always be blank?

class CustomImage : Drawable() {
    var bitmap: Bitmap

    private var barcodeText = Paint(ANTI_ALIAS_FLAG).apply {
        color = Color.BLACK
        textSize = 24f
    }
    private var circlePainter = Paint(ANTI_ALIAS_FLAG).apply {
        color = Color.WHITE
    }

    init {
        bitmap = Bitmap.createBitmap(LABEL_SIDE_LENGTH, LABEL_SIDE_LENGTH, Bitmap.Config.ARGB_8888)
    }

    override fun draw(canvas: Canvas) {
        Timber.d("canvas: In draw")
        canvas.setBitmap(bitmap)
        canvas.apply {
            drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
            drawText("002098613", LABEL_SIDE_LENGTH - 50f, 50f, barcodeText)
            drawCircle(200f, 200f, 100f, circlePainter)
        }
        Timber.d("canvas: $canvas")
    }

    override fun setAlpha(alpha: Int) {
    }

    override fun getOpacity(): Int {
        return PixelFormat.OPAQUE
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
    }

    companion object {
        const val LABEL_SIDE_LENGTH = 1160
    }
}


class MyActivity: AppCompatActivity(){
    private lateinit var customImgBitmap: Bitmap

    override fun onCreate(savedInstanceState: Bundle?) {
        customImgBitmap = createImgBitmap()
        val test = POLabelGenerator
    }
    ...
    private fun createImgBitmap(): Bitmap {
        return CustomImage.bitmap
    }
}
Cody
  • 1,801
  • 3
  • 28
  • 53
  • 1
    Unless that `Drawable` gets set on an onscreen `View`, its `draw()` method never will be called. You don't need to extend any class to create that image. All you need is your own `Bitmap`, `Canvas`, and `Paint`s. First, set up your `Paint`s, then `val bitmap = Bitmap.create(...)`, then `val canvas = Canvas(bitmap)`, then `drawColor()`, `drawText()`, and `drawCircle()`, all right in a row. Your image will then be in `bitmap`. You could stick that all into a single little helper method. – Mike M. Nov 23 '19 at 12:06
  • @MikeM. Ah I didn't realize I could use an instance of canvas outside the scope of draw(). This solution worked, please submit it as an answer and i'll accept it. Thanks! – Cody Nov 25 '19 at 15:34

0 Answers0