Android - 在 Android Pie (API 28) RadialGradient 中绘制矩形而不是圆形

问题描述 投票:0回答:3

我正在尝试用背景图像和前景图像模拟

TorchView
。它在 API 27 及以下版本上运行良好,但在 API 28 上绘制矩形。

知道为什么它在 Android Pie 上不起作用吗?

API 27 及以下版本 API 28
API 27 and below API 28

火炬视图类:

TorchView 类:视图,OnTouchListener {

    var mBitmapBackground:位图? = 空
    var mBitmapForeground:位图? = 空
    var mMask:位图? = 空
    私有变量 mPosX = 0f
    私有变量 mPosY = 0f

    private Lateinit var PaintMask:油漆
    private Lateinit var PaintBackground:油漆
    private Lateinit var PaintForeground:油漆

    私有变量半径 = 150

    构造函数(上下文:上下文):超级(上下文){
        初始化()
    }

    构造函数(上下文:上下文,属性:AttributeSet):超级(上下文,属性){
        初始化()
    }

    fun initBitmaps(bitmapBackground:位图,bitmapForeground:位图,半径:Int){
        this.radius = 半径
        mBitmapBackground = 位图背景
        mBitmapForeground = 位图前景
        mMask = makeRadGrad()
        mPosX = (bitmapBackground.width/2 - 半径).toFloat()
        mPosY = (bitmapBackground.height/2 - 半径).toFloat()
        无效()
    }

    有趣的初始化(){
        油漆背景 = 油漆()

        油漆掩码 = 油漆()
        PaintMask.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

        油漆前景 = 油漆()
        PaintForeground.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)

        可聚焦 = true
        isFocusableInTouchMode = true
        this.setOnTouchListener(this)
    }

    公共覆盖 fun onDraw(canvas: Canvas) {
        super.onDraw(画布)

        val 掩码 = mMask
        val 位图前景 = mBitmapBackground
        val 位图背景 = mBitmapForeground
        if(掩码!= null && bitmapForeground != null && bitmapBackground != null){
            画布.保存()
            canvas.drawBitmap(位图背景,0f,0f,paintBackground)
            canvas.drawBitmap(掩码,mPosX,mPosY,paintMask)
            canvas.drawBitmap(bitmapForeground,0f,0f,paintForeground)
            画布.恢复()
        }
    }

    私人乐趣 makeRadGrad(): 位图 {
        val 梯度 = RadialGradient(
            半径.toFloat(), 半径.toFloat(), 半径.toFloat(), -0xff0100,
            0x00000000,android.graphics.Shader.TileMode.CLAMP
        )
        val p = Paint()
        p.isDither = true
        p.shader = 渐变

        val 位图 = Bitmap.createBitmap(半径*2, 半径*2, Config.ARGB_8888)
        val c = 画布(位图)
        c.drawCircle(radius.toFloat(), radius.toFloat(), radius.toFloat(), p)

        返回位图
    }

    覆盖 fun onTouch(v: View?, event: MotionEvent): Boolean {
        mPosX = event.x - 半径
        mPosY = event.y - 半径
        无效()
        返回真
    }
}
android android-canvas paint android-9.0-pie porter-duff
3个回答
1
投票

检查这个https://issuetracker.google.com/issues/111819103

试试这个

 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)
 }

1
投票

根据官方文档

PorterDuff 在 Android API 28 中已弃用

您应该将 PorterDuff 替换为 BlendMode

enter image description here

也许你应该在 Android API 28 上做一些兼容的工作


0
投票

班级:

TorchView 类:视图、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
}

}

© www.soinside.com 2019 - 2024. All rights reserved.