重组一个Canvas,同时保持之前的绘图
Recompose a Canvas while maintaining the previous drawing
此函数在 canvas 上绘制图形,但是当我单击按钮时,它仅显示最新单击的图形,但我想显示之前单击的所有图形。
我认为 drawScope 状态可以被记住为可变状态,但如何实现它。
请帮忙...
@Composable
fun PaintBrushLayout(
modifier: Modifier = Modifier,
) {
var clicked by remember {
mutableStateOf(false)
}
var figName by remember {
mutableStateOf("")
}
Column(
verticalArrangement = Arrangement.Bottom, modifier = modifier.fillMaxSize()
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(.9f)
) {
Log.d("in Paint", "PaintBrushLayout: $this")
if (clicked) {
Log.d("TAG", "PaintBrushLayout: $figName")
when (figName) {
"Circle" -> {
drawCircleFig(color = Color.Blue)
}
"Rectangle" -> {
drawRectangleFig()
}
"Oval" -> {
drawOvalFig(color = Color.Gray)
}
}
}
}
Row(
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
) {
BottomLayout("Circle") { click, name ->
clicked = click
figName = name
}
BottomLayout("Rectangle") { click, name ->
clicked = click
figName = name
}
BottomLayout("Oval") { click, name ->
clicked = click
figName = name
}
BottomLayout("Choose Color") { click, name ->
clicked = click
// figName = name
}
}
}
}
创建按钮的底部布局
@Composable
fun BottomLayout(
btnName: String,
click: (Boolean, String) -> Unit
) {
Button(onClick = {
click(true, btnName)
}, modifier = Modifier.padding(4.dp)) {
Text(text = btnName)
}
}
在 canvas
上画圆圈图
fun DrawScope.drawCircleFig(color: Color = Color.Red) {
drawCircle(
color = color
)
}
在 canvas
上绘制矩形图形
fun DrawScope.drawRectangleFig(color: Color = Color.Red) {
drawRect(
color = color
)
}
在 canvas
上画椭圆形
fun DrawScope.drawOvalFig(color: Color = Color.Red) {
drawOval(
color = color
)
}
我不知道是否可以重组 Canvas 并保持其之前的状态,让您可以在已有的基础上进行绘制。一种解决方案是跟踪您要执行的操作的队列,然后每次 Canvas 重新组合时,您遍历队列并绘制每个项目。如果这是一个绘图应用程序,它的好处是允许用户撤消之前的步骤。我还注意到,当您单击按钮时,您提供的代码不会重新组合。我以前注意到过这个问题。解决方案是将记住的值分配给另一个值。这是使用队列的示例:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val queue = mutableListOf<DrawingObject>()
PaintBrushLayout(queue = queue)
}
}
}
@Composable
fun PaintBrushLayout(
modifier: Modifier = Modifier,
queue: MutableList<DrawingObject>
) {
var currentDrawingObject by remember { mutableStateOf(DrawingObject.None) }
var c = currentDrawingObject // This fixes a bug in recomposition.
fun addToQueue(drawingObject: DrawingObject) {
queue.add(drawingObject)
currentDrawingObject = drawingObject
}
Column(
verticalArrangement = Arrangement.Bottom, modifier = modifier.fillMaxSize()
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(.9f)
) {
queue.forEach { drawingObject ->
when (drawingObject) {
DrawingObject.Circle -> {
drawCircleFig(color = Color.Blue)
}
DrawingObject.Rectangle -> {
drawRectangleFig()
}
DrawingObject.Oval -> {
drawOvalFig(color = Color.Gray)
}
}
}
}
Row(
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
) {
BottomLayout("Circle") { click, name ->
addToQueue(DrawingObject.Circle)
}
BottomLayout("Rectangle") { click, name ->
addToQueue(DrawingObject.Rectangle)
}
BottomLayout("Oval") { click, name ->
addToQueue(DrawingObject.Oval)
}
BottomLayout("Choose Color") { click, name ->
}
}
}
}
@Composable
fun BottomLayout(
btnName: String,
click: (Boolean, String) -> Unit
) {
Button(onClick = {
click(true, btnName)
}, modifier = Modifier.padding(4.dp)) {
Text(text = btnName)
}
}
fun DrawScope.drawCircleFig(color: Color = Color.Red) {
drawCircle(
radius = 300f,
color = color
)
}
fun DrawScope.drawRectangleFig(color: Color = Color.Red) {
drawRect(
size = Size(200f, 200f),
color = color
)
}
fun DrawScope.drawOvalFig(color: Color = Color.Red) {
drawOval(
size = Size(100f, 100f),
color = color
)
}
enum class DrawingObject {
None,
Circle,
Rectangle,
Oval
}
此函数在 canvas 上绘制图形,但是当我单击按钮时,它仅显示最新单击的图形,但我想显示之前单击的所有图形。 我认为 drawScope 状态可以被记住为可变状态,但如何实现它。
请帮忙...
@Composable
fun PaintBrushLayout(
modifier: Modifier = Modifier,
) {
var clicked by remember {
mutableStateOf(false)
}
var figName by remember {
mutableStateOf("")
}
Column(
verticalArrangement = Arrangement.Bottom, modifier = modifier.fillMaxSize()
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(.9f)
) {
Log.d("in Paint", "PaintBrushLayout: $this")
if (clicked) {
Log.d("TAG", "PaintBrushLayout: $figName")
when (figName) {
"Circle" -> {
drawCircleFig(color = Color.Blue)
}
"Rectangle" -> {
drawRectangleFig()
}
"Oval" -> {
drawOvalFig(color = Color.Gray)
}
}
}
}
Row(
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
) {
BottomLayout("Circle") { click, name ->
clicked = click
figName = name
}
BottomLayout("Rectangle") { click, name ->
clicked = click
figName = name
}
BottomLayout("Oval") { click, name ->
clicked = click
figName = name
}
BottomLayout("Choose Color") { click, name ->
clicked = click
// figName = name
}
}
}
}
创建按钮的底部布局
@Composable
fun BottomLayout(
btnName: String,
click: (Boolean, String) -> Unit
) {
Button(onClick = {
click(true, btnName)
}, modifier = Modifier.padding(4.dp)) {
Text(text = btnName)
}
}
在 canvas
上画圆圈图 fun DrawScope.drawCircleFig(color: Color = Color.Red) {
drawCircle(
color = color
)
}
在 canvas
上绘制矩形图形 fun DrawScope.drawRectangleFig(color: Color = Color.Red) {
drawRect(
color = color
)
}
在 canvas
上画椭圆形 fun DrawScope.drawOvalFig(color: Color = Color.Red) {
drawOval(
color = color
)
}
我不知道是否可以重组 Canvas 并保持其之前的状态,让您可以在已有的基础上进行绘制。一种解决方案是跟踪您要执行的操作的队列,然后每次 Canvas 重新组合时,您遍历队列并绘制每个项目。如果这是一个绘图应用程序,它的好处是允许用户撤消之前的步骤。我还注意到,当您单击按钮时,您提供的代码不会重新组合。我以前注意到过这个问题。解决方案是将记住的值分配给另一个值。这是使用队列的示例:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val queue = mutableListOf<DrawingObject>()
PaintBrushLayout(queue = queue)
}
}
}
@Composable
fun PaintBrushLayout(
modifier: Modifier = Modifier,
queue: MutableList<DrawingObject>
) {
var currentDrawingObject by remember { mutableStateOf(DrawingObject.None) }
var c = currentDrawingObject // This fixes a bug in recomposition.
fun addToQueue(drawingObject: DrawingObject) {
queue.add(drawingObject)
currentDrawingObject = drawingObject
}
Column(
verticalArrangement = Arrangement.Bottom, modifier = modifier.fillMaxSize()
) {
Canvas(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(.9f)
) {
queue.forEach { drawingObject ->
when (drawingObject) {
DrawingObject.Circle -> {
drawCircleFig(color = Color.Blue)
}
DrawingObject.Rectangle -> {
drawRectangleFig()
}
DrawingObject.Oval -> {
drawOvalFig(color = Color.Gray)
}
}
}
}
Row(
modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween
) {
BottomLayout("Circle") { click, name ->
addToQueue(DrawingObject.Circle)
}
BottomLayout("Rectangle") { click, name ->
addToQueue(DrawingObject.Rectangle)
}
BottomLayout("Oval") { click, name ->
addToQueue(DrawingObject.Oval)
}
BottomLayout("Choose Color") { click, name ->
}
}
}
}
@Composable
fun BottomLayout(
btnName: String,
click: (Boolean, String) -> Unit
) {
Button(onClick = {
click(true, btnName)
}, modifier = Modifier.padding(4.dp)) {
Text(text = btnName)
}
}
fun DrawScope.drawCircleFig(color: Color = Color.Red) {
drawCircle(
radius = 300f,
color = color
)
}
fun DrawScope.drawRectangleFig(color: Color = Color.Red) {
drawRect(
size = Size(200f, 200f),
color = color
)
}
fun DrawScope.drawOvalFig(color: Color = Color.Red) {
drawOval(
size = Size(100f, 100f),
color = color
)
}
enum class DrawingObject {
None,
Circle,
Rectangle,
Oval
}