1
1
package com.reactnativepagerview
2
2
3
3
import android.view.View
4
+ import android.view.ViewGroup
4
5
import androidx.viewpager2.widget.ViewPager2
5
6
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
6
7
import com.facebook.infer.annotation.Assertions
@@ -17,14 +18,17 @@ import com.reactnativepagerview.event.PageScrollStateChangedEvent
17
18
import com.reactnativepagerview.event.PageSelectedEvent
18
19
19
20
20
- class PagerViewViewManager : ViewGroupManager <ViewPager2 >() {
21
+ class PagerViewViewManager : ViewGroupManager <NestedScrollableHost >() {
21
22
private lateinit var eventDispatcher: EventDispatcher
22
23
23
24
override fun getName (): String {
24
25
return REACT_CLASS
25
26
}
26
27
27
- override fun createViewInstance (reactContext : ThemedReactContext ): ViewPager2 {
28
+ override fun createViewInstance (reactContext : ThemedReactContext ): NestedScrollableHost {
29
+ val host = NestedScrollableHost (reactContext)
30
+ host.layoutParams = ViewGroup .LayoutParams (ViewGroup .LayoutParams .MATCH_PARENT , ViewGroup .LayoutParams .MATCH_PARENT )
31
+ host.isSaveEnabled = false
28
32
val vp = ViewPager2 (reactContext)
29
33
vp.adapter = ViewPagerAdapter ()
30
34
// https://github.com/callstack/react-native-viewpager/issues/183
@@ -36,13 +40,13 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
36
40
override fun onPageScrolled (position : Int , positionOffset : Float , positionOffsetPixels : Int ) {
37
41
super .onPageScrolled(position, positionOffset, positionOffsetPixels)
38
42
eventDispatcher.dispatchEvent(
39
- PageScrollEvent (vp .id, position, positionOffset))
43
+ PageScrollEvent (host .id, position, positionOffset))
40
44
}
41
45
42
46
override fun onPageSelected (position : Int ) {
43
47
super .onPageSelected(position)
44
48
eventDispatcher.dispatchEvent(
45
- PageSelectedEvent (vp .id, position))
49
+ PageSelectedEvent (host .id, position))
46
50
}
47
51
48
52
override fun onPageScrollStateChanged (state : Int ) {
@@ -54,25 +58,34 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
54
58
else -> throw IllegalStateException (" Unsupported pageScrollState" )
55
59
}
56
60
eventDispatcher.dispatchEvent(
57
- PageScrollStateChangedEvent (vp .id, pageScrollState))
61
+ PageScrollStateChangedEvent (host .id, pageScrollState))
58
62
}
59
63
})
60
64
61
- eventDispatcher.dispatchEvent(PageSelectedEvent (vp .id, vp.currentItem))
65
+ eventDispatcher.dispatchEvent(PageSelectedEvent (host .id, vp.currentItem))
62
66
}
67
+ host.addView(vp)
68
+ return host
69
+ }
63
70
64
- return vp
71
+ private fun getViewPager (view : NestedScrollableHost ): ViewPager2 {
72
+ if (view.getChildAt(0 ) is ViewPager2 ) {
73
+ return view.getChildAt(0 ) as ViewPager2
74
+ } else {
75
+ throw ClassNotFoundException (" Could not retrieve ViewPager2 instance" )
76
+ }
65
77
}
66
78
67
79
private fun setCurrentItem (view : ViewPager2 , selectedTab : Int , scrollSmooth : Boolean ) {
68
80
refreshViewChildrenLayout(view)
69
81
view.setCurrentItem(selectedTab, scrollSmooth)
70
82
}
71
83
72
- override fun addView (parent : ViewPager2 , child : View ? , index : Int ) {
84
+ override fun addView (host : NestedScrollableHost , child : View ? , index : Int ) {
73
85
if (child == null ) {
74
86
return
75
87
}
88
+ val parent = getViewPager(host)
76
89
77
90
(parent.adapter as ViewPagerAdapter ? )?.addChild(child, index);
78
91
@@ -85,68 +98,71 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
85
98
}
86
99
}
87
100
88
- override fun getChildCount (parent : ViewPager2 ): Int {
89
- return parent.adapter?.itemCount ? : 0 ;
90
- }
101
+ override fun getChildCount (parent : NestedScrollableHost ) = getViewPager(parent).adapter?.itemCount ? : 0
91
102
92
- override fun getChildAt (parent : ViewPager2 , index : Int ): View {
93
- return (parent.adapter as ViewPagerAdapter ? )!! .getChildAt(index)
103
+ override fun getChildAt (parent : NestedScrollableHost , index : Int ): View {
104
+ val view = getViewPager(parent)
105
+ return (view.adapter as ViewPagerAdapter ? )!! .getChildAt(index)
94
106
}
95
107
96
- override fun removeView (parent : ViewPager2 , view : View ) {
97
- (parent.adapter as ViewPagerAdapter ? )?.removeChild(view)
108
+ override fun removeView (parent : NestedScrollableHost , view : View ) {
109
+ val pager = getViewPager(parent)
110
+ (pager.adapter as ViewPagerAdapter ? )?.removeChild(view)
98
111
99
112
// Required so ViewPager actually animates the removed view right away (otherwise
100
113
// a white screen is shown until the next user interaction).
101
114
// https://github.com/facebook/react-native/issues/17968#issuecomment-697136929
102
- refreshViewChildrenLayout(parent )
115
+ refreshViewChildrenLayout(pager )
103
116
}
104
117
105
- override fun removeAllViews (parent : ViewPager2 ) {
106
- parent.isUserInputEnabled = false
107
- val adapter = parent.adapter as ViewPagerAdapter ?
118
+ override fun removeAllViews (parent : NestedScrollableHost ) {
119
+ val pager = getViewPager(parent)
120
+ pager.isUserInputEnabled = false
121
+ val adapter = pager.adapter as ViewPagerAdapter ?
108
122
adapter?.removeAll()
109
123
}
110
124
111
- override fun removeViewAt (parent : ViewPager2 , index : Int ) {
112
- val adapter = parent.adapter as ViewPagerAdapter ?
125
+ override fun removeViewAt (parent : NestedScrollableHost , index : Int ) {
126
+ val pager = getViewPager(parent)
127
+ val adapter = pager.adapter as ViewPagerAdapter ?
113
128
adapter?.removeChildAt(index)
114
129
115
130
// Required so ViewPager actually animates the removed view right away (otherwise
116
131
// a white screen is shown until the next user interaction).
117
132
// https://github.com/facebook/react-native/issues/17968#issuecomment-697136929
118
- refreshViewChildrenLayout(parent )
133
+ refreshViewChildrenLayout(pager )
119
134
}
120
135
121
136
override fun needsCustomLayoutForChildren (): Boolean {
122
137
return true
123
138
}
124
139
125
140
@ReactProp(name = " scrollEnabled" , defaultBoolean = true )
126
- fun setScrollEnabled (viewPager : ViewPager2 , value : Boolean ) {
127
- viewPager .isUserInputEnabled = value
141
+ fun setScrollEnabled (host : NestedScrollableHost , value : Boolean ) {
142
+ getViewPager(host) .isUserInputEnabled = value
128
143
}
129
144
130
145
@ReactProp(name = " initialPage" , defaultInt = 0 )
131
- fun setInitialPage (viewPager : ViewPager2 , value : Int ) {
132
- viewPager.post {
133
- setCurrentItem(viewPager, value, false )
146
+ fun setInitialPage (host : NestedScrollableHost , value : Int ) {
147
+ val view = getViewPager(host)
148
+ view.post {
149
+ setCurrentItem(view, value, false )
134
150
}
135
151
}
136
152
137
153
@ReactProp(name = " orientation" )
138
- fun setOrientation (viewPager : ViewPager2 , value : String ) {
139
- viewPager .orientation = if (value == " vertical" ) ViewPager2 .ORIENTATION_VERTICAL else ViewPager2 .ORIENTATION_HORIZONTAL
154
+ fun setOrientation (host : NestedScrollableHost , value : String ) {
155
+ getViewPager(host) .orientation = if (value == " vertical" ) ViewPager2 .ORIENTATION_VERTICAL else ViewPager2 .ORIENTATION_HORIZONTAL
140
156
}
141
157
142
158
@ReactProp(name = " offscreenPageLimit" , defaultInt = ViewPager2 .OFFSCREEN_PAGE_LIMIT_DEFAULT )
143
- operator fun set (viewPager : ViewPager2 , value : Int ) {
144
- viewPager .offscreenPageLimit = value
159
+ operator fun set (host : NestedScrollableHost , value : Int ) {
160
+ getViewPager(host) .offscreenPageLimit = value
145
161
}
146
162
147
163
@ReactProp(name = " overScrollMode" )
148
- fun setOverScrollMode (viewPager : ViewPager2 , value : String ) {
149
- val child = viewPager .getChildAt(0 )
164
+ fun setOverScrollMode (host : NestedScrollableHost , value : String ) {
165
+ val child = getViewPager(host) .getChildAt(0 )
150
166
when (value) {
151
167
" never" -> {
152
168
child.overScrollMode = ViewPager2 .OVER_SCROLL_NEVER
@@ -161,13 +177,14 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
161
177
}
162
178
163
179
@ReactProp(name = " layoutDirection" )
164
- fun setLayoutDirection (viewPager : ViewPager2 , value : String ) {
180
+ fun setLayoutDirection (host : NestedScrollableHost , value : String ) {
181
+ val view = getViewPager(host)
165
182
when (value) {
166
183
" rtl" -> {
167
- viewPager .layoutDirection = View .LAYOUT_DIRECTION_RTL
184
+ view .layoutDirection = View .LAYOUT_DIRECTION_RTL
168
185
}
169
186
else -> {
170
- viewPager .layoutDirection = View .LAYOUT_DIRECTION_LTR
187
+ view .layoutDirection = View .LAYOUT_DIRECTION_LTR
171
188
}
172
189
}
173
190
}
@@ -189,24 +206,25 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
189
206
COMMAND_SET_SCROLL_ENABLED )
190
207
}
191
208
192
- override fun receiveCommand (root : ViewPager2 , commandId : Int , args : ReadableArray ? ) {
209
+ override fun receiveCommand (root : NestedScrollableHost , commandId : Int , args : ReadableArray ? ) {
193
210
super .receiveCommand(root, commandId, args)
194
- Assertions .assertNotNull(root)
211
+ val view = getViewPager(root)
212
+ Assertions .assertNotNull(view)
195
213
Assertions .assertNotNull(args)
196
- val childCount = root .adapter?.itemCount
214
+ val childCount = view .adapter?.itemCount
197
215
198
216
when (commandId) {
199
217
COMMAND_SET_PAGE , COMMAND_SET_PAGE_WITHOUT_ANIMATION -> {
200
218
val pageIndex = args!! .getInt(0 )
201
219
val canScroll = childCount != null && childCount > 0 && pageIndex >= 0 && pageIndex < childCount
202
220
if (canScroll) {
203
221
val scrollWithAnimation = commandId == COMMAND_SET_PAGE
204
- setCurrentItem(root , pageIndex, scrollWithAnimation)
222
+ setCurrentItem(view , pageIndex, scrollWithAnimation)
205
223
eventDispatcher.dispatchEvent(PageSelectedEvent (root.id, pageIndex))
206
224
}
207
225
}
208
226
COMMAND_SET_SCROLL_ENABLED -> {
209
- root .isUserInputEnabled = args!! .getBoolean(0 )
227
+ view .isUserInputEnabled = args!! .getBoolean(0 )
210
228
}
211
229
else -> throw IllegalArgumentException (String .format(
212
230
" Unsupported command %d received by %s." ,
@@ -216,7 +234,8 @@ class PagerViewViewManager : ViewGroupManager<ViewPager2>() {
216
234
}
217
235
218
236
@ReactProp(name = " pageMargin" , defaultFloat = 0F )
219
- fun setPageMargin (pager : ViewPager2 , margin : Float ) {
237
+ fun setPageMargin (host : NestedScrollableHost , margin : Float ) {
238
+ val pager = getViewPager(host)
220
239
val pageMargin = PixelUtil .toPixelFromDIP(margin).toInt()
221
240
/* *
222
241
* Don't use MarginPageTransformer to be able to support negative margins
0 commit comments