Skip to content

iOS native scroll and feel - #609

Merged
Elijah Semyonov (elijah-semyonov) merged 135 commits into
jb-mainfrom
elijah.semyonov/ios-scroll-behavior
Jul 10, 2023
Merged

iOS native scroll and feel#609
Elijah Semyonov (elijah-semyonov) merged 135 commits into
jb-mainfrom
elijah.semyonov/ios-scroll-behavior

Conversation

@elijah-semyonov

@elijah-semyonov Elijah Semyonov (elijah-semyonov) commented Jun 27, 2023

Copy link
Copy Markdown

Proposed Changes

Implement CupertinoScrollDecayAnimationSpec to simulate iOS inertia equation.
Implement CupertinoOverscrollEffect to simulate rubber banding and spring effect.

Testing

Test: launch iOS app and test interaction between fling and overscroll

Notes

Comments for CupertinoOverscrollEffect.direction mention this behavior for 2D cases:
Left picture shows visual path of combined scroll offset (scrollable content offset + overscroll offset), rect represents bounds of values max(0, content.size - frame.size) for each dimension.
Right pictures show value over time (t) for X and Y components. Green changes are happening inside spring animation, blue inside fling animation. (t) scale is matching for both (bottom and top on the right).
tempImagepBK72j
tempImageirkMZm

Currently the API forces us to communicate with outer entities using velocities deltas, which is built on assumption that all these animations' stages happen in sync for both dimensions (which is not the case).

override suspend fun applyToFling(
        velocity: Velocity,
        performFling: suspend (Velocity) -> Velocity
    ) {
        val availableFlingVelocity = playInitialSpringAnimationIfNeeded(velocity)

        val velocityConsumedByFling = performFling(availableFlingVelocity)
        val postFlingVelocity = availableFlingVelocity - velocityConsumedByFling

        playSpringAnimation(
            lastFlingUncosumedDelta.toFloat(),
            postFlingVelocity.toFloat(),
            false
        )
    }

# Conflicts:
#	compose/mpp/demo/src/commonMain/kotlin/androidx/compose/mpp/demo/LazyLayouts.kt
@elijah-semyonov
Elijah Semyonov (elijah-semyonov) deleted the elijah.semyonov/ios-scroll-behavior branch July 10, 2023 10:14
Nikolai Rykunov (Walingar) pushed a commit to Walingar/androidx that referenced this pull request Jul 11, 2023
* developmentTeamToRunOnRealDevice

* print jvm arch

* iOS run configuration

* redundant run configurations

* run configurations

* Revert "run configurations"

This reverts commit 3b04108.

* Revert "redundant run configurations"

This reverts commit bb18b67.

* Revert "iOS run configuration"

This reverts commit 69b717e.

* simplify

* check runOnDevice correctly

* update README

* update README

* run with Xcode

* run with Xcode

* run with Xcode

* doc run mpp/demo-uikit sample on iOS

* projectProperties

* projectProperties

* fix iOS on x86-64

* simplify demo-uikit

* Added check to TEAM_ID

* Add geometry functions to Offset.kt

* Implement DecelerationTimingParameters

* add feature flag

* Add RubberBand effect business logic

* Fix comment

* Refactor RubberBand

* WIP: start experimenting

* Revert Scroll.kt changes

* Chop OvercrollEffect actual providers into uikit and macos targets. Implement stub for iOS.

* Implement working stub for iOS.

* Implement rubber band logic in IOSOverScrollEffect

* Delete dead code, mark private members accordingly.

* Explicitly pass environmental variables to Xcode build script.

* Integrate COMPOSE_DEMO_APPLE_TEAM_ID variable into xcodegen

* Add stub for demo with spring animation

* Add Underdamped spring solution

* Create logic for making spring solution

* Snapshot

* Remove dead code.

* Add spec-based implementation

* Add test case to check animation

* Snapshot

* Snapshot

* Snapshot

* Snapshot

* Snapshot everything except edge case working

* Move connecting fling behavior and overscroll further down the tree

* Add back button on nested selection screens in Demo App

* Play spring animation on zero velocity fling.

* Remove dead code

* Snapshot before fling from overscroll edge case

* Resolve edge case of flinging from inside overscroll area

* Update documentation

* Refactor boolean value to OverscrollOffsetSpace enum

* Refactor boolean value to OverscrollOffsetSpace enum

* Modify API to support interaction between OverscrollEffect and FlingBehavior

* Delete dead code.

* Update comment.

* Update comment.

* Move division by density outside of Offset

* Revert "Add geometry functions to Offset.kt"

This reverts commit 947b295.

* Remove redundant import

* Remove redundant CupertinoFlingBehavior.

* Remove redundant constructor arg

* Refine documentation

* Modify android code and tests to conform to API change

* Update document

* Reset change

* Remove gradle line.

* Revert changes

* Revert changes

* Revert changes

* Add comment

* Make constant internal

* Revert Scrollable.kt.

* Bring CupertinoFlingBehavior back

* Revert changes.

* Revert API change.

* Updater converter interface

* Update CupertinoOverscrollEffect

* Update CupertinoOverscrollEffect

* Revert "Modify android code and tests to conform to API change"

This reverts commit d5ad295.

* Revert changes

* Remove dead code mentions

* Bind cupertino fling and overscroll behavior together

* Fix a wrong construction argument bug

* Revert line

* Remove unneeded imports

* Remove rubberband/linear space logic. iOS seems to calculate everything in rubberband space.

* Update stiffness to counteract rubbe-band space visual feedback.

* Fix typo.

* Return it back.

* Refactor density injection logic.

* Fix edge case.

* Change var to val

* Remove new line

* Fix formatting

* Fix typo

* Adjust fling from overscroll logic

* Implement Cupertino behavior using old API

* Remove println

* Fix RTL and add demo

* Make added API internal

* Add optOut API

* Update comment

* Remove ScrollValueConverter altogether.

* Update documentation

* Move CupertinoScrollDecayAnimationSpec to uikit source set

* Move CupertinoOverscrollEffect to cupertino module

* Change visibility modifer

* Change visibility modifier

* Move CupertinoScrollDecayAnimationSpec to cupertino module

* Revert visibility modifier change.

* Fix formatting

* Remove dead code.

* Use specific type instead of a Pair

* Add explicit arguments' names

* Update formatting

* Replace boolean with enum

* Move Velocity<->Offset conversions to file scope.

* Replace default decelerationRate with iOS constant instead of literal

* Remove extra line

* Move opt-out rubber banding to ScrollConfig

* Refactor last change a bit

* Rename UIKitScroll config

* Fix experimental annotation to correct one

---------

Co-authored-by: dima.avdeev <dima.avdeev@jetbrains.com>
Vladimir Mazunin (mazunin-v-jb) pushed a commit that referenced this pull request Jul 11, 2023
* developmentTeamToRunOnRealDevice

* print jvm arch

* iOS run configuration

* redundant run configurations

* run configurations

* Revert "run configurations"

This reverts commit 3b04108.

* Revert "redundant run configurations"

This reverts commit bb18b67.

* Revert "iOS run configuration"

This reverts commit 69b717e.

* simplify

* check runOnDevice correctly

* update README

* update README

* run with Xcode

* run with Xcode

* run with Xcode

* doc run mpp/demo-uikit sample on iOS

* projectProperties

* projectProperties

* fix iOS on x86-64

* simplify demo-uikit

* Added check to TEAM_ID

* Add geometry functions to Offset.kt

* Implement DecelerationTimingParameters

* add feature flag

* Add RubberBand effect business logic

* Fix comment

* Refactor RubberBand

* WIP: start experimenting

* Revert Scroll.kt changes

* Chop OvercrollEffect actual providers into uikit and macos targets. Implement stub for iOS.

* Implement working stub for iOS.

* Implement rubber band logic in IOSOverScrollEffect

* Delete dead code, mark private members accordingly.

* Explicitly pass environmental variables to Xcode build script.

* Integrate COMPOSE_DEMO_APPLE_TEAM_ID variable into xcodegen

* Add stub for demo with spring animation

* Add Underdamped spring solution

* Create logic for making spring solution

* Snapshot

* Remove dead code.

* Add spec-based implementation

* Add test case to check animation

* Snapshot

* Snapshot

* Snapshot

* Snapshot

* Snapshot everything except edge case working

* Move connecting fling behavior and overscroll further down the tree

* Add back button on nested selection screens in Demo App

* Play spring animation on zero velocity fling.

* Remove dead code

* Snapshot before fling from overscroll edge case

* Resolve edge case of flinging from inside overscroll area

* Update documentation

* Refactor boolean value to OverscrollOffsetSpace enum

* Refactor boolean value to OverscrollOffsetSpace enum

* Modify API to support interaction between OverscrollEffect and FlingBehavior

* Delete dead code.

* Update comment.

* Update comment.

* Move division by density outside of Offset

* Revert "Add geometry functions to Offset.kt"

This reverts commit 947b295.

* Remove redundant import

* Remove redundant CupertinoFlingBehavior.

* Remove redundant constructor arg

* Refine documentation

* Modify android code and tests to conform to API change

* Update document

* Reset change

* Remove gradle line.

* Revert changes

* Revert changes

* Revert changes

* Add comment

* Make constant internal

* Revert Scrollable.kt.

* Bring CupertinoFlingBehavior back

* Revert changes.

* Revert API change.

* Updater converter interface

* Update CupertinoOverscrollEffect

* Update CupertinoOverscrollEffect

* Revert "Modify android code and tests to conform to API change"

This reverts commit d5ad295.

* Revert changes

* Remove dead code mentions

* Bind cupertino fling and overscroll behavior together

* Fix a wrong construction argument bug

* Revert line

* Remove unneeded imports

* Remove rubberband/linear space logic. iOS seems to calculate everything in rubberband space.

* Update stiffness to counteract rubbe-band space visual feedback.

* Fix typo.

* Return it back.

* Refactor density injection logic.

* Fix edge case.

* Change var to val

* Remove new line

* Fix formatting

* Fix typo

* Adjust fling from overscroll logic

* Implement Cupertino behavior using old API

* Remove println

* Fix RTL and add demo

* Make added API internal

* Add optOut API

* Update comment

* Remove ScrollValueConverter altogether.

* Update documentation

* Move CupertinoScrollDecayAnimationSpec to uikit source set

* Move CupertinoOverscrollEffect to cupertino module

* Change visibility modifer

* Change visibility modifier

* Move CupertinoScrollDecayAnimationSpec to cupertino module

* Revert visibility modifier change.

* Fix formatting

* Remove dead code.

* Use specific type instead of a Pair

* Add explicit arguments' names

* Update formatting

* Replace boolean with enum

* Move Velocity<->Offset conversions to file scope.

* Replace default decelerationRate with iOS constant instead of literal

* Remove extra line

* Move opt-out rubber banding to ScrollConfig

* Refactor last change a bit

* Rename UIKitScroll config

* Fix experimental annotation to correct one

---------

Co-authored-by: dima.avdeev <dima.avdeev@jetbrains.com>
Igor Demin (igordmn) pushed a commit that referenced this pull request Nov 15, 2023
* developmentTeamToRunOnRealDevice

* print jvm arch

* iOS run configuration

* redundant run configurations

* run configurations

* Revert "run configurations"

This reverts commit 3b04108.

* Revert "redundant run configurations"

This reverts commit bb18b67.

* Revert "iOS run configuration"

This reverts commit 69b717e.

* simplify

* check runOnDevice correctly

* update README

* update README

* run with Xcode

* run with Xcode

* run with Xcode

* doc run mpp/demo-uikit sample on iOS

* projectProperties

* projectProperties

* fix iOS on x86-64

* simplify demo-uikit

* Added check to TEAM_ID

* Add geometry functions to Offset.kt

* Implement DecelerationTimingParameters

* add feature flag

* Add RubberBand effect business logic

* Fix comment

* Refactor RubberBand

* WIP: start experimenting

* Revert Scroll.kt changes

* Chop OvercrollEffect actual providers into uikit and macos targets. Implement stub for iOS.

* Implement working stub for iOS.

* Implement rubber band logic in IOSOverScrollEffect

* Delete dead code, mark private members accordingly.

* Explicitly pass environmental variables to Xcode build script.

* Integrate COMPOSE_DEMO_APPLE_TEAM_ID variable into xcodegen

* Add stub for demo with spring animation

* Add Underdamped spring solution

* Create logic for making spring solution

* Snapshot

* Remove dead code.

* Add spec-based implementation

* Add test case to check animation

* Snapshot

* Snapshot

* Snapshot

* Snapshot

* Snapshot everything except edge case working

* Move connecting fling behavior and overscroll further down the tree

* Add back button on nested selection screens in Demo App

* Play spring animation on zero velocity fling.

* Remove dead code

* Snapshot before fling from overscroll edge case

* Resolve edge case of flinging from inside overscroll area

* Update documentation

* Refactor boolean value to OverscrollOffsetSpace enum

* Refactor boolean value to OverscrollOffsetSpace enum

* Modify API to support interaction between OverscrollEffect and FlingBehavior

* Delete dead code.

* Update comment.

* Update comment.

* Move division by density outside of Offset

* Revert "Add geometry functions to Offset.kt"

This reverts commit 947b295.

* Remove redundant import

* Remove redundant CupertinoFlingBehavior.

* Remove redundant constructor arg

* Refine documentation

* Modify android code and tests to conform to API change

* Update document

* Reset change

* Remove gradle line.

* Revert changes

* Revert changes

* Revert changes

* Add comment

* Make constant internal

* Revert Scrollable.kt.

* Bring CupertinoFlingBehavior back

* Revert changes.

* Revert API change.

* Updater converter interface

* Update CupertinoOverscrollEffect

* Update CupertinoOverscrollEffect

* Revert "Modify android code and tests to conform to API change"

This reverts commit d5ad295.

* Revert changes

* Remove dead code mentions

* Bind cupertino fling and overscroll behavior together

* Fix a wrong construction argument bug

* Revert line

* Remove unneeded imports

* Remove rubberband/linear space logic. iOS seems to calculate everything in rubberband space.

* Update stiffness to counteract rubbe-band space visual feedback.

* Fix typo.

* Return it back.

* Refactor density injection logic.

* Fix edge case.

* Change var to val

* Remove new line

* Fix formatting

* Fix typo

* Adjust fling from overscroll logic

* Implement Cupertino behavior using old API

* Remove println

* Fix RTL and add demo

* Make added API internal

* Add optOut API

* Update comment

* Remove ScrollValueConverter altogether.

* Update documentation

* Move CupertinoScrollDecayAnimationSpec to uikit source set

* Move CupertinoOverscrollEffect to cupertino module

* Change visibility modifer

* Change visibility modifier

* Move CupertinoScrollDecayAnimationSpec to cupertino module

* Revert visibility modifier change.

* Fix formatting

* Remove dead code.

* Use specific type instead of a Pair

* Add explicit arguments' names

* Update formatting

* Replace boolean with enum

* Move Velocity<->Offset conversions to file scope.

* Replace default decelerationRate with iOS constant instead of literal

* Remove extra line

* Move opt-out rubber banding to ScrollConfig

* Refactor last change a bit

* Rename UIKitScroll config

* Fix experimental annotation to correct one

---------

Co-authored-by: dima.avdeev <dima.avdeev@jetbrains.com>
Zahari Zahariev (harryzz) pushed a commit to harryzz/compose-multiplatform-core that referenced this pull request Jul 28, 2026
* developmentTeamToRunOnRealDevice

* print jvm arch

* iOS run configuration

* redundant run configurations

* run configurations

* Revert "run configurations"

This reverts commit 3b04108.

* Revert "redundant run configurations"

This reverts commit bb18b67.

* Revert "iOS run configuration"

This reverts commit 69b717e.

* simplify

* check runOnDevice correctly

* update README

* update README

* run with Xcode

* run with Xcode

* run with Xcode

* doc run mpp/demo-uikit sample on iOS

* projectProperties

* projectProperties

* fix iOS on x86-64

* simplify demo-uikit

* Added check to TEAM_ID

* Add geometry functions to Offset.kt

* Implement DecelerationTimingParameters

