0

how to get the actual size values with compose? if something with the layout size has to be done before feeding the data to the view? i don't like checking. when everytime the canvas redraws

    Box {
        var count by rememberSaveable {
            mutableStateOf(0)
        }
        var states = remember { mutableListOf<Rain>() }
        Canvas(modifier = Modifier.fillMaxSize()) {
            // i need the canvas' size so i initialize the object inside this scope, and check it every time when canvas redraws
            Log.e("canvas", "repainted")
            if(states.isEmpty()) states.addAll(MutableList(300) {
                Rain(size.width, size.height)
            })
            drawRect(color = Color.Black)
            repeat(300) {
                val c = count
                val x1 = states[it].x1
                val x2 = states[it].x2
                val y1 = states[it].y1
                val y2 = states[it].y2
                val color = states[it].color
                drawLine(start = Offset(x1, y1), end = Offset(x2, y2), color = color)
                states[it]()
            }
        }
        LaunchedEffect(isPaused) {
            while (!isPaused) {
                delay(40)
                count++
            }
        }
    }

2 Answers 2

2

You can save canvasSize into a state variable, and then use derivedStateOf for your states: content of this block will only be recalculated when any of mutable states used inside are changed, in this case it'll be canvasSize

Box {
    var count by rememberSaveable {
        mutableStateOf(0)
    }
    var canvasSize by remember { mutableStateOf(Size.Unspecified) }
    val states by remember(canvasSize) {
        derivedStateOf {
            List(300) {
                Rain(canvasSize.width, canvasSize.height)
            }
        }
    }
    Canvas(
        modifier = Modifier
            .fillMaxSize()
    ) {
        canvasSize = size
        drawRect(color = Color.Blue)
        repeat(300) {
            val x1 = states[it].x1
            val x2 = states[it].x2
            val y1 = states[it].y1
            val y2 = states[it].y2
            drawLine(start = Offset(x1, y1), end = Offset(x2, y2), color = color)
        }
        states[it]()
    }
    LaunchedEffect(isPaused) {
        while (!isPaused) {
            delay(40)
            count++
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

excuse me, i have no ideas how to create states inside drawScope using remember, compose invocations can only happen from the context of a Composable function , it says so. i have to implement my own one?
do you mean mutable state inside Canvas is all by itself a kind of remember?
@user16799920 I misunderstood your question, check the update
thanks, it does work. and it was wrong of my broken language which is hard to understand.
0

DrawScope where inside has some properties one of them being size which itself has width, height, minDimension and maxDimension properties.

Canvas {
       size.width
       size.height
}

others are

@DrawScopeMarker
interface DrawScope : Density {

    /**
     * The current [DrawContext] that contains the dependencies
     * needed to create the drawing environment
     */
    val drawContext: DrawContext

    /**
     * Center of the current bounds of the drawing environment
     */
    val center: Offset
        get() = drawContext.size.center

    /**
     * Provides the dimensions of the current drawing environment
     */
    val size: Size
        get() = drawContext.size

    /**
     * The layout direction of the layout being drawn in.
     */
    val layoutDirection: LayoutDirection
...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.