@expo/ui 56.0.15 → 56.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +54 -6
  4. package/android/src/main/java/expo/modules/ui/HostView.kt +0 -2
  5. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +65 -0
  6. package/android/src/main/java/expo/modules/ui/NavigationBarView.kt +95 -0
  7. package/android/src/main/java/expo/modules/ui/RNHostView.kt +182 -6
  8. package/android/src/main/java/expo/modules/ui/textfield/BasicTextField.kt +203 -0
  9. package/android/src/main/java/expo/modules/ui/{TextFieldView.kt → textfield/TextField.kt} +63 -267
  10. package/android/src/main/java/expo/modules/ui/textfield/TextFieldShared.kt +299 -0
  11. package/build/State/useNativeState.d.ts +8 -3
  12. package/build/State/useNativeState.d.ts.map +1 -1
  13. package/build/community/pager-view/PagerView.android.d.ts.map +1 -1
  14. package/build/jetpack-compose/NavigationBar/index.d.ts +101 -0
  15. package/build/jetpack-compose/NavigationBar/index.d.ts.map +1 -0
  16. package/build/jetpack-compose/TextField/BasicTextField.d.ts +36 -0
  17. package/build/jetpack-compose/TextField/BasicTextField.d.ts.map +1 -0
  18. package/build/jetpack-compose/TextField/TextField.d.ts +131 -0
  19. package/build/jetpack-compose/TextField/TextField.d.ts.map +1 -0
  20. package/build/jetpack-compose/TextField/index.d.ts +3 -244
  21. package/build/jetpack-compose/TextField/index.d.ts.map +1 -1
  22. package/build/jetpack-compose/TextField/shared.d.ts +171 -0
  23. package/build/jetpack-compose/TextField/shared.d.ts.map +1 -0
  24. package/build/jetpack-compose/index.d.ts +2 -1
  25. package/build/jetpack-compose/index.d.ts.map +1 -1
  26. package/build/jetpack-compose/modifiers/index.d.ts +42 -0
  27. package/build/jetpack-compose/modifiers/index.d.ts.map +1 -1
  28. package/build/swift-ui/DisclosureGroup/index.d.ts +11 -2
  29. package/build/swift-ui/DisclosureGroup/index.d.ts.map +1 -1
  30. package/build/swift-ui/Image/index.d.ts +7 -1
  31. package/build/swift-ui/Image/index.d.ts.map +1 -1
  32. package/build/swift-ui/Label/index.d.ts +5 -0
  33. package/build/swift-ui/Label/index.d.ts.map +1 -1
  34. package/build/swift-ui/modifiers/index.d.ts +100 -4
  35. package/build/swift-ui/modifiers/index.d.ts.map +1 -1
  36. package/build/universal/Collapsible/index.android.d.ts +1 -1
  37. package/build/universal/Collapsible/index.android.d.ts.map +1 -1
  38. package/build/universal/Collapsible/index.d.ts +1 -1
  39. package/build/universal/Collapsible/index.d.ts.map +1 -1
  40. package/build/universal/Collapsible/index.ios.d.ts +1 -1
  41. package/build/universal/Collapsible/index.ios.d.ts.map +1 -1
  42. package/build/universal/Collapsible/types.d.ts +5 -0
  43. package/build/universal/Collapsible/types.d.ts.map +1 -1
  44. package/build/universal/TextInput/index.android.d.ts.map +1 -1
  45. package/build/universal/TextInput/types.d.ts +5 -1
  46. package/build/universal/TextInput/types.d.ts.map +1 -1
  47. package/expo-module.config.json +1 -1
  48. package/ios/BottomSheetView.swift +1 -1
  49. package/ios/DisclosureGroupView.swift +36 -13
  50. package/ios/ImageView.swift +20 -14
  51. package/ios/Label.swift +26 -2
  52. package/ios/Modifiers/ButtonBorderShapeModifier.swift +46 -0
  53. package/ios/Modifiers/DynamicTypeSizeModifier.swift +56 -0
  54. package/ios/Modifiers/FontModifier.swift +4 -1
  55. package/ios/Modifiers/ImageScaleModifier.swift +29 -0
  56. package/ios/Modifiers/OnGeometryChangeModifier.swift +8 -16
  57. package/ios/Modifiers/ViewModifierRegistry.swift +89 -8
  58. package/ios/SecureFieldView.swift +17 -1
  59. package/ios/TextFieldView.swift +33 -2
  60. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.15/expo.modules.ui-56.0.15-sources.jar → 56.0.17/expo.modules.ui-56.0.17-sources.jar} +0 -0
  61. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17-sources.jar.md5 +1 -0
  62. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17-sources.jar.sha1 +1 -0
  63. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17-sources.jar.sha256 +1 -0
  64. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17-sources.jar.sha512 +1 -0
  65. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.aar +0 -0
  66. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.aar.md5 +1 -0
  67. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.aar.sha1 +1 -0
  68. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.aar.sha256 +1 -0
  69. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.aar.sha512 +1 -0
  70. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.15/expo.modules.ui-56.0.15.module → 56.0.17/expo.modules.ui-56.0.17.module} +22 -22
  71. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.module.md5 +1 -0
  72. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.module.sha1 +1 -0
  73. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.module.sha256 +1 -0
  74. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.module.sha512 +1 -0
  75. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{56.0.15/expo.modules.ui-56.0.15.pom → 56.0.17/expo.modules.ui-56.0.17.pom} +1 -1
  76. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.pom.md5 +1 -0
  77. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.pom.sha1 +1 -0
  78. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.pom.sha256 +1 -0
  79. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.17/expo.modules.ui-56.0.17.pom.sha512 +1 -0
  80. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
  81. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
  82. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
  83. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
  84. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
  85. package/package.json +4 -4
  86. package/src/State/index.fx.ts +4 -1
  87. package/src/State/useNativeState.ts +24 -13
  88. package/src/community/datetime-picker/DateTimePicker.tsx +1 -1
  89. package/src/community/menu/MenuView.ios.tsx +1 -1
  90. package/src/community/pager-view/PagerView.android.tsx +16 -2
  91. package/src/community/pager-view/PagerView.ios.tsx +1 -1
  92. package/src/community/picker/Picker.ios.tsx +1 -1
  93. package/src/community/segmented-control/SegmentedControl.ios.tsx +1 -1
  94. package/src/community/slider/Slider.ios.tsx +1 -1
  95. package/src/jetpack-compose/NavigationBar/index.tsx +174 -0
  96. package/src/jetpack-compose/TextField/BasicTextField.tsx +118 -0
  97. package/src/jetpack-compose/TextField/TextField.tsx +198 -0
  98. package/src/jetpack-compose/TextField/index.ts +19 -0
  99. package/src/jetpack-compose/TextField/{index.tsx → shared.ts} +71 -203
  100. package/src/jetpack-compose/index.ts +7 -0
  101. package/src/jetpack-compose/modifiers/index.ts +49 -0
  102. package/src/swift-ui/BottomSheet/index.tsx +1 -1
  103. package/src/swift-ui/DisclosureGroup/index.tsx +14 -2
  104. package/src/swift-ui/Image/index.tsx +16 -3
  105. package/src/swift-ui/Label/index.tsx +8 -1
  106. package/src/swift-ui/modifiers/index.ts +143 -5
  107. package/src/universal/Collapsible/index.android.tsx +10 -2
  108. package/src/universal/Collapsible/index.ios.tsx +17 -3
  109. package/src/universal/Collapsible/index.tsx +8 -2
  110. package/src/universal/Collapsible/types.ts +7 -0
  111. package/src/universal/TextInput/index.android.tsx +26 -33
  112. package/src/universal/TextInput/types.ts +5 -1
  113. package/android/src/main/java/expo/modules/ui/ShadowNodeSyncFlush.kt +0 -28
  114. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15-sources.jar.md5 +0 -1
  115. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15-sources.jar.sha1 +0 -1
  116. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15-sources.jar.sha256 +0 -1
  117. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15-sources.jar.sha512 +0 -1
  118. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.aar +0 -0
  119. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.aar.md5 +0 -1
  120. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.aar.sha1 +0 -1
  121. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.aar.sha256 +0 -1
  122. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.aar.sha512 +0 -1
  123. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.module.md5 +0 -1
  124. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.module.sha1 +0 -1
  125. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.module.sha256 +0 -1
  126. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.module.sha512 +0 -1
  127. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.pom.md5 +0 -1
  128. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.pom.sha1 +0 -1
  129. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.pom.sha256 +0 -1
  130. package/local-maven-repo/expo/modules/ui/expo.modules.ui/56.0.15/expo.modules.ui-56.0.15.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,53 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 56.0.17 — 2026-06-10
