https://kotlinlang.org logo
#compose
Title
# compose
a

Adam Bennett

04/11/2020, 9:11 AM
Is there an equivalent to this in
Canvas
using Compose? I'm looking to do this
Copy code
override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        calculatePropagation()
        canvas?.let { render() }
        postInvalidateDelayed(20)
    }
But I can't seem to find an equivalent for repeatedly drawing to Canvas. I've done a tonne of digging through docs and on here - can anyone chime in?
b

Bacho Kurtanidze

04/11/2020, 11:15 AM
Copy code
fun Modifier.drawBehind(
    onDraw: Density.(canvas: Canvas, size: PxSize) -> Unit
) = this + DrawBackgroundModifier(onDraw)
have you tried this modifier?
a

Adam Bennett

04/11/2020, 11:21 AM
No I haven't, thanks I'll look into this
👍 1
Is there a way with this modifier to call draw repeatedly with a delay of some form? I haven't had much experience with modifiers so trying to wrap my head around it
b

Bacho Kurtanidze

04/11/2020, 11:35 AM
I think you can request recomposition manually with recompose method. so Recompose and simple Handler.delay could do the trick. for reference look at this link https://github.com/Foso/Jetpack-Compose-Playground/blob/master/mkdocs/compose/recompose.md
a

Adam Bennett

04/11/2020, 11:52 AM
Aha! I think this was the method I was missing
Thank you so much
t

Timo Drick

04/11/2020, 11:58 AM
Maybe you should also consider use an animated state variable to trigger the recomposition automatically. Because it only makes sense to redraw when you draw something different the second time
b

Bacho Kurtanidze

04/11/2020, 12:11 PM
@Adam Bennett Glad I managed to help
a

Adam Powell

04/11/2020, 1:36 PM
There's a
Canvas
composable function that will take up some layout space for you to draw into. You should separate the time pulse code from your drawing code though.
The Canvas composable uses that modifier from above as its implementation
a

Adam Bennett

04/11/2020, 1:44 PM
Interesting, thank you. I think I've got everything I need
a

Adam Powell

04/12/2020, 1:40 PM
Nice post resulting from this 🙂
a

Adam Bennett

04/12/2020, 2:09 PM
Thank you! If there's a more idiomatic way of achieving this I'd love to know
a

Adam Powell

04/12/2020, 2:56 PM
You had the right of it in terms of driving it from data updates. You could get a bit more efficient in the data structures used after that given the use case but the single-value state update is a good start here.
In particular you can have it skip composition entirely using the approach you arrived at, since compose knows the difference between state read by a composable function and state read by drawing code
a

Adam Bennett

04/12/2020, 3:42 PM
Interesting feedback, thank you. I didn't know that compose could distinguish where the state was being read from, that's clever. Would be interested to see how others would approach the same problem within the compose framework
a

Adam Powell

04/12/2020, 4:15 PM
yep, we maintain different observation scopes. Composable functions have a local observation scope within the function body, and we also have separate observation scopes for measurement, layout and drawing of different elements.
so we can tell the difference between what part of the UI needs to do work. Much easier than trying to track manual `requestLayout()`/`invalidate()` everywhere - we record when you read state instead and infer what scopes need to invalidate from there.
a

Adam Bennett

04/12/2020, 4:19 PM
That makes a tonne of sense. Brilliant, thanks so much for chiming in
👍 1
a

Adam Powell

04/12/2020, 4:27 PM
thanks for the cool demo! I'm sure Fabian and Romain will get a kick out of it too 🙂
a

Adam Bennett

04/12/2020, 4:29 PM
I hope so!
5 Views