簡體   English   中英

Jetpack compose 中的可點擊區域未更新

[英]Clickable area not updated in Jetpack compose

我目前正在試驗新的 Jetpack Compose UI 工具包,現在我真的很喜歡它。 使用以下代碼,我可以在屏幕上繪制任何形狀,使其可點擊並四處移動:

@Composable
fun Shape(
    color: Color, @FloatRange(from = 0.0, to = 1.0) transparency: Float, strokeWidth: Dp,
    onMoveShape: (dragAmount: Offset) -> Unit,
    builder: Path.(size: Size, layoutDirection: LayoutDirection) -> Unit
) {
    val fillColor = color.copy(transparency)
    val drawingShape = GenericShape(builder)

    val position = Modifier.fillMaxSize()

    val border = Modifier.border(strokeWidth, color, drawingShape)
    val background = Modifier.background(fillColor, drawingShape)
    val clip = Modifier.clip(drawingShape)

    val clickListener = Modifier.clickable { /* ... */ }

    val dragListener = Modifier.draggable { change, dragAmount ->
        change.consumeAllChanges()
        onMoveShape(dragAmount)
    }

    Box(position + border + background + clip + clickListener + dragListener)
}

onMoveShape 回調移動構建器中使用的點,圍繞這些點觸發重新組合,效果很好。 我的問題是,當我移動形狀時,可以開始拖動和單擊事件的區域不會更新。 我認為最好在此屏幕截圖中對此進行解釋:

在此處輸入圖片說明

我刪除了上面紅點的代碼,因為它對問題不重要。 我猜因為單擊和拖動偵聽器不依賴於繪圖形狀,所以它們不會重新組合,這就是該區域未更新的原因。 有什么想法可以存檔嗎?

修飾符的+draggable修飾符是擴展函數順便說一句。

要創建可點擊和可拖動的組合,

@Composable
fun DraggableShape() {
    Box(modifier = Modifier.fillMaxSize()) {
        var offsetX by remember { mutableStateOf(0f) }
        var offsetY by remember { mutableStateOf(0f) }

        Box(
            Modifier
                .offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
                .background(Color.Blue)
                .size(50.dp)
                .clickable {
                    Log.e("TAG","Clicked")
                }
                .pointerInput(Unit) {
                    detectDragGestures { change, dragAmount ->
                        change.consumeAllChanges()
                        offsetX += dragAmount.x
                        offsetY += dragAmount.y
                    }
                }
        )
    }
}

來源:Android 文檔

即使在拖動之后,單擊事件也能正常工作。

筆記:
使用pointerInput向所有方向draggable ,使用draggable向單個方向拖動。

如果這仍然不適合您,請提供可重現問題的最小代碼。
(當前代碼具有擴展名、形狀等,我在其中找不到確切的問題)

不要將你的 dragListener 放在你的可組合中。 如果您的可組合重新組合,它將被銷毀並重新創建,從而導致其失去狀態。 相反,將拖動偵聽器作為 lamda 參數傳入。 使用狀態提升來做到這一點。 您的提升組合不應該重新組合。 將普通偵聽器(如單擊偵聽器)放在可組合中是可以的,因為在大多數情況下,重新組合它們不會影響它們的邏輯 - 例如按鈕單擊事件。 但是,如果您的偵聽器需要在拖動等事件期間維護狀態數據,則需要維護該狀態。 嘗試這樣的事情:

@Composable
fun ShapeHandler() {

    val dragListener = Modifier.draggable { change, dragAmount ->
        change.consumeAllChanges()
        onMoveShape(dragAmount)
    }
   
   Shape(
      color = xxx,
      transparency = xxx,
      strokeWidth = xxx
      onMoveShape = xxx,
      builder = xxx,
      dragListener = dragListener
   )
}

@Composable
fun Shape(
    color: Color, 
    @FloatRange(from = 0.0, to = 1.0) transparency: Float, 
    strokeWidth: Dp,
    onMoveShape: (dragAmount: Offset) -> Unit,
    builder: Path.(size: Size, layoutDirection: LayoutDirection) -> Unit,
    dragListener: DragListener
) {
    val fillColor = color.copy(transparency)
    val drawingShape = GenericShape(builder)

    val position = Modifier.fillMaxSize()

    val border = Modifier.border(strokeWidth, color, drawingShape)
    val background = Modifier.background(fillColor, drawingShape)
    val clip = Modifier.clip(drawingShape)

    val clickListener = Modifier.clickable { /* ... */ }

    Box(position + border + background + clip + clickListener + dragListener)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM