Is there a “compose way” to invoke callback passin...
# compose
j
Is there a “compose way” to invoke callback passing touch based data from a custom composable? I’m using
Canvas {}
to draw a custom graph and I’d like to report the trig values (
sin
,
cos
,
tan
,
theta
) at which the graph was last interacted to calling code. My concern is invoking the callback to often even when the angle hasn’t changed (I do some rounding so tiny changes won’t be reflected). Is this a better use for custom state class to hold the values?
t
I think you maybe want to do it like it is done e.g. for scrolling. So they do have a state class which stores the current scrolling position using a mutablestate. (So no callback) But depends on how you want to use this information. But when it is for the UI it would be fine.
j
I plan to use the information for another Composable that will handle displaying it in a different format; should be black box from the source composable.
t
Yes than you can use my proposed approach:
Copy code
class TouchState(initial: Int) {
    var value: Int by mutableIntStateOf(initial)
        private set
}
You can create an instance of this in the parent composable or in your viewmodel. If you want to do it in the compose code make sure to use remember:
Copy code
@Composable
fun rememberTouchState(initial: Int = 0): TouchState {
    return remember {
        TouchState(initial = initial)
    }
}
j
Thanks for the help. I’ll give it a try now.
Would this solution work for multiple values besides just one state value? For example my sin, cos, tan values or should I create a new state class for each value?
Also could you share the file or a link to the scrolling example you mentioned above? I’d like to see the full example and completely understand what’s being done.
t
No you can add as many as you want.
I meant the implementation from the Compose sources: androidx.compose.foundation.ScrollState(..)
So when you type rememberScrollState() in your code. And than navigate to the source it would bring you to the Implementation
🙌🏿 1
j
You’re a saint
👍 1
t
They have also many more parameters in their state
But keep in mind. For properties with by mutableState Compose will detect if it is changed and do the rerendering automatically without callbacks
You could also create one data class with all your parameters and just use one mutableState for this. If all values change at the same time
j
The values will change all at once… I want to keep a collection of individual sin, cos, and tan values… My other composable will manually plot these values. I think holding the 3 mutable collections in a single data class.
t
Oh for collections it is a little bit different
j
.. Actually I think it’ll be better to only hold the current value and my other view would handle holding the values in a collection as an implementation details
👍 1
t
Yes otherwise you have to use a SnapshotStateList
Hmm
j
I’ve not heard of that before.. Any examples of where it’s been used
t
It is the same like mutableStateOf but for lists. But not sure if this is the right choice for your problem. Do you want to draw a graph in a canvas out of the history values?
j
Yes
t
You can try this:
Copy code
class TouchState() {
    var value = mutableStateListOf<Int>()
}
Of ocurse instead of int you could use a custom data class with all your parameters
Please note that here you must not use the 'by' keyword.
Sorry did not found a good documentation
But i am also not sure anymore if this is the right approach. Maybe callback solution is for your usecase better.
j
I think just holding current state and allowing calling code handle the history make more sense…
t
Yes but this is also not so easy. Than you ran into another problem to monitor changes to the value
And at the end you still have to provide a list to the canvas.
j
The fact that compose clears the canvas on every draw (thus requiring keeping history) is an implementation details that shouldn’t leak into sibling composables.
I think I can use a derivedStateOf for observing changes and transforming into a different format ie List
💯 1
t
Maybe you still need the SnapshotStateList so the compose rendering detects changes in the list
j
This is just my best guess. I’m new to this type of thing
t
So you create the list in the canvas composable using mutalbeStateListOf and than adding values to it in your drivedStateOf function. But not sure. Not super easy.