<lambda>null1 package com.reactnativepagerview
2 
3 import android.view.View
4 import androidx.viewpager2.widget.ViewPager2
5 import com.facebook.react.uimanager.PixelUtil
6 
7 object PagerViewViewManagerImpl {
8     const val NAME = "RNCViewPager"
9 
10     fun getViewPager(view: NestedScrollableHost): ViewPager2 {
11         if (view.getChildAt(0) is ViewPager2) {
12             return view.getChildAt(0) as ViewPager2
13         } else {
14             throw ClassNotFoundException("Could not retrieve ViewPager2 instance")
15         }
16     }
17 
18     fun setCurrentItem(view: ViewPager2, selectedTab: Int, scrollSmooth: Boolean) {
19         refreshViewChildrenLayout(view)
20         view.setCurrentItem(selectedTab, scrollSmooth)
21     }
22 
23     fun addView(host: NestedScrollableHost, child: View?, index: Int) {
24         if (child == null) {
25             return
26         }
27         val parent = getViewPager(host)
28 
29         (parent.adapter as ViewPagerAdapter?)?.addChild(child, index);
30 
31         if (parent.currentItem == index) {
32             // Solves https://github.com/callstack/react-native-pager-view/issues/219
33             // Required so ViewPager actually displays first dynamically added child
34             // (otherwise a white screen is shown until the next user interaction).
35             // https://github.com/facebook/react-native/issues/17968#issuecomment-697136929
36             refreshViewChildrenLayout(parent)
37         }
38 
39         if (!host.didSetInitialIndex && host.initialIndex == index) {
40             host.didSetInitialIndex = true
41             setCurrentItem(parent, index, false)
42         }
43     }
44 
45     fun getChildCount(parent: NestedScrollableHost) = getViewPager(parent).adapter?.itemCount ?: 0
46 
47     fun getChildAt(parent: NestedScrollableHost, index: Int): View {
48         val view = getViewPager(parent)
49         return (view.adapter as ViewPagerAdapter?)!!.getChildAt(index)
50     }
51 
52     fun removeView(parent: NestedScrollableHost, view: View) {
53         val pager = getViewPager(parent)
54         (pager.adapter as ViewPagerAdapter?)?.removeChild(view)
55 
56         // Required so ViewPager actually animates the removed view right away (otherwise
57         // a white screen is shown until the next user interaction).
58         // https://github.com/facebook/react-native/issues/17968#issuecomment-697136929
59         refreshViewChildrenLayout(pager)
60     }
61 
62     fun removeAllViews(parent: NestedScrollableHost) {
63         val pager = getViewPager(parent)
64         pager.isUserInputEnabled = false
65         val adapter = pager.adapter as ViewPagerAdapter?
66         adapter?.removeAll()
67     }
68 
69     fun removeViewAt(parent: NestedScrollableHost, index: Int) {
70         val pager = getViewPager(parent)
71         val adapter = pager.adapter as ViewPagerAdapter?
72         adapter?.removeChildAt(index)
73 
74         // Required so ViewPager actually animates the removed view right away (otherwise
75         // a white screen is shown until the next user interaction).
76         // https://github.com/facebook/react-native/issues/17968#issuecomment-697136929
77         refreshViewChildrenLayout(pager)
78     }
79 
80     fun needsCustomLayoutForChildren(): Boolean {
81         return true
82     }
83 
84     fun setScrollEnabled(host: NestedScrollableHost, value: Boolean) {
85         getViewPager(host).isUserInputEnabled = value
86     }
87 
88     fun setLayoutDirection(host: NestedScrollableHost, value: String) {
89         val view = getViewPager(host)
90         when (value) {
91             "rtl" -> {
92                 view.layoutDirection = View.LAYOUT_DIRECTION_RTL
93             }
94             else -> {
95                 view.layoutDirection = View.LAYOUT_DIRECTION_LTR
96             }
97         }
98     }
99 
100     fun setInitialPage(host: NestedScrollableHost, value: Int) {
101         val view = getViewPager(host)
102         //https://github.com/callstack/react-native-pager-view/issues/456
103         //Initial index should be set only once.
104         if (host.initialIndex === null) {
105             host.initialIndex = value
106             view.post {
107                 host.didSetInitialIndex = true
108             }
109         }
110     }
111 
112     fun setOrientation(host: NestedScrollableHost, value: String) {
113         getViewPager(host).orientation = if (value == "vertical") ViewPager2.ORIENTATION_VERTICAL else ViewPager2.ORIENTATION_HORIZONTAL
114     }
115 
116     fun setOffscreenPageLimit(host: NestedScrollableHost, value: Int) {
117         getViewPager(host).offscreenPageLimit = value
118     }
119 
120     fun setOverScrollMode(host: NestedScrollableHost, value: String) {
121         val child = getViewPager(host).getChildAt(0)
122         when (value) {
123             "never" -> {
124                 child.overScrollMode = ViewPager2.OVER_SCROLL_NEVER
125             }
126             "always" -> {
127                 child.overScrollMode = ViewPager2.OVER_SCROLL_ALWAYS
128             }
129             else -> {
130                 child.overScrollMode = ViewPager2.OVER_SCROLL_IF_CONTENT_SCROLLS
131             }
132         }
133     }
134 
135     fun setPageMargin(host: NestedScrollableHost, margin: Int) {
136         val pager = getViewPager(host)
137         val pageMargin = PixelUtil.toPixelFromDIP(margin.toDouble()).toInt()
138         /**
139          * Don't use MarginPageTransformer to be able to support negative margins
140          */
141         pager.setPageTransformer { page, position ->
142             val offset = pageMargin * position
143             if (pager.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
144                 val isRTL = pager.layoutDirection == View.LAYOUT_DIRECTION_RTL
145                 page.translationX = if (isRTL) -offset else offset
146             } else {
147                 page.translationY = offset
148             }
149         }
150     }
151 
152     private fun refreshViewChildrenLayout(view: View) {
153         view.post {
154             view.measure(
155                     View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.EXACTLY),
156                     View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.EXACTLY))
157             view.layout(view.left, view.top, view.right, view.bottom)
158         }
159     }
160 }