Skip to content
This repository was archived by the owner on Aug 13, 2024. It is now read-only.

Commit 0b30c5a

Browse files
committed
feat: implement android files
1 parent 1c7c4aa commit 0b30c5a

File tree

9 files changed

+183
-286
lines changed

9 files changed

+183
-286
lines changed

android/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ dependencies {
7474
//noinspection GradleDynamicVersion
7575
implementation "com.facebook.react:react-native:+"
7676
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
77+
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
7778
}
7879

7980
if (isNewArchitectureEnabled()) {

android/src/main/java/com/scrollviewenhancer/EnhancerFragment.kt

Lines changed: 0 additions & 83 deletions
This file was deleted.

android/src/main/java/com/scrollviewenhancer/MaintainVisibleScrollPositionHelper.kt

Lines changed: 44 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77
package com.scrollviewenhancer
88

99
import android.graphics.Rect
10+
import android.util.Log
1011
import android.view.View
1112
import com.facebook.infer.annotation.Assertions
1213
import com.facebook.react.bridge.*
14+
import com.facebook.react.uimanager.ReactShadowNode
15+
import com.facebook.react.uimanager.UIImplementation.LayoutUpdateListener
1316
import com.facebook.react.uimanager.UIManagerHelper
14-
import com.facebook.react.uimanager.common.ViewUtil
15-
import com.facebook.react.views.scroll.ReactHorizontalScrollView
17+
import com.facebook.react.uimanager.UIManagerModule
1618
import com.facebook.react.views.scroll.ReactScrollView
1719
import com.facebook.react.views.view.ReactViewGroup
1820
import java.lang.ref.WeakReference
1921

2022

21-
abstract class MaintainVisibleScrollPositionHelper {
23+
abstract class MVCPHelper {
2224
class Config internal constructor(
2325
val minIndexForVisible: Int,
2426
val autoScrollToTopThreshold: Int?
@@ -37,9 +39,9 @@ abstract class MaintainVisibleScrollPositionHelper {
3739
fun setConfig(config: Config?) {
3840
mConfig = config
3941
}
40-
abstract fun start(): Unit
41-
abstract fun stop(): Unit
42-
abstract fun updateScrollPosition(): Unit
42+
abstract fun start()
43+
abstract fun stop()
44+
abstract fun updateScrollPosition()
4345
}
4446

4547

@@ -48,173 +50,54 @@ abstract class MaintainVisibleScrollPositionHelper {
4850
*
4951
* This uses UIManager to listen to updates and capture position of items before and after layout.
5052
*/
51-
class MaintainVisibleScrollPositionHelperV(
53+
class MaintainVisibleScrollPositionHelper(
5254
private val mScrollView: ReactScrollView,
5355
private val mHorizontal: Boolean = false
54-
): UIManagerListener, MaintainVisibleScrollPositionHelper() {
56+
): MVCPHelper(), UIManagerListener, LayoutUpdateListener {
5557
private var mFirstVisibleView: WeakReference<View>? = null
5658
private var mPrevFirstVisibleFrame: Rect? = null
5759
private var mListening: Boolean = false
5860

59-
/**
60-
* Start listening to view hierarchy updates. Should be called when this is created.
61-
*/
62-
override fun start() {
63-
if (mListening) {
64-
return
65-
}
66-
mListening = true
67-
uIManagerModule.addUIManagerEventListener(this)
68-
}
69-
70-
/**
71-
* Stop listening to view hierarchy updates. Should be called before this is destroyed.
72-
*/
73-
override fun stop() {
74-
if (!mListening) {
75-
return
76-
}
77-
mListening = false
78-
uIManagerModule.removeUIManagerEventListener(this)
79-
}
61+
private val contentView: ReactViewGroup?
62+
get() = mScrollView.getChildAt(0) as? ReactViewGroup
8063

81-
/**
82-
* Update the scroll position of the managed ScrollView. This should be called after layout
83-
* has been updated.
84-
*/
85-
override fun updateScrollPosition() {
86-
if ((mConfig == null
87-
) || (mFirstVisibleView == null
88-
) || (mPrevFirstVisibleFrame == null)
89-
) {
90-
return
91-
}
92-
val firstVisibleView: View? = mFirstVisibleView!!.get()
93-
val newFrame: Rect = Rect()
94-
firstVisibleView!!.getHitRect(newFrame)
95-
if (mHorizontal) {
96-
val deltaX: Int = newFrame.left - mPrevFirstVisibleFrame!!.left
97-
if (deltaX != 0) {
98-
val scrollX: Int = mScrollView.scrollX
99-
mScrollView.scrollTo(scrollX + deltaX, mScrollView.scrollY)
100-
mPrevFirstVisibleFrame = newFrame
101-
if (mConfig!!.autoScrollToTopThreshold != null && scrollX <= mConfig!!.autoScrollToTopThreshold!!) {
102-
mScrollView.reactSmoothScrollTo(0, mScrollView.scrollY)
103-
}
104-
}
105-
} else {
106-
val deltaY: Int = newFrame.top - mPrevFirstVisibleFrame!!.top
107-
if (deltaY != 0) {
108-
val scrollY: Int = mScrollView.scrollY
109-
mScrollView.scrollTo(mScrollView.scrollX, scrollY + deltaY)
110-
mPrevFirstVisibleFrame = newFrame
111-
if (mConfig!!.autoScrollToTopThreshold != null && scrollY <= mConfig!!.autoScrollToTopThreshold!!) {
112-
mScrollView.reactSmoothScrollTo(mScrollView.scrollX, 0)
113-
}
114-
}
115-
}
116-
}
117-
118-
private val contentView: ReactViewGroup
119-
get() = mScrollView.getChildAt(0) as ReactViewGroup
120-
121-
private val uIManagerModule: UIManager
64+
private val uiManager: UIManager
12265
get() = Assertions.assertNotNull(
123-
UIManagerHelper.getUIManager(
124-
mScrollView.context as ReactContext,
125-
ViewUtil.getUIManagerType(mScrollView.id)
126-
)
66+
UIManagerHelper.getUIManagerForReactTag(mScrollView.context as ReactContext, mScrollView.id)
12767
)
12868

129-
private fun computeTargetView() {
130-
if (mConfig == null) {
131-
return
132-
}
133-
val contentView: ReactViewGroup? = contentView
134-
if (contentView == null) {
135-
return
136-
}
137-
val currentScroll: Int = if (mHorizontal) mScrollView!!.scrollX else mScrollView!!.scrollY
138-
for (i in mConfig!!.minIndexForVisible until contentView.childCount) {
139-
val child: View = contentView.getChildAt(i)
140-
val position: Float = if (mHorizontal) child.x else child.y
141-
if (position > currentScroll || i == contentView.childCount - 1) {
142-
mFirstVisibleView = WeakReference(child)
143-
val frame: Rect = Rect()
144-
child.getHitRect(frame)
145-
mPrevFirstVisibleFrame = frame
146-
break
147-
}
148-
}
149-
}
150-
151-
// UIManagerListener
152-
override fun willDispatchViewUpdates(uiManager: UIManager) {
153-
UiThreadUtil.runOnUiThread(
154-
object : Runnable {
155-
override fun run() {
156-
computeTargetView()
157-
}
158-
})
159-
}
160-
161-
override fun didDispatchMountItems(uiManager: UIManager) {
162-
// noop
163-
}
164-
165-
override fun didScheduleMountItems(uiManager: UIManager) {
166-
// noop
167-
}
168-
}
169-
170-
/**
171-
* Manage state for the maintainVisibleContentPosition prop.
172-
*
173-
* This uses UIManager to listen to updates and capture position of items before and after layout.
174-
*/
175-
class MaintainVisibleScrollPositionHelperH(
176-
private val mScrollView: ReactHorizontalScrollView,
177-
private val mHorizontal: Boolean = false
178-
): UIManagerListener, MaintainVisibleScrollPositionHelper() {
179-
private var mFirstVisibleView: WeakReference<View>? = null
180-
private var mPrevFirstVisibleFrame: Rect? = null
181-
private var mListening: Boolean = false
182-
18369
/**
18470
* Start listening to view hierarchy updates. Should be called when this is created.
18571
*/
18672
override fun start() {
187-
if (mListening) {
188-
return
189-
}
73+
if (mListening) return
74+
19075
mListening = true
191-
uIManagerModule.addUIManagerEventListener(this)
76+
uiManager.addUIManagerEventListener(this)
77+
(uiManager as? UIManagerModule)?.uiImplementation?.setLayoutUpdateListener(this)
19278
}
19379

19480
/**
19581
* Stop listening to view hierarchy updates. Should be called before this is destroyed.
19682
*/
19783
override fun stop() {
198-
if (!mListening) {
199-
return
200-
}
84+
if (!mListening) return
85+
20186
mListening = false
202-
uIManagerModule.removeUIManagerEventListener(this)
87+
uiManager.removeUIManagerEventListener(this)
20388
}
20489

20590
/**
20691
* Update the scroll position of the managed ScrollView. This should be called after layout
20792
* has been updated.
20893
*/
20994
override fun updateScrollPosition() {
210-
if ((mConfig == null
211-
) || (mFirstVisibleView == null
212-
) || (mPrevFirstVisibleFrame == null)
213-
) {
95+
if ((mConfig == null) || (mFirstVisibleView == null) || (mPrevFirstVisibleFrame == null)) {
21496
return
21597
}
98+
21699
val firstVisibleView: View? = mFirstVisibleView!!.get()
217-
val newFrame: Rect = Rect()
100+
val newFrame = Rect()
218101
firstVisibleView!!.getHitRect(newFrame)
219102
if (mHorizontal) {
220103
val deltaX: Int = newFrame.left - mPrevFirstVisibleFrame!!.left
@@ -239,47 +122,28 @@ class MaintainVisibleScrollPositionHelperH(
239122
}
240123
}
241124

242-
private val contentView: ReactViewGroup
243-
get() = mScrollView.getChildAt(0) as ReactViewGroup
244-
245-
private val uIManagerModule: UIManager
246-
get() = Assertions.assertNotNull(
247-
UIManagerHelper.getUIManager(
248-
mScrollView.context as ReactContext,
249-
ViewUtil.getUIManagerType(mScrollView.id)
250-
)
251-
)
252-
253125
private fun computeTargetView() {
254-
if (mConfig == null) {
255-
return
256-
}
257-
val contentView: ReactViewGroup? = contentView
258-
if (contentView == null) {
259-
return
260-
}
261-
val currentScroll: Int = if (mHorizontal) mScrollView!!.scrollX else mScrollView!!.scrollY
262-
for (i in mConfig!!.minIndexForVisible until contentView.childCount) {
263-
val child: View = contentView.getChildAt(i)
264-
val position: Float = if (mHorizontal) child.x else child.y
265-
if (position > currentScroll || i == contentView.childCount - 1) {
266-
mFirstVisibleView = WeakReference(child)
267-
val frame: Rect = Rect()
268-
child.getHitRect(frame)
269-
mPrevFirstVisibleFrame = frame
270-
break
126+
if (mConfig == null) return
127+
128+
contentView?.let { contentView ->
129+
val currentScroll: Int = if (mHorizontal) mScrollView.scrollX else mScrollView.scrollY
130+
for (i in mConfig!!.minIndexForVisible until contentView.childCount) {
131+
val child: View = contentView.getChildAt(i)
132+
val position: Float = if (mHorizontal) child.x else child.y
133+
if (position > currentScroll || i == contentView.childCount - 1) {
134+
mFirstVisibleView = WeakReference(child)
135+
val frame = Rect()
136+
child.getHitRect(frame)
137+
mPrevFirstVisibleFrame = frame
138+
break
139+
}
271140
}
272141
}
273142
}
274143

275144
// UIManagerListener
276145
override fun willDispatchViewUpdates(uiManager: UIManager) {
277-
UiThreadUtil.runOnUiThread(
278-
object : Runnable {
279-
override fun run() {
280-
computeTargetView()
281-
}
282-
})
146+
computeTargetView()
283147
}
284148

285149
override fun didDispatchMountItems(uiManager: UIManager) {
@@ -289,4 +153,9 @@ class MaintainVisibleScrollPositionHelperH(
289153
override fun didScheduleMountItems(uiManager: UIManager) {
290154
// noop
291155
}
156+
157+
// LayoutUpdateListener
158+
override fun onLayoutUpdated(p0: ReactShadowNode<out ReactShadowNode<*>>?) {
159+
updateScrollPosition()
160+
}
292161
}

0 commit comments

Comments
 (0)