14
+
15
+ ### 🛠 Breaking changes
16
+
17
+ - [universal][android] Use `BasicTextField` component instead of Filled Material TextField. ([#46442](https://github.com/expo/expo/pull/46442) by [@nishan](https://github.com/intergalacticspacehighway))
18
+
19
+ ### 🎉 New features
20
+
21
+ - [iOS] Added the SwiftUI `imageScale` modifier to scale SF Symbols within a view relative to the surrounding text (`small`, `medium`, `large`). ([#46774](https://github.com/expo/expo/pull/46774) by [@ramonclaudio](https://github.com/ramonclaudio))
22
+ - [jetpack-compose] Added `onGloballyPositioned` modifier, which reports a composable's window position and size. ([#46744](https://github.com/expo/expo/pull/46744) by [@nishan](https://github.com/intergalacticspacehighway))
23
+ - [iOS] Extended the SwiftUI `onGeometryChange` modifier to also report the view's global position (`x`/`y`) alongside its size. ([#46744](https://github.com/expo/expo/pull/46744) by [@nishan](https://github.com/intergalacticspacehighway))
24
+ - [iOS] Added the SwiftUI `minimumScaleFactor` modifier to let text shrink down to a given fraction of its size before truncating. ([#46740](https://github.com/expo/expo/pull/46740) by [@nishan](https://github.com/intergalacticspacehighway))
25
+ - [iOS][android] Added React Compiler-friendly `get()` / `set()` accessors to `useNativeState`, as an alternative to reading and writing `.value`. ([#46690](https://github.com/expo/expo/pull/46692) by [@nishan](https://github.com/intergalacticspacehighway))
26
+ - [jetpack-compose] Added `BasicTextField` component. ([#46442](https://github.com/expo/expo/pull/46442) by [@nishan](https://github.com/intergalacticspacehighway))
27
+ - [iOS] Added the SwiftUI `accessibilityInputLabels` modifier to set alternative spoken phrases Voice Control uses to refer to a view (for example "Hang up" for an "End" button). ([#46661](https://github.com/expo/expo/pull/46661) by [@ramonclaudio](https://github.com/ramonclaudio))
28
+
29
+ ## 56.0.16 — 2026-06-05
30
+
31
+ ### 🎉 New features
32
+
33
+ - [iOS] Added the SwiftUI `accessibilityHidden` modifier to hide decorative views from VoiceOver and other assistive technologies during element traversal. ([#46579](https://github.com/expo/expo/pull/46579) by [@ramonclaudio](https://github.com/ramonclaudio))
34
+ - [iOS] Added the SwiftUI `accessibilityIdentifier` modifier to set a stable identifier for UI testing tools such as XCUITest. ([#46556](https://github.com/expo/expo/pull/46556) by [@ramonclaudio](https://github.com/ramonclaudio))
35
+ - [iOS] Added the SwiftUI `dynamicTypeSize` modifier to set or constrain the Dynamic Type size within a view. Accepts a single size or a `{ min, max }` range, and cascades from `<Host>` to bound how far text scales at the largest accessibility sizes. ([#46540](https://github.com/expo/expo/pull/46540) by [@ramonclaudio](https://github.com/ramonclaudio))
36
+ - [iOS] Added `children` prop to `Label` component, allowing custom title views (e.g. a `VStack` with title and subtitle) while preserving native icon spacing and Dynamic Type icon sizing.
37
+ - [iOS] Add `buttonBorderShape` SwiftUI modifier, which reshapes a styled button (for example a `glass` button) while preserving its native press effect. ([#46348](https://github.com/expo/expo/pull/46348) by [@nishan](https://github.com/intergalacticspacehighway))
38
+ - [jetpack-compose] Added `NavigationBar` and `NavigationBarItem` components.
39
+ - [iOS] Added the SwiftUI `listRowSpacing` modifier. ([#46417](https://github.com/expo/expo/pull/46417) by [@qiyangdev](https://github.com/qiyangdev))
40
+ - [iOS] Added support for custom SF Symbols in the SwiftUI `Image` component. ([#46183](https://github.com/expo/expo/pull/46183) by [@cinques](https://github.com/cinques))
41
+ - [swift-ui] Added `<DisclosureGroup.Label>` for custom label style. ([#46288](https://github.com/expo/expo/pull/46288) by [@kudo](https://github.com/kudo))
42
+ - [universal] Added `<Collapsible.labelStyle>` for custom label style. ([#46288](https://github.com/expo/expo/pull/46288) by [@kudo](https://github.com/kudo))
43
+ - [jetpack-compose] Added `dropShadow` and `innerShadow` modifiers. ([#46364](https://github.com/expo/expo/discussions/46364) by [@duyanhv](https://github.com/duyanhv))
44
+
45
+ ### 🐛 Bug fixes
46
+
47
+ - [android] Fix React Native touchables (e.g. `Pressable`) on `community/pager-view` pages not responding, or triggering the wrong page's handler, after navigating between pages. ([#46778](https://github.com/expo/expo/pull/46778) by [@nishan](https://github.com/intergalacticspacehighway))
48
+ - [iOS] Fix `font`, `dynamicTypeSize`, and `resizable` modifiers not applying to the SwiftUI `Image`. SF Symbols scale with Dynamic Type when a `font` modifier sets a `textStyle`. ([#46714](https://github.com/expo/expo/pull/46714) by [@ramonclaudio](https://github.com/ramonclaudio))
49
+ - [android] Fix React Native `ScrollView` nested scrolling inside `BottomSheet`. ([#46544](https://github.com/expo/expo/pull/46544) by [@nishan](https://github.com/intergalacticspacehighway))
50
+ - [jetpack-compose] Fix layout shift when `Host` with `matchContents` is used inside React Native Screens. ([#46604](https://github.com/expo/expo/pull/46604) by [@nishan](https://github.com/intergalacticspacehighway))
51
+ - [iOS] Fix `PagerView` offsetting `ScrollView` by safe area insets. ([#46637](https://github.com/expo/expo/pull/46637) by [@nishan](https://github.com/intergalacticspacehighway))
52
+ - [iOS] Fix `SegmentedControl` being overlapped by sibling components inside a `ScrollView`, by disabling the `Host` safe area insets. ([#46575](https://github.com/expo/expo/pull/46575) by [@nishan](https://github.com/intergalacticspacehighway))
53
+ - [iOS] Fix the community `DateTimePicker`, `MenuView`, `Picker`, and `Slider` applying safe area insets (including keyboard avoidance) twice, by disabling the `Host` safe area insets (`ignoreSafeArea="all"`). ([#46721](https://github.com/expo/expo/pull/46721) by [@nishan](https://github.com/intergalacticspacehighway))
54
+ - [jetpack-compose] Fix `TextField` jiggling the surrounding content while its label animates on focus (a Material 3 expressive motion spring overshoot). ([#46568](https://github.com/expo/expo/pull/46568) by [@nishan](https://github.com/intergalacticspacehighway))
55
+ - [iOS] Fix `BottomSheet` animating open from the bottom-left corner in `fitToContents` mode. ([#46546](https://github.com/expo/expo/pull/46546) by [@nishan](https://github.com/intergalacticspacehighway))
56
+ - [iOS] Fix `TextField` and `SecureField` worklet `onTextChange` firing more than once per keystroke (when a change triggers reformatting) and on programmatic text updates. ([#46483](https://github.com/expo/expo/pull/46483) by [@nishan](https://github.com/intergalacticspacehighway))
57
+ - [iOS] Fix the `font` modifier dropping Dynamic Type scaling (`relativeTo`) and `weight` on concatenated `Text` runs. The Text-concatenation path now resolves the same `Font` as the view path. ([#46509](https://github.com/expo/expo/pull/46509) by [@ramonclaudio](https://github.com/ramonclaudio))
58
+ - [android] Fix universal `TextInput` ignoring `style` `backgroundColor` / `borderWidth` and not applying `textAlign` to the placeholder. ([#46441](https://github.com/expo/expo/pull/46441) by [@duyanhv](https://github.com/duyanhv))
59
+
13
60
  ## 56.0.15 — 2026-05-29
14
61
 
15
62
  _This version does not introduce any user-facing changes._
@@ -12,13 +12,13 @@ apply plugin: 'expo-module-gradle-plugin'
12
12
  apply plugin: 'org.jetbrains.kotlin.plugin.compose'
13
13
 
14
14
  group = 'expo.modules.ui'
15
- version = '56.0.15'
15
+ version = '56.0.17'
16
16
 
17
17
  android {
18
18
  namespace "expo.modules.ui"
19
19
  defaultConfig {
20
20
  versionCode 1
21
- versionName "56.0.15"
21
+ versionName "56.0.17"
22
22
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23
23
  }
24
24
  buildFeatures {
@@ -36,6 +36,15 @@ import expo.modules.ui.menu.DropdownMenuItemProps
36
36
  import expo.modules.kotlin.jni.worklets.Worklet
37
37
  import expo.modules.ui.state.ObservableState
38
38
  import expo.modules.ui.state.WorkletCallback
39
+ import expo.modules.ui.textfield.BasicTextFieldContent
40
+ import expo.modules.ui.textfield.BasicTextFieldProps
41
+ import expo.modules.ui.textfield.InnerTextFieldView
42
+ import expo.modules.ui.textfield.KeyboardActionEvent
43
+ import expo.modules.ui.textfield.PlaceholderView
44
+ import expo.modules.ui.textfield.TextFieldContent
45
+ import expo.modules.ui.textfield.TextFieldProps
46
+ import expo.modules.ui.textfield.TextFieldSelectionPayload
47
+ import expo.modules.ui.textfield.TextFieldValuePayload
39
48
  import expo.modules.ui.menu.ExposedDropdownMenuBoxContent
40
49
  import expo.modules.ui.menu.ExposedDropdownMenuBoxProps
41
50
  import expo.modules.ui.menu.ExposedDropdownMenuContent
@@ -109,8 +118,7 @@ class ExpoUIModule : Module() {
109
118
  //region Views use expo-modules-core DSL for uncommon features
110
119
 
111
120
  View(HostView::class) {
112
- // See ShadowNodeSyncFlush.kt for why onExpoUISyncFlush is needed.
113
- Events("onLayoutContent", "onExpoUISyncFlush")
121
+ Events("onLayoutContent")
114
122
 
115
123
  OnViewDidUpdateProps { view ->
116
124
  view.onViewDidUpdateProps()
@@ -147,14 +155,13 @@ class ExpoUIModule : Module() {
147
155
  colorScheme.toTokenMap()
148
156
  }
149
157
 
150
- View(RNHostView::class) {
151
- // See ShadowNodeSyncFlush.kt for why this internal phantom event is needed.
152
- Events("onExpoUISyncFlush")
153
- }
158
+ View(RNHostView::class)
154
159
 
155
160
  View(SlotView::class) {
156
161
  Events("onSlotEvent")
157
162
  }
163
+ View(InnerTextFieldView::class)
164
+ View(PlaceholderView::class)
158
165
  View(IconView::class)
159
166
  View(LazyColumnView::class)
160
167
  View(LazyRowView::class)
@@ -610,6 +617,20 @@ class ExpoUIModule : Module() {
610
617
  }
611
618
  }
612
619
 
620
+ ExpoUIView<NavigationBarProps>("NavigationBarView") {
621
+ Content { props ->
622
+ NavigationBarContent(props)
623
+ }
624
+ }
625
+
626
+ ExpoUIView<NavigationBarItemProps>("NavigationBarItemView") {
627
+ val onButtonPressed by Event<Unit>()
628
+
629
+ Content { props ->
630
+ NavigationBarItemContent(props) { onButtonPressed(Unit) }
631
+ }
632
+ }
633
+
613
634
  ExpoUIView<SpacerProps>("SpacerView") {
614
635
  Content { props ->
615
636
  SpacerContent(props)
@@ -683,6 +704,33 @@ class ExpoUIModule : Module() {
683
704
  }
684
705
  }
685
706
 
707
+ ExpoUIView<BasicTextFieldProps>("BasicTextFieldView") {
708
+ val setText by AsyncFunction<String>()
709
+ val setSelection by AsyncFunction<Int, Int>()
710
+ val clear by AsyncFunction()
711
+ val focus by AsyncFunction()
712
+ val blur by AsyncFunction()
713
+ val onValueChange by Event<TextFieldValuePayload>()
714
+ val onFocusChanged by Event<GenericEventPayload1<Boolean>>()
715
+ val onKeyboardAction by Event<KeyboardActionEvent>()
716
+ val onSelectionChange by Event<TextFieldSelectionPayload>()
717
+
718
+ Content { props ->
719
+ BasicTextFieldContent(
720
+ props,
721
+ setText,
722
+ setSelection,
723
+ clear,
724
+ focus,
725
+ blur,
726
+ onValueChanged = { onValueChange(it) },
727
+ onFocusChange = { onFocusChanged(it) },
728
+ onKeyboardActionTriggered = { onKeyboardAction(it) },
729
+ onSelectionChanged = { onSelectionChange(it) }
730
+ )
731
+ }
732
+ }
733
+
686
734
  ExpoUIView<RadioButtonProps>("RadioButtonView") {
687
735
  val onButtonPressed by Event<Unit>()
688
736
 
@@ -193,7 +193,6 @@ internal class HostView(context: Context, appContext: AppContext) :
193
193
  if (constraints.maxWidth == 0) widthDp else Double.NaN,
194
194
  if (constraints.maxHeight == 0) heightDp else Double.NaN
195
195
  )
196
- flushPendingStateUpdates()
197
196
  }
198
197
  }
199
198
 
@@ -222,7 +221,6 @@ internal class HostView(context: Context, appContext: AppContext) :
222
221
  val styleWidth = if (matchContentsHorizontal == true && width > 0) width else null
223
222
  val styleHeight = if (matchContentsVertical == true && height > 0) height else null
224
223
  shadowNodeProxy.setStyleSize(styleWidth?.toDouble(), styleHeight?.toDouble())
225
- flushPendingStateUpdates()
226
224
  }
227
225
 
228
226
  onLayoutContent(LayoutContentEvent(width.toDouble(), height.toDouble()))
@@ -47,6 +47,8 @@ import androidx.compose.ui.Modifier
47
47
  import androidx.compose.ui.draw.alpha
48
48
  import androidx.compose.ui.draw.blur
49
49
  import androidx.compose.ui.draw.clip
50
+ import androidx.compose.ui.draw.dropShadow
51
+ import androidx.compose.ui.draw.innerShadow
50
52
  import androidx.compose.ui.draw.rotate
51
53
  import androidx.compose.ui.draw.shadow
52
54
  import androidx.compose.ui.graphics.CompositingStrategy
@@ -54,12 +56,16 @@ import androidx.compose.ui.graphics.RectangleShape
54
56
  import androidx.compose.ui.graphics.Shape
55
57
  import androidx.compose.ui.graphics.TransformOrigin
56
58
  import androidx.compose.ui.graphics.graphicsLayer
59
+ import androidx.compose.ui.graphics.shadow.Shadow
60
+ import androidx.compose.ui.layout.onGloballyPositioned
57
61
  import androidx.compose.ui.layout.onSizeChanged
58
62
  import androidx.compose.ui.layout.onVisibilityChanged
63
+ import androidx.compose.ui.layout.positionInWindow
59
64
  import androidx.compose.ui.platform.LocalDensity
60
65
  import androidx.compose.ui.semantics.Role
61
66
  import androidx.compose.ui.semantics.contentType
62
67
  import androidx.compose.ui.semantics.semantics
68
+ import androidx.compose.ui.unit.DpOffset
63
69
  import androidx.compose.ui.unit.dp
64
70
  import androidx.compose.ui.zIndex
65
71
  import expo.modules.kotlin.AppContext
@@ -181,6 +187,17 @@ internal data class ShadowParams(
181
187
  @Field val elevation: Int = 0
182
188
  ) : Record
183
189
 
190
+ @OptimizedRecord
191
+ internal data class ShadowGeometryParams(
192
+ @Field val shape: BuiltinShapeRecord? = null,
193
+ @Field val radius: Float = 0f,
194
+ @Field val spread: Float = 0f,
195
+ @Field val color: Color? = null,
196
+ @Field val offsetX: Float = 0f,
197
+ @Field val offsetY: Float = 0f,
198
+ @Field val alpha: Float = 1f
199
+ ) : Record
200
+
184
201
  @OptimizedRecord
185
202
  internal data class AlphaParams(
186
203
  @Field val alpha: Float = 1.0f
@@ -502,6 +519,36 @@ object ModifierRegistry {
502
519
  Modifier.shadow(params.elevation.dp)
503
520
  }
504
521
 
522
+ register("dropShadow") { map, _, _, _ ->
523
+ val params = recordFromMap<ShadowGeometryParams>(map)
524
+ val shape = params.shape?.let { resolveShape(it) } ?: RectangleShape
525
+ Modifier.dropShadow(
526
+ shape,
527
+ Shadow(
528
+ radius = params.radius.dp,
529
+ spread = params.spread.dp,
530
+ color = params.color.composeOrNull ?: androidx.compose.ui.graphics.Color.Black,
531
+ offset = DpOffset(params.offsetX.dp, params.offsetY.dp),
532
+ alpha = params.alpha
533
+ )
534
+ )
535
+ }
536
+
537
+ register("innerShadow") { map, _, _, _ ->
538
+ val params = recordFromMap<ShadowGeometryParams>(map)
539
+ val shape = params.shape?.let { resolveShape(it) } ?: RectangleShape
540
+ Modifier.innerShadow(
541
+ shape,
542
+ Shadow(
543
+ radius = params.radius.dp,
544
+ spread = params.spread.dp,
545
+ color = params.color.composeOrNull ?: androidx.compose.ui.graphics.Color.Black,
546
+ offset = DpOffset(params.offsetX.dp, params.offsetY.dp),
547
+ alpha = params.alpha
548
+ )
549
+ )
550
+ }
551
+
505
552
  register("alpha") { map, _, _, _ ->
506
553
  val params = recordFromMap<AlphaParams>(map)
507
554
  Modifier.alpha(params.alpha)
@@ -647,6 +694,24 @@ object ModifierRegistry {
647
694
  }
648
695
  }
649
696
 
697
+ register("onGloballyPositioned") { _, _, _, eventDispatcher ->
698
+ val density = LocalDensity.current
699
+ Modifier.onGloballyPositioned { coordinates ->
700
+ val position = coordinates.positionInWindow()
701
+ with(density) {
702
+ eventDispatcher(
703
+ "onGloballyPositioned",
704
+ mapOf(
705
+ "x" to position.x.toDp().value,
706
+ "y" to position.y.toDp().value,
707
+ "width" to coordinates.size.width.toDp().value,
708
+ "height" to coordinates.size.height.toDp().value
709
+ )
710
+ )
711
+ }
712
+ }
713
+ }
714
+
650
715
  register("clickable") { map, _, _, eventDispatcher ->
651
716
  val params = recordFromMap<ClickableParams>(map)
652
717
  if (params.indication) {
@@ -0,0 +1,95 @@
1
+ package expo.modules.ui
2
+
3
+ import android.graphics.Color
4
+ import androidx.compose.material3.NavigationBar
5
+ import androidx.compose.material3.NavigationBarDefaults
6
+ import androidx.compose.material3.NavigationBarItem
7
+ import androidx.compose.material3.NavigationBarItemDefaults
8
+ import androidx.compose.material3.contentColorFor
9
+ import androidx.compose.runtime.Composable
10
+ import androidx.compose.ui.graphics.Color as ComposeColor
11
+ import androidx.compose.ui.unit.dp
12
+ import expo.modules.kotlin.records.Field
13
+ import expo.modules.kotlin.records.Record
14
+ import expo.modules.kotlin.types.OptimizedRecord
15
+ import expo.modules.kotlin.views.ComposeProps
16
+ import expo.modules.kotlin.views.FunctionalComposableScope
17
+ import expo.modules.kotlin.views.OptimizedComposeProps
18
+
19
+ @OptimizedRecord
20
+ data class NavigationBarItemColors(
21
+ @Field val selectedIconColor: Color? = null,
22
+ @Field val selectedTextColor: Color? = null,
23
+ @Field val selectedIndicatorColor: Color? = null,
24
+ @Field val unselectedIconColor: Color? = null,
25
+ @Field val unselectedTextColor: Color? = null,
26
+ @Field val disabledIconColor: Color? = null,
27
+ @Field val disabledTextColor: Color? = null
28
+ ) : Record
29
+
30
+ @OptimizedComposeProps
31
+ data class NavigationBarProps(
32
+ val containerColor: Color? = null,
33
+ val contentColor: Color? = null,
34
+ val tonalElevation: Float? = null,
35
+ val modifiers: ModifierList = emptyList()
36
+ ) : ComposeProps
37
+
38
+ @OptimizedComposeProps
39
+ data class NavigationBarItemProps(
40
+ val selected: Boolean = false,
41
+ val enabled: Boolean = true,
42
+ val alwaysShowLabel: Boolean = true,
43
+ val colors: NavigationBarItemColors = NavigationBarItemColors(),
44
+ val modifiers: ModifierList = emptyList()
45
+ ) : ComposeProps
46
+
47
+ @Composable
48
+ fun FunctionalComposableScope.NavigationBarContent(props: NavigationBarProps) {
49
+ val resolvedContainerColor = props.containerColor.composeOrNull ?: NavigationBarDefaults.containerColor
50
+ val modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
51
+
52
+ NavigationBar(
53
+ modifier = modifier,
54
+ containerColor = resolvedContainerColor,
55
+ contentColor = props.contentColor.composeOrNull ?: contentColorFor(resolvedContainerColor),
56
+ tonalElevation = props.tonalElevation?.dp ?: NavigationBarDefaults.Elevation
57
+ ) {
58
+ Children(UIComposableScope(rowScope = this@NavigationBar), filter = { !isSlotView(it) })
59
+ }
60
+ }
61
+
62
+ @Composable
63
+ fun FunctionalComposableScope.NavigationBarItemContent(
64
+ props: NavigationBarItemProps,
65
+ onClick: () -> Unit
66
+ ) {
67
+ val iconSlotView = findChildSlotView(view, "icon")
68
+ val labelSlotView = findChildSlotView(view, "label")
69
+ val modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
70
+ val label: (@Composable () -> Unit)? = labelSlotView?.let { slot -> { slot.renderSlot() } }
71
+ val rowScope = composableScope.rowScope ?: return
72
+
73
+ with(rowScope) {
74
+ NavigationBarItem(
75
+ selected = props.selected,
76
+ onClick = onClick,
77
+ icon = {
78
+ iconSlotView?.renderSlot()
79
+ },
80
+ modifier = modifier,
81
+ enabled = props.enabled,
82
+ label = label,
83
+ alwaysShowLabel = props.alwaysShowLabel,
84
+ colors = NavigationBarItemDefaults.colors(
85
+ selectedIconColor = props.colors.selectedIconColor.composeOrNull ?: ComposeColor.Unspecified,
86
+ selectedTextColor = props.colors.selectedTextColor.composeOrNull ?: ComposeColor.Unspecified,
87
+ indicatorColor = props.colors.selectedIndicatorColor.composeOrNull ?: ComposeColor.Unspecified,
88
+ unselectedIconColor = props.colors.unselectedIconColor.composeOrNull ?: ComposeColor.Unspecified,
89
+ unselectedTextColor = props.colors.unselectedTextColor.composeOrNull ?: ComposeColor.Unspecified,
90
+ disabledIconColor = props.colors.disabledIconColor.composeOrNull ?: ComposeColor.Unspecified,
91
+ disabledTextColor = props.colors.disabledTextColor.composeOrNull ?: ComposeColor.Unspecified
92
+ )
93
+ )
94
+ }
95
+ }
@@ -19,6 +19,9 @@ import androidx.compose.ui.layout.onSizeChanged
19
19
  import androidx.compose.ui.platform.LocalDensity
20
20
  import androidx.compose.ui.unit.IntSize
21
21
  import androidx.compose.ui.viewinterop.AndroidView
22
+ import androidx.core.view.NestedScrollingChild3
23
+ import androidx.core.view.NestedScrollingChildHelper
24
+ import androidx.core.view.ViewCompat
22
25
  import com.facebook.react.bridge.ReactContext
23
26
  import com.facebook.react.common.annotations.UnstableReactNativeAPI
24
27
  import com.facebook.react.config.ReactFeatureFlags
@@ -158,7 +161,6 @@ internal class RNHostView(context: Context, appContext: AppContext) :
158
161
  size.width.toDp().value.toDouble(),
159
162
  size.height.toDp().value.toDouble()
160
163
  )
161
- flushPendingStateUpdates()
162
164
  }
163
165
  }
164
166
  }
@@ -168,13 +170,30 @@ internal class RNHostView(context: Context, appContext: AppContext) :
168
170
  * A thin FrameLayout that intercepts touch events and dispatches them to JS via
169
171
  * JSTouchDispatcher/JSPointerDispatcher, replicating the pattern from React Native's
170
172
  * DialogRootViewGroup in ReactModalHostView.
173
+ * Implements NestedScrollingChild3 to forward scroll events up to the parent Compose view, because Compose only listens for NestedScrollingChild3 nested-scroll events.
171
174
  */
172
175
  private class TouchDispatchingRootViewGroup(
173
176
  context: Context
174
- ) : FrameLayout(context), RootView {
177
+ ) : FrameLayout(context), RootView, NestedScrollingChild3 {
175
178
  private val jsTouchDispatcher = JSTouchDispatcher(this)
176
179
  private var jsPointerDispatcher: JSPointerDispatcher? = null
177
180
 
181
+ // The "child face": this helper does the real work of finding the nearest scrolling-aware
182
+ // ancestor (Compose, here) and forwarding our scroll offers to it.
183
+ private val childHelper = NestedScrollingChildHelper(this)
184
+
185
+ // How far the sheet has slid this view on-screen since the gesture began. Used to keep the
186
+ // FlatList's touch coordinates coherent while the view moves under the finger.
187
+ private val gestureStartLocation = IntArray(2)
188
+ private val currentLocation = IntArray(2)
189
+ private var trackingGestureOffset = false
190
+
191
+ // True if the sheet consumed scroll on the most recent drag frame; drives the settle decision.
192
+ private var sheetMovingOnLastDragFrame = false
193
+
194
+ // True once a fling was dispatched this gesture, so the gentle-release settle doesn't double-fire.
195
+ private var flingHandledThisGesture = false
196
+
178
197
  var eventDispatcher: EventDispatcher? = null
179
198
 
180
199
  private val reactContext: ThemedReactContext
@@ -184,6 +203,7 @@ private class TouchDispatchingRootViewGroup(
184
203
  if (ReactFeatureFlags.dispatchPointerEvents) {
185
204
  jsPointerDispatcher = JSPointerDispatcher(this)
186
205
  }
206
+ childHelper.isNestedScrollingEnabled = true
187
207
  }
188
208
 
189
209
  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
@@ -200,6 +220,38 @@ private class TouchDispatchingRootViewGroup(
200
220
  // and we must not override those values.
201
221
  }
202
222
 
223
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
224
+ if (ev.actionMasked == MotionEvent.ACTION_DOWN) {
225
+ // dispatchTouchEvent is the true start of every gesture, so reset all per-gesture state here.
226
+ getLocationInWindow(gestureStartLocation)
227
+ trackingGestureOffset = true
228
+ sheetMovingOnLastDragFrame = false
229
+ flingHandledThisGesture = false
230
+ }
231
+
232
+ // While a nested scroll is in flight the sheet may be sliding this whole view up/down. Re-express
233
+ // every event as if the view hadn't moved, so the FlatList's own scroll tracking stays coherent.
234
+ val handled = if (trackingGestureOffset && hasNestedScrollingParent()) {
235
+ getLocationInWindow(currentLocation)
236
+ val dy = currentLocation[1] - gestureStartLocation[1]
237
+ if (dy != 0) {
238
+ ev.offsetLocation(0f, dy.toFloat())
239
+ val result = super.dispatchTouchEvent(ev)
240
+ ev.offsetLocation(0f, -dy.toFloat())
241
+ result
242
+ } else {
243
+ super.dispatchTouchEvent(ev)
244
+ }
245
+ } else {
246
+ super.dispatchTouchEvent(ev)
247
+ }
248
+
249
+ if (ev.actionMasked == MotionEvent.ACTION_UP || ev.actionMasked == MotionEvent.ACTION_CANCEL) {
250
+ trackingGestureOffset = false
251
+ }
252
+ return handled
253
+ }
254
+
203
255
  override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
204
256
  eventDispatcher?.let { dispatcher ->
205
257
  jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
@@ -241,12 +293,136 @@ private class TouchDispatchingRootViewGroup(
241
293
  jsPointerDispatcher?.onChildEndedNativeGesture()
242
294
  }
243
295
 
296
+ override fun handleException(t: Throwable) {
297
+ reactContext.reactApplicationContext.handleException(RuntimeException(t))
298
+ }
299
+
244
300
  override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
245
- // No-op - override to still receive events in onInterceptTouchEvent
246
- // even when a child view disallows interception
301
+ // Forward the request up so Compose learns the list claimed the gesture and its own sheet-drag
302
+ // yields. But don't call super: setting our own FLAG_DISALLOW_INTERCEPT would skip
303
+ // onInterceptTouchEvent, which must keep firing to dispatch touches to JS (the reason #43716
304
+ // added this override).
305
+ parent?.requestDisallowInterceptTouchEvent(disallowIntercept)
247
306
  }
248
307
 
249
- override fun handleException(t: Throwable) {
250
- reactContext.reactApplicationContext.handleException(RuntimeException(t))
308
+ // --- Parent face: catch the FlatList's scroll offers and relay them up via the child face. ---
309
+ override fun onStartNestedScroll(child: View, target: View, axes: Int): Boolean =
310
+ axes and ViewCompat.SCROLL_AXIS_VERTICAL != 0
311
+
312
+ override fun onNestedScrollAccepted(child: View, target: View, axes: Int) {
313
+ super.onNestedScrollAccepted(child, target, axes)
314
+ startNestedScroll(axes)
251
315
  }
316
+
317
+ override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) {
318
+ // Expand path: offer the delta to the sheet (above us) before the list scrolls with the rest.
319
+ dispatchNestedPreScroll(dx, dy, consumed, null)
320
+ // Did the sheet move this frame? consumed[1] is what it consumed in y axis.
321
+ sheetMovingOnLastDragFrame = consumed[1] != 0
322
+ }
323
+
324
+ override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
325
+ // Collapse path: after the list scrolled what it could, hand the leftover up to the sheet.
326
+ // Use the (…, type, consumed) variant so we can read how much the sheet ate (consumed[1]).
327
+ val consumed = IntArray(2)
328
+ dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null, ViewCompat.TYPE_TOUCH, consumed)
329
+ if (consumed[1] != 0) sheetMovingOnLastDragFrame = true
330
+ }
331
+
332
+ override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
333
+ // A real fling is being dispatched, so its settle is already in motion; note that so the
334
+ // gentle-release fallback in onStopNestedScroll doesn't add a second, redundant settle.
335
+ flingHandledThisGesture = true
336
+ val composeConsumed = dispatchNestedPreFling(velocityX, velocityY)
337
+ // RN's ScrollView wants a synchronous yes/no, but Compose's pre-fling is async (it returns false
338
+ // now and settles later). So decide here: if the sheet was mid-move and this is an up-flick
339
+ // (velocityY > 0), swallow the list's fling so the sheet finishes expanding. A down-flick passes
340
+ // through so it can still settle/collapse.
341
+ return composeConsumed || (sheetMovingOnLastDragFrame && velocityY > 0)
342
+ }
343
+
344
+ override fun onNestedFling(target: View, velocityX: Float, velocityY: Float, consumed: Boolean): Boolean =
345
+ // Post-fling: hand the leftover flick up so the sheet can fling to its next anchor.
346
+ dispatchNestedFling(velocityX, velocityY, consumed)
347
+
348
+ override fun onStopNestedScroll(target: View) {
349
+ // Must run BEFORE stopNestedScroll() so Compose is still our parent and can receive the fling.
350
+ settleSheetIfNoFling()
351
+ super.onStopNestedScroll(target)
352
+ stopNestedScroll()
353
+ }
354
+
355
+ // A slow (sub-threshold) release never flings, so the sheet would hang where it was dragged. If the
356
+ // sheet moved this gesture and no real fling settled it, dispatch a zero-velocity fling so the
357
+ // holder snaps it to the nearest anchor.
358
+ private fun settleSheetIfNoFling() {
359
+ if (sheetMovingOnLastDragFrame && !flingHandledThisGesture) {
360
+ flingHandledThisGesture = true
361
+ dispatchNestedFling(0f, 0f, false)
362
+ }
363
+ }
364
+
365
+ // --- Child face: the wrapper's upstream voice. The parent hooks above relay through these. ---
366
+ // So we listen to ViewGroup nested scroll methods and call below methods from them,
367
+ // which essentially converts regular Nested scrolling methods to NestedScrollingChild3.
368
+ override fun setNestedScrollingEnabled(enabled: Boolean) {
369
+ childHelper.isNestedScrollingEnabled = enabled
370
+ }
371
+ override fun isNestedScrollingEnabled(): Boolean = childHelper.isNestedScrollingEnabled
372
+ override fun startNestedScroll(axes: Int): Boolean = childHelper.startNestedScroll(axes)
373
+ override fun startNestedScroll(axes: Int, type: Int): Boolean = childHelper.startNestedScroll(axes, type)
374
+ override fun stopNestedScroll() = childHelper.stopNestedScroll()
375
+ override fun stopNestedScroll(type: Int) = childHelper.stopNestedScroll(type)
376
+ override fun hasNestedScrollingParent(): Boolean = childHelper.hasNestedScrollingParent()
377
+ override fun hasNestedScrollingParent(type: Int): Boolean = childHelper.hasNestedScrollingParent(type)
378
+
379
+ override fun dispatchNestedScroll(
380
+ dxConsumed: Int,
381
+ dyConsumed: Int,
382
+ dxUnconsumed: Int,
383
+ dyUnconsumed: Int,
384
+ offsetInWindow: IntArray?
385
+ ): Boolean = childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
386
+
387
+ override fun dispatchNestedScroll(
388
+ dxConsumed: Int,
389
+ dyConsumed: Int,
390
+ dxUnconsumed: Int,
391
+ dyUnconsumed: Int,
392
+ offsetInWindow: IntArray?,
393
+ type: Int
394
+ ): Boolean = childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type)
395
+
396
+ override fun dispatchNestedScroll(
397
+ dxConsumed: Int,
398
+ dyConsumed: Int,
399
+ dxUnconsumed: Int,
400
+ dyUnconsumed: Int,
401
+ offsetInWindow: IntArray?,
402
+ type: Int,
403
+ consumed: IntArray
404
+ ) {
405
+ childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed)
406
+ }
407
+
408
+ override fun dispatchNestedPreScroll(
409
+ dx: Int,
410
+ dy: Int,
411
+ consumed: IntArray?,
412
+ offsetInWindow: IntArray?
413
+ ): Boolean = childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
414
+
415
+ override fun dispatchNestedPreScroll(
416
+ dx: Int,
417
+ dy: Int,
418
+ consumed: IntArray?,
419
+ offsetInWindow: IntArray?,
420
+ type: Int
421
+ ): Boolean = childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type)
422
+
423
+ override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean): Boolean =
424
+ childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
425
+
426
+ override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float): Boolean =
427
+ childHelper.dispatchNestedPreFling(velocityX, velocityY)
252
428
  }