@@ -103,6 +103,46 @@ function replaceCopyrightHeader(content, sourceFile) {
103103 return content . replace ( COPYRIGHT_HEADER_PATTERN , generatedHeader ( sourceFile ) ) ;
104104}
105105
106+ /**
107+ * Keep NestedScrollView in charge of the non-paging fling lifecycle.
108+ *
109+ * ReactScrollView intentionally drives its reflected OverScroller directly. For
110+ * the generated AndroidX variant, doing the same bypasses NestedScrollView.fling()
111+ * and therefore its TYPE_NON_TOUCH nested-scroll lifecycle.
112+ */
113+ function replaceNestedScrollViewFling ( content ) {
114+ const scrollerFlingBranch = ` } else if (scroller != null) {
115+ val scrollWindowHeight = height - paddingBottom - paddingTop
116+ scroller.fling(
117+ scrollX, // startX
118+ scrollY, // startY
119+ 0, // velocityX
120+ correctedVelocityY, // velocityY
121+ 0, // minX
122+ 0, // maxX
123+ 0, // minY
124+ Int.MAX_VALUE, // maxY
125+ 0, // overX
126+ scrollWindowHeight / 2, // overY
127+ )
128+ postInvalidateOnAnimation()
129+ } else {
130+ super.fling(correctedVelocityY)
131+ }` ;
132+ const nestedScrollFlingBranch = ` } else {
133+ super.fling(correctedVelocityY)
134+ }` ;
135+ const occurrenceCount = content . split ( scrollerFlingBranch ) . length - 1 ;
136+
137+ if ( occurrenceCount !== 1 ) {
138+ throw new Error (
139+ `Expected exactly one ReactScrollView fling scroller branch; found ${ occurrenceCount } .` ,
140+ ) ;
141+ }
142+
143+ return content . replace ( scrollerFlingBranch , nestedScrollFlingBranch ) ;
144+ }
145+
106146function removePublicModifiers ( content ) {
107147 return content . replace ( KOTLIN_DECLARATION_PATTERN , '' ) ;
108148}
@@ -128,6 +168,10 @@ function transformScrollView(content) {
128168 // Replace ReactScrollView with ReactNestedScrollView
129169 content = replaceClassNames ( content ) ;
130170
171+ // Unlike android.widget.ScrollView, AndroidX NestedScrollView owns the nested-scroll
172+ // lifecycle of a fling. Preserve that lifecycle in the generated variant.
173+ content = replaceNestedScrollViewFling ( content ) ;
174+
131175 // Make the class internal to keep it out of the public API
132176 content = content . replace (
133177 'public open class ReactNestedScrollView' ,
0 commit comments