google / horologist

Horologist is a group of libraries that aim to supplement Wear OS developers with features that are commonly required by developers but not yet available.
https://google.github.io/horologist/
Apache License 2.0
565 stars 93 forks source link

[Feature Request] Let rotaryWithScroll support nested scrolling #1862

Closed ichenhe closed 5 months ago

ichenhe commented 10 months ago

Horologist Version: 0.4.17

Currently Modifier.rotaryWithScroll() takes and manipulates ScrollableState directly, which may bypass the nested scroll mechanism.

Maybe this modifier factory function can take NestedScrollDispatcher as another parameter so that it can incorporate nested scrolling. Alternatively, it would be great to have another, more concise API design.

yschimke commented 10 months ago

Cc @Kpeved in case you have thoughts

ichenhe commented 10 months ago

@Kpeved Here's my basic idea:

To support nested scrolling, we must implement the following:

Parameter

A parameter can be introduced to allow developer to specify the scroll axis and to provide their own NestedScrollDispatcher if needed.

Example ```kotlin data class NestedScrollOptions ( val axis: NestedScrollAxis, val dispatcher: NestedScrollDispatcher = NestedScrollDispatcher() ) // public api public fun Modifier.rotaryWithScroll( scrollableState: ScrollableState, nestedScrollOptions: NestedScrollOptions? = null, // others... ) ```

Dispatch

  1. Make RotaryInputNode extend DelegatingNode and register a delegate node: nestedScrollModifierNode(). The NestedScrollConnection here is meaningless so an empty implementation can be used.

    Example ```kotlin private class RotaryInputNode( var rotaryScrollHandler: RotaryScrollHandler, var nestedScrollDispatcher: NestedScrollDispatcher, ) : RotaryInputModifierNode, DelegatingNode() { init { val conn = object : NestedScrollConnection {} delegate(nestedScrollModifierNode(conn, dispatcher = nestedScrollDispatcher)) } } ```
  2. Modify the RotaryScrollBehavior to dispatch nested scroll event.

    Example ```kotlin // RotaryScrollBehavior suspend fun handleEvent(targetValue: Float) { scrollAnimation.animateTo() { var consumed = dispatcher.dispatchPreScroll(Offset(0f, delta), NestedScrollSource.Wheel).y consumed += scrollBy(delta - consumed) dispatcher.dispatchPostScroll( Offset(0f, consumed), Offset(0f, delta - consumed), NestedScrollSource.Wheel ) } } ```
Kpeved commented 10 months ago

@ichenhe thanks for your feedback and proposal. That request makes total sense. We're working on bringing rotary support by default to Compose for WearOS in AndroidX, so this will be very useful. What we have to do is to align this api with similar apis regarding nested scroll support.

yschimke commented 5 months ago

This is no longer relevant for the deprecated methods in horologist.