Is there any plans to have the PositionIndicator h...
# compose-wear
t
Is there any plans to have the PositionIndicator highlight configurable? I'm facing a small issue due to rounding leading to double state update leading to blinking of the indicator. (Like a volume bar that send the volume to a remote device then receive the updated volume that is a little different and update the state).
j
I am not sure what you mean by making the highlight configurable. Perhaps you can provide some specifics of the issue you are facing. @Sergio Sancho
s
You can configure some of the PositionIndicator's behavior by creating your own PositionIndicatorState (you can use the existing ones as inspiration). Alternatively, for your concrete case, you can use two state variables, one to display in the position indicator, and another for the value synced from the actual device (and you can configure some of the behavior by changing how you update between them)
t
Unfortunately PositionIndicatorState does not give much access to the highlight behavior, and in my case the external volume could be changed externally so the indicator will need to be updated when the actual device change. Even with hard rounding and limitation of the possible values, the risk of value change will still be present.
s
Wait, I missunderstood, by highlight you mean the animation on alpha PositionIndicator does when the state changes. Right, currently we have no configuration of that. You can still use the two state variables approach, and carry changes from the actual device state to the position indicator state only when the change is significant (to avoid the highlight on rounding errors, but still animate when there is an external volumen change).
t
Yes talking about that one. Dual state looks too error prone, I'll probably go with a local copy of the indicator if there's not too much internal stuff to carry with it.
While you are here, some insight about the other Time text stuff?
s
One very simple way (but it may fail on edge cases) to implement the 2-state idea is something like
val positionIndicatorState by remember { derivedStateOf { round(actualDeviceState * K) / K } }
One a bit more involved is to implement a PositionIndicatorState wrapper, that keeps track of the last value for positionFraction, and returns an update only if the change is big enough.
t
Yes rounding is not 100% so not worth it. The second solution will be needed if I can't easily duplicate the source due to too much internal stuff referenced.
s
Something like:
Copy code
fun wrap(wrapped: PositionIndicatorState) = object : PositionIndicatorState {
    var previousPositionFraction: Float = -1f
    override val positionFraction: Float
        get() = run {
            val newFraction = wrapped.positionFraction
            if (abs(previousPositionFraction - newFraction) > 0.1f) {
                previousPositionFraction = newFraction
            }
            previousPositionFraction
        }
    ...
}
t
Of course thanks for this nice approach don't know why I wanted to make it more complicated than needed.
s
No problem. One more idea:
Copy code
val deNoisedPosition = remember {
    var prev = position.value
    derivedStateOf {
        val newVal = position.value
        if (abs(newVal - prev) > 0.01f) {
            prev = newVal
        }
        prev
    }
}
t
Ok so the last one works nice and is easy, there's just one last little point the FractionPositionIndicatorState is internal and have a forced start value of 1f, so when the indicator is first drawn if the starting position is not 0 it will animate. This is not always wanted like displaying the indicator after a gesture with a non 0 starting point. the alpha animation coupled with already an animation to display the screen containing the indicator does not look nice specially with different durations. I can easily write my own state now that we discussed that, but maybe that one should have a native solution as it does not seem as uncommon as rounding issues ?
Actually no the first animation runs always
Any idea about the first highlight animation ?
s
So, as far as I can see, the highlight animation should only trigger when the value returned by the value function changes (the positionFraction = 1f is constant, that kind of position indicator is always at the bottom/end, only the size changes). There is an animation to show the indicator since it starts as not showing and fraction position indicators are always shown. I don't think there is an easy way to avoid that.
t
The issue is that the launch is also tied to the height resolution, so even with a custom state that have the proper starting value there's still the long animation (650ms) running, way longer than a typical animation to show the containing screen 😞 Do you think this is something than can be addressed at the library level? Position indicator use many wear internal functions so is not easy to just copy paste to change.
s
Right, I'll see if we can add some configuration options for the animations, without making the API more complex than needed.
t
Thanks.