* add feature flag

* Add RubberBand effect business logic

* Fix comment

* Refactor RubberBand

* WIP: start experimenting

* Revert Scroll.kt changes

* Chop OvercrollEffect actual providers into uikit and macos targets. Implement stub for iOS.

* Implement working stub for iOS.

* Implement rubber band logic in IOSOverScrollEffect

* Delete dead code, mark private members accordingly.

* Explicitly pass environmental variables to Xcode build script.

* Integrate COMPOSE_DEMO_APPLE_TEAM_ID variable into xcodegen

* Add stub for demo with spring animation

* Add Underdamped spring solution

* Create logic for making spring solution

* Snapshot

* Remove dead code.

* Add spec-based implementation

* Add test case to check animation

* Snapshot

* Snapshot

* Snapshot

* Snapshot

* Snapshot everything except edge case working

* Move connecting fling behavior and overscroll further down the tree

* Add back button on nested selection screens in Demo App

* Play spring animation on zero velocity fling.

* Remove dead code

* Snapshot before fling from overscroll edge case

* Resolve edge case of flinging from inside overscroll area

* Update documentation

* Refactor boolean value to OverscrollOffsetSpace enum

* Refactor boolean value to OverscrollOffsetSpace enum

* Modify API to support interaction between OverscrollEffect and FlingBehavior

* Delete dead code.

* Update comment.

* Update comment.

* Move division by density outside of Offset

* Revert "Add geometry functions to Offset.kt"

This reverts commit 947b295.

* Remove redundant import

* Remove redundant CupertinoFlingBehavior.

* Remove redundant constructor arg

* Refine documentation

* Modify android code and tests to conform to API change

* Update document

* Reset change

* Remove gradle line.

* Revert changes

* Revert changes

* Revert changes

* Add comment

* Make constant internal

* Revert Scrollable.kt.

* Bring CupertinoFlingBehavior back

* Revert changes.

* Revert API change.

* Updater converter interface

* Update CupertinoOverscrollEffect

* Update CupertinoOverscrollEffect

* Revert "Modify android code and tests to conform to API change"

This reverts commit d5ad295.

* Revert changes

* Remove dead code mentions

* Bind cupertino fling and overscroll behavior together

* Fix a wrong construction argument bug

* Revert line

* Remove unneeded imports

* Remove rubberband/linear space logic. iOS seems to calculate everything in rubberband space.

* Update stiffness to counteract rubbe-band space visual feedback.

* Fix typo.

* Return it back.

* Refactor density injection logic.

* Fix edge case.

* Change var to val

* Remove new line

* Fix formatting

* Fix typo

* Adjust fling from overscroll logic

* Implement Cupertino behavior using old API

* Remove println

* Fix RTL and add demo

* Make added API internal

* Add optOut API

* Update comment

* Remove ScrollValueConverter altogether.

* Update documentation

* Move CupertinoScrollDecayAnimationSpec to uikit source set

* Move CupertinoOverscrollEffect to cupertino module

* Change visibility modifer

* Change visibility modifier

* Move CupertinoScrollDecayAnimationSpec to cupertino module

* Revert visibility modifier change.

* Fix formatting

* Remove dead code.

* Use specific type instead of a Pair

* Add explicit arguments' names

* Update formatting

* Replace boolean with enum

* Move Velocity<->Offset conversions to file scope.

* Replace default decelerationRate with iOS constant instead of literal

* Remove extra line

* Move opt-out rubber banding to ScrollConfig

* Refactor last change a bit

* Rename UIKitScroll config

* Fix experimental annotation to correct one

---------

Co-authored-by: dima.avdeev <dima.avdeev@jetbrains.com>
Zahari Zahariev (harryzz) pushed a commit to harryzz/compose-multiplatform-core that referenced this pull request Jul 28, 2026
…mon*`

Test: ./gradlew paging:paging-testing:allTests

This is an imported pull request from androidx#609.

Resolves JetBrains#609
Github-Pr-Head-Sha: 8ce38e6
GitOrigin-RevId: ea700e2
Change-Id: I001dac7814ba8b9a01f1797657efac0643a18b0c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants