在 compose 中创建 Drawable 实例时出现问题

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

我需要迁移我的旧java代码,该代码创建一个Drawable实例,它是一个渐变,其起始颜色在上部,结束颜色在底部。

它在 java 中运行得很好,但是将代码迁移到 kotlin 并进行 compose 后,getDrawable 函数返回一个空的透明可绘制对象:

override fun getDrawable(): Drawable {
    val sf: ShaderFactory = object : ShaderFactory() {
        override fun resize(width: Int, height: Int): Shader {
            return LinearGradient(
                startX(width), startY(height), endX(width), endY(height), intArrayOf(
                    color1, color2
                ),
                null, Shader.TileMode.MIRROR
            )
        }
    }
    val p = PaintDrawable()
    p.shape = RectShape()
    p.shaderFactory = sf
    return p
}
   
fun startX(actualWidth: Int): Float {
    when (type) {
        Type.SOLID -> return 0f
        Type.DEGREE_DOWN_UP, Type.DEGREE_UP_DOWN -> return actualWidth / 2.0f
        Type.DEGREE_LEFT_RIGHT -> return 0.0f
        Type.DEGREE_RIGHT_LEFT -> return actualWidth.toFloat()
        else -> {}
    }
    return (-1).toFloat()
}

fun startY(actualHeight: Int): Float {
    when (type) {
        Type.SOLID -> return 0f
        Type.DEGREE_DOWN_UP -> return actualHeight.toFloat()
        Type.DEGREE_LEFT_RIGHT, Type.DEGREE_RIGHT_LEFT -> return actualHeight / 2.0f
        Type.DEGREE_UP_DOWN -> return 0f
        else -> {}
    }
    return (-1).toFloat()
}

fun endX(actualWidth: Int): Float {
    when (type) {
        Type.SOLID -> return actualWidth.toFloat()
        Type.DEGREE_DOWN_UP, Type.DEGREE_UP_DOWN -> return actualWidth / 2.0f
        Type.DEGREE_LEFT_RIGHT -> return actualWidth.toFloat()
        Type.DEGREE_RIGHT_LEFT -> return 0f
        else -> {}
    }
    return (-1).toFloat()
}

fun endY(actualHeight: Int): Float {
    when (type) {
        Type.SOLID -> return actualHeight.toFloat()
        Type.DEGREE_DOWN_UP -> return 0f
        Type.DEGREE_UP_DOWN -> return actualHeight.toFloat()
        Type.DEGREE_LEFT_RIGHT, Type.DEGREE_RIGHT_LEFT -> return actualHeight / 2.0f
        else -> {}
    }
    return (-1).toFloat()
}

drawable 的类型是

DEGREE_UP_DOWN

这就是我使用可绘制对象的方式:

val bg = GradientShading(Shading.Type.DEGREE_UP_DOWN, topColor, bottomColor)

LazyColumn(
        modifier = modifier.fillMaxWidth()
            .clipToBounds()
            .drawBehind {
                drawIntoCanvas { bg.getDrawable().draw(it.nativeCanvas) }
            },
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Top
    )

代码有什么问题?

这是代码的工作 java 版本,显然是完全相同的:

@Override
    public Drawable getDrawable() {
        ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
            @Override
            public Shader resize(int width, int height) {
                LinearGradient lg = new LinearGradient(startX(width), startY(height), endX(width), endY(height), new int[] {
                        color1 , color2 },
                        null, Shader.TileMode.MIRROR);
                 return lg;
            }
        };      
        PaintDrawable p = new PaintDrawable();
        p.setShape(new RectShape());
        p.setShaderFactory(sf);
        return (Drawable)p;
    }

float startX(int actualWidth) {         
        switch (this.type) {
        case SOLID:
            return 0;
        case DEGREE_DOWN_UP:
        case DEGREE_UP_DOWN:
            return actualWidth/2.0f;
        case DEGREE_LEFT_RIGHT:
            return 0.0f;
        case DEGREE_RIGHT_LEFT:
            return actualWidth;
        }
        
        return -1;
    }
    
    float startY(int actualHeight){     
        switch (this.type) {
        case SOLID:
            return 0;
        case DEGREE_DOWN_UP:
            return actualHeight;
        case DEGREE_LEFT_RIGHT:
        case DEGREE_RIGHT_LEFT:
            return actualHeight/2.0f;
        case DEGREE_UP_DOWN:
            return 0;
        }
        
        return -1;      
    }
    
    float endX(int actualWidth){        
        switch (this.type) {
        case SOLID:
            return actualWidth;
        case DEGREE_DOWN_UP:
        case DEGREE_UP_DOWN:
            return actualWidth/2.0f;
        case DEGREE_LEFT_RIGHT:
            return actualWidth;
        case DEGREE_RIGHT_LEFT:
            return 0;
        }       
        return -1;          
    }
    
    float endY(int actualHeight){       
        switch (this.type) {
        case SOLID:
            return actualHeight;
        case DEGREE_DOWN_UP:
            return 0;
        case DEGREE_UP_DOWN:
            return actualHeight;
        case DEGREE_LEFT_RIGHT:
        case DEGREE_RIGHT_LEFT:
            return actualHeight/2.0f;
        }       
        return -1;      
    }
android kotlin android-jetpack-compose android-drawable
1个回答
0
投票

在调用

nativeCanvas.clipBounds
之前将
drawable.bounds
分配给
drawable.draw
,如下所示:

val drawable = remember { GradientShading(Color.BLUE, Color.MAGENTA).getDrawable() }

LazyColumn(modifier = Modifier
    .fillMaxWidth()
    .clipToBounds()
    .drawBehind {
        drawIntoCanvas { canvas ->
            drawable.bounds = canvas.nativeCanvas.clipBounds
            drawable.draw(canvas.nativeCanvas)
        }
    }
) {
    items(10) { Text("Item $it") }
}

我的

GradientShading
类重构为
DEGREE_UP_DOWN
getDrawable
方法相同):

private class GradientShading(val color1: Int, val color2: Int) {
    fun getDrawable(): Drawable {
        val sf: ShaderFactory = object : ShaderFactory() {
            override fun resize(width: Int, height: Int): Shader {
                return LinearGradient(
                    startX(width), startY(height), endX(width), endY(height), intArrayOf(
                        color1, color2
                    ),
                    null, Shader.TileMode.MIRROR
                )
            }
        }
        val p = PaintDrawable()
        p.shape = RectShape()
        p.shaderFactory = sf
        return p
    }

    fun startX(actualWidth: Int): Float {
        return actualWidth / 2.0f
    }

    fun startY(actualHeight: Int): Float {
        return 0f
    }

    fun endX(actualWidth: Int): Float {
        return actualWidth / 2.0f
    }

    fun endY(actualHeight: Int): Float {
        return actualHeight.toFloat()
    }
}

结果:

screenshot

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