1818
1919import java .util .HashMap ;
2020
21- public class MvcpScrollViewManagerModule extends ReactContextBaseJavaModule {
21+ /**
22+ * Holds the required values for layoutUpdateListener.
23+ */
24+ class ScrollViewUIHolders {
25+ static int prevFirstVisibleTop = 0 ;
26+ static View firstVisibleView = null ;
27+ static int currentScrollY = 0 ;
28+ }
2229
30+ public class MvcpScrollViewManagerModule extends ReactContextBaseJavaModule {
2331 private final ReactApplicationContext reactContext ;
2432 private HashMap <Integer , UIManagerModuleListener > uiManagerModuleListeners ;
2533
@@ -48,60 +56,51 @@ public void run() {
4856 try {
4957 final ReactScrollView scrollView = (ReactScrollView )uiManagerModule .resolveView (viewTag );
5058 final UIManagerModuleListener uiManagerModuleListener = new UIManagerModuleListener () {
51- private int prevFirstVisibleTop = 0 ;
52- private View firstVisibleView = null ;
53- private int currentScrollY = 0 ;
5459 @ Override
5560 public void willDispatchViewUpdates (final UIManagerModule uiManagerModule ) {
56- uiManagerModule .prependUIBlock (new UIBlock () {
57- @ Override
58- public void execute (NativeViewHierarchyManager nativeViewHierarchyManager ) {
59- ReactViewGroup mContentView = (ReactViewGroup )scrollView .getChildAt (0 );
60- if (mContentView == null ) return ;
61-
62- currentScrollY = scrollView .getScrollY ();
63-
64- for (int ii = minIndexForVisible ; ii < mContentView .getChildCount (); ++ii ) {
65- View subview = mContentView .getChildAt (ii );
66- if (subview .getTop () >= currentScrollY ) {
67- prevFirstVisibleTop = subview .getTop ();
68- firstVisibleView = subview ;
69- break ;
70- }
71- }
61+ ReactViewGroup mContentView = (ReactViewGroup )scrollView .getChildAt (0 );
62+ if (mContentView == null ) return ;
63+
64+ ScrollViewUIHolders .currentScrollY = scrollView .getScrollY ();
65+
66+ for (int ii = minIndexForVisible ; ii < mContentView .getChildCount (); ++ii ) {
67+ View subview = mContentView .getChildAt (ii );
68+ if (subview .getTop () >= ScrollViewUIHolders .currentScrollY ) {
69+ ScrollViewUIHolders .prevFirstVisibleTop = subview .getTop ();
70+ ScrollViewUIHolders .firstVisibleView = subview ;
71+ break ;
7272 }
73- });
73+ }
74+ }
75+ };
7476
75- UIImplementation .LayoutUpdateListener layoutUpdateListener = new UIImplementation .LayoutUpdateListener () {
76- @ Override
77- public void onLayoutUpdated (ReactShadowNode root ) {
78- if (firstVisibleView == null ) return ;
77+ UIImplementation .LayoutUpdateListener layoutUpdateListener = new UIImplementation .LayoutUpdateListener () {
78+ @ Override
79+ public void onLayoutUpdated (ReactShadowNode root ) {
80+ if (ScrollViewUIHolders . firstVisibleView == null ) return ;
7981
80- int deltaY = firstVisibleView .getTop () - prevFirstVisibleTop ;
82+ int deltaY = ScrollViewUIHolders . firstVisibleView .getTop () - ScrollViewUIHolders . prevFirstVisibleTop ;
8183
8284
83- if (Math .abs (deltaY ) > 1 ) {
84- boolean isWithinThreshold = currentScrollY <= autoscrollToTopThreshold ;
85- scrollView .setScrollY (currentScrollY + deltaY );
85+ if (Math .abs (deltaY ) > 1 ) {
86+ boolean isWithinThreshold = ScrollViewUIHolders . currentScrollY <= autoscrollToTopThreshold ;
87+ scrollView .setScrollY (ScrollViewUIHolders . currentScrollY + deltaY );
8688
87- // If the offset WAS within the threshold of the start, animate to the start.
88- if (isWithinThreshold ) {
89- scrollView .smoothScrollTo (scrollView .getScrollX (), 0 );
90- }
91- }
92- uiManagerModule .getUIImplementation ().removeLayoutUpdateListener ();
89+ // If the offset WAS within the threshold of the start, animate to the start.
90+ if (isWithinThreshold ) {
91+ scrollView .smoothScrollTo (scrollView .getScrollX (), 0 );
9392 }
94- };
95-
96- uiManagerModule .getUIImplementation ().setLayoutUpdateListener (layoutUpdateListener );
93+ }
9794 }
9895 };
96+
97+ uiManagerModule .getUIImplementation ().setLayoutUpdateListener (layoutUpdateListener );
9998 uiManagerModule .addUIManagerListener (uiManagerModuleListener );
10099 int key = uiManagerModuleListeners .size () + 1 ;
101100 uiManagerModuleListeners .put (key , uiManagerModuleListener );
102101 promise .resolve (key );
103102 } catch (IllegalViewOperationException e ) {
104- promise .resolve (- 1 );
103+ promise .reject ( e );
105104 }
106105 }
107106 });
@@ -113,9 +112,10 @@ public void disableMaintainVisibleContentPosition(int key, Promise promise) {
113112 if (key >= 0 ) {
114113 final UIManagerModule uiManagerModule = this .reactContext .getNativeModule (UIManagerModule .class );
115114 uiManagerModule .removeUIManagerListener (uiManagerModuleListeners .remove (key ));
115+ uiManagerModule .getUIImplementation ().removeLayoutUpdateListener ();
116116 }
117117 promise .resolve (null );
118- } catch (IllegalViewOperationException e ) {
118+ } catch (Exception e ) {
119119 promise .resolve (-1 );
120120 }
121121 }
0 commit comments