Estoy tratando de simular un TorchView con una imagen de fondo y una imagen de primer plano. Funciona bien en API 27 e inferiores, pero dibuja un rectángulo en API 28.

¿Alguna idea de por qué no funciona en Android Pie?

Captura de pantalla en API 27 e inferior API 27 y por debajo

Captura de pantalla en API 28 API 28

Antorcha Ver clase

class TorchView : View, OnTouchListener {

    var mBitmapBackground: Bitmap? = null
    var mBitmapForeground: Bitmap? = null
    var mMask: Bitmap? = null
    private var mPosX = 0f
    private var mPosY = 0f

    private lateinit var paintMask: Paint
    private lateinit var paintBackground: Paint
    private lateinit var paintForeground: Paint

    private var radius = 150


    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }


    fun initBitmaps(bitmapBackground: Bitmap, bitmapForeground: Bitmap, radius: Int){
        this.radius = radius
        mBitmapBackground = bitmapBackground
        mBitmapForeground = bitmapForeground
        mMask = makeRadGrad()
        mPosX = (bitmapBackground.width/2 - radius).toFloat()
        mPosY = (bitmapBackground.height/2 - radius).toFloat()
        invalidate()
    }

    fun init() {
        paintBackground = Paint()

        paintMask = Paint()
        paintMask.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

        paintForeground = Paint()
        paintForeground.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)

        isFocusable = true
        isFocusableInTouchMode = true
        this.setOnTouchListener(this)
    }

    public override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val mask = mMask
        val bitmapForeground = mBitmapBackground
        val bitmapBackground = mBitmapForeground
        if(mask != null && bitmapForeground != null && bitmapBackground != null){
            canvas.save()
            canvas.drawBitmap(bitmapBackground, 0f, 0f, paintBackground)
            canvas.drawBitmap(mask, mPosX, mPosY, paintMask)
            canvas.drawBitmap(bitmapForeground, 0f, 0f, paintForeground)
            canvas.restore()
        }
    }

    private fun makeRadGrad(): Bitmap {
        val gradient = RadialGradient(
            radius.toFloat(), radius.toFloat(), radius.toFloat(), -0xff0100,
            0x00000000, android.graphics.Shader.TileMode.CLAMP
        )
        val p = Paint()
        p.isDither = true
        p.shader = gradient

        val bitmap = Bitmap.createBitmap(radius*2, radius*2, Config.ARGB_8888)
        val c = Canvas(bitmap)
        c.drawCircle(radius.toFloat(), radius.toFloat(), radius.toFloat(), p)

        return bitmap
    }

    override fun onTouch(v: View?, event: MotionEvent): Boolean {
        mPosX = event.x - radius
        mPosY = event.y - radius
        invalidate()
        return true
    }
}
respuesta

mira esto https://issuetracker.google.com/issues/111819103

prueba esto

 public override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val mask = mMask
    val bitmapForeground = mBitmapBackground
    val bitmapBackground = mBitmapForeground
    if(mask != null && bitmapForeground != null && bitmapBackground != null){
        canvas.save()
        canvas.drawBitmap(bitmapBackground, 0f, 0f, paintBackground)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            makeRadGradP(canvas, bitmapForeground)
        } else {
            canvas.drawBitmap(mask, mPosX, mPosY, paintMask)
            canvas.drawBitmap(bitmapForeground, 0f, 0f, paintForeground)
         }
        canvas.restore()
    }
}

private fun makeRadGradP(canvas: Canvas, bm: Bitmap) {
        val paint = Paint()
        paint.style = Paint.Style.FILL
        val shader = BitmapShader(bm, TileMode.CLAMP, TileMode.CLAMP)
        paint.shader = shader
        val corners = Path()
        corners.addCircle(mPosX + radius, mPosY + radius, radius.toFloat(), Path.Direction.CW)
        canvas.drawPath(corners, paint)

        val gradient = RadialGradient(
                mPosX + radius, mPosY + radius, radius.toFloat(), 0x00000000,
                Color.parseColor("#df000000"), TileMode.CLAMP
        )
        val p = Paint()
        p.isDither = true
        p.shader = gradient
        canvas.drawCircle(mPosX + radius, mPosY + radius, radius.toFloat(), p)
 }

Según el Documento Oficial

PorterDuff quedó obsoleto en Android API 28

Deberías reemplazar PorterDuff con BlendMode

ingrese la descripción de la imagen aquí

Tal vez deberías hacer algún trabajo compatible en Android API 28