1-
21/**
32 * Copyright (c) 2015-present, Facebook, Inc.
4- * All rights reserved.
53 *
6- * This source code is licensed under the BSD-style license found in the
7- * LICENSE file in the root directory of this source tree. An additional grant
8- * of patent rights can be found in the PATENTS file in the same directory.
4+ * This source code is licensed under the MIT license found in the
5+ * LICENSE file in the root directory of this source tree.
96 */
107
118package com .rnnestedscrollview ;
129
13- import javax .annotation .Nullable ;
14-
15- import java .lang .reflect .Field ;
16-
10+ import android .annotation .TargetApi ;
1711import android .graphics .Canvas ;
1812import android .graphics .Color ;
1913import android .graphics .Rect ;
2014import android .graphics .drawable .ColorDrawable ;
2115import android .graphics .drawable .Drawable ;
2216import android .support .v4 .widget .NestedScrollView ;
17+ import android .support .v4 .view .ViewCompat ;
2318import android .util .Log ;
2419import android .view .MotionEvent ;
2520import android .view .View ;
2621import android .view .ViewGroup ;
2722import android .widget .OverScroller ;
28- import android .widget .ScrollView ;
29-
23+ import com .facebook .infer .annotation .Assertions ;
3024import com .facebook .react .bridge .ReactContext ;
3125import com .facebook .react .common .ReactConstants ;
3226import com .facebook .react .views .scroll .FpsListener ;
3327import com .facebook .react .views .scroll .OnScrollDispatchHelper ;
3428import com .facebook .react .views .scroll .VelocityHelper ;
29+ import com .facebook .react .views .scroll .ReactScrollViewHelper ;
3530import com .facebook .react .uimanager .MeasureSpecAssertions ;
36- import com .facebook .react .uimanager .events .NativeGestureUtil ;
3731import com .facebook .react .uimanager .ReactClippingViewGroup ;
3832import com .facebook .react .uimanager .ReactClippingViewGroupHelper ;
39- import com .facebook .infer . annotation . Assertions ;
33+ import com .facebook .react . uimanager . events . NativeGestureUtil ;
4034import com .facebook .react .views .view .ReactViewBackgroundManager ;
35+ import java .lang .reflect .Field ;
36+ import javax .annotation .Nullable ;
4137
4238/**
43- * Forked from https://github.com/facebook/react-native/blob/0.45 -stable/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java
39+ * Forked from https://github.com/facebook/react-native/blob/0.56 -stable/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java
4440 *
4541 * A simple subclass of ScrollView that doesn't dispatch measure and layout to its children and has
4642 * a scroll listener to send scroll events to JS.
4743 *
4844 * <p>ReactNestedScrollView only supports vertical scrolling. For horizontal scrolling,
4945 * use {@link ReactHorizontalScrollView}.
5046 */
47+ @ TargetApi (11 )
5148public class ReactNestedScrollView extends NestedScrollView implements ReactClippingViewGroup , ViewGroup .OnHierarchyChangeListener , View .OnLayoutChangeListener {
5249
53- private static Field sScrollerField ;
50+ private static @ Nullable Field sScrollerField ;
5451 private static boolean sTriedToGetScrollerField = false ;
5552
5653 private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper ();
57- private final OverScroller mScroller ;
54+ private final @ Nullable OverScroller mScroller ;
5855 private final VelocityHelper mVelocityHelper = new VelocityHelper ();
5956
6057 private @ Nullable Rect mClippingRect ;
@@ -80,6 +77,15 @@ public ReactNestedScrollView(ReactContext context, @Nullable FpsListener fpsList
8077 mFpsListener = fpsListener ;
8178 mReactBackgroundManager = new ReactViewBackgroundManager (this );
8279
80+ mScroller = getOverScrollerFromParent ();
81+ setOnHierarchyChangeListener (this );
82+ setScrollBarStyle (SCROLLBARS_OUTSIDE_OVERLAY );
83+ }
84+
85+ @ Nullable
86+ private OverScroller getOverScrollerFromParent () {
87+ OverScroller scroller ;
88+
8389 if (!sTriedToGetScrollerField ) {
8490 sTriedToGetScrollerField = true ;
8591 try {
@@ -95,32 +101,31 @@ public ReactNestedScrollView(ReactContext context, @Nullable FpsListener fpsList
95101
96102 if (sScrollerField != null ) {
97103 try {
98- Object scroller = sScrollerField .get (this );
99- if (scroller instanceof OverScroller ) {
100- mScroller = (OverScroller ) scroller ;
104+ Object scrollerValue = sScrollerField .get (this );
105+ if (scrollerValue instanceof OverScroller ) {
106+ scroller = (OverScroller ) scrollerValue ;
101107 } else {
102108 Log .w (
103109 ReactConstants .TAG ,
104110 "Failed to cast mScroller field in ScrollView (probably due to OEM changes to AOSP)! " +
105111 "This app will exhibit the bounce-back scrolling bug :(" );
106- mScroller = null ;
112+ scroller = null ;
107113 }
108114 } catch (IllegalAccessException e ) {
109115 throw new RuntimeException ("Failed to get mScroller from ScrollView!" , e );
110116 }
111117 } else {
112- mScroller = null ;
118+ scroller = null ;
113119 }
114120
115- setOnHierarchyChangeListener (this );
116- setScrollBarStyle (SCROLLBARS_OUTSIDE_OVERLAY );
121+ return scroller ;
117122 }
118123
119124 public void setSendMomentumEvents (boolean sendMomentumEvents ) {
120125 mSendMomentumEvents = sendMomentumEvents ;
121126 }
122127
123- public void setScrollPerfTag (String scrollPerfTag ) {
128+ public void setScrollPerfTag (@ Nullable String scrollPerfTag ) {
124129 mScrollPerfTag = scrollPerfTag ;
125130 }
126131
@@ -177,7 +182,7 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) {
177182 mDoneFlinging = false ;
178183 }
179184
180- ReactNestedScrollViewHelper .emitScrollEvent (
185+ ReactScrollViewHelper .emitScrollEvent (
181186 this ,
182187 mOnScrollDispatchHelper .getXFlingVelocity (),
183188 mOnScrollDispatchHelper .getYFlingVelocity ());
@@ -190,12 +195,19 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
190195 return false ;
191196 }
192197
193- if (super .onInterceptTouchEvent (ev )) {
194- NativeGestureUtil .notifyNativeGestureStarted (this , ev );
195- ReactNestedScrollViewHelper .emitScrollBeginDragEvent (this );
196- mDragging = true ;
197- enableFpsListener ();
198- return true ;
198+ try {
199+ if (super .onInterceptTouchEvent (ev )) {
200+ NativeGestureUtil .notifyNativeGestureStarted (this , ev );
201+ ReactScrollViewHelper .emitScrollBeginDragEvent (this );
202+ mDragging = true ;
203+ enableFpsListener ();
204+ return true ;
205+ }
206+ } catch (IllegalArgumentException e ) {
207+ // Log and ignore the error. This seems to be a bug in the android SDK and
208+ // this is the commonly accepted workaround.
209+ // https://tinyurl.com/mw6qkod (Stack Overflow)
210+ Log .w (ReactConstants .TAG , "Error intercepting touch event." , e );
199211 }
200212
201213 return false ;
@@ -210,7 +222,7 @@ public boolean onTouchEvent(MotionEvent ev) {
210222 mVelocityHelper .calculateVelocity (ev );
211223 int action = ev .getAction () & MotionEvent .ACTION_MASK ;
212224 if (action == MotionEvent .ACTION_UP && mDragging ) {
213- ReactNestedScrollViewHelper .emitScrollEndDragEvent (
225+ ReactScrollViewHelper .emitScrollEndDragEvent (
214226 this ,
215227 mVelocityHelper .getXVelocity (),
216228 mVelocityHelper .getYVelocity ());
@@ -280,7 +292,7 @@ public void fling(int velocityY) {
280292 0 ,
281293 scrollWindowHeight / 2 );
282294
283- postInvalidateOnAnimation ();
295+ ViewCompat . postInvalidateOnAnimation (this );
284296
285297 // END FB SCROLLVIEW CHANGE
286298 } else {
@@ -290,21 +302,24 @@ public void fling(int velocityY) {
290302 if (mSendMomentumEvents || isScrollPerfLoggingEnabled ()) {
291303 mFlinging = true ;
292304 enableFpsListener ();
293- ReactNestedScrollViewHelper .emitScrollMomentumBeginEvent (this );
305+ ReactScrollViewHelper .emitScrollMomentumBeginEvent (this , 0 , velocityY );
294306 Runnable r = new Runnable () {
295307 @ Override
296308 public void run () {
297309 if (mDoneFlinging ) {
298310 mFlinging = false ;
299311 disableFpsListener ();
300- ReactNestedScrollViewHelper .emitScrollMomentumEndEvent (ReactNestedScrollView .this );
312+ ReactScrollViewHelper .emitScrollMomentumEndEvent (ReactNestedScrollView .this );
301313 } else {
302314 mDoneFlinging = true ;
303- ReactNestedScrollView .this .postOnAnimationDelayed (this , ReactNestedScrollViewHelper .MOMENTUM_DELAY );
315+ ViewCompat .postOnAnimationDelayed (
316+ ReactNestedScrollView .this ,
317+ this ,
318+ ReactScrollViewHelper .MOMENTUM_DELAY );
304319 }
305320 }
306321 };
307- postOnAnimationDelayed (r , ReactNestedScrollViewHelper .MOMENTUM_DELAY );
322+ ViewCompat . postOnAnimationDelayed (this , r , ReactScrollViewHelper .MOMENTUM_DELAY );
308323 }
309324 }
310325
0 commit comments