react-native-navigation 7.43.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Mock/Components/ComponentScreen.tsx +29 -15
- package/lib/Mock/Components/LayoutComponent.tsx +2 -2
- package/lib/Mock/index.js +2 -2
- package/lib/android/app/build.gradle +1 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt +60 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java +20 -4
- package/lib/android/app/src/main/java/com/reactnativenavigation/options/ValueAnimationOptions.kt +3 -3
- package/lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java +3 -3
- package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalHostLayout.kt +1 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactTypefaceUtils.java +3 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactViewGroup.kt +4 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StubAnimationListener.kt +19 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +16 -10
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java +6 -4
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsAnimator.kt +2 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +7 -14
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +37 -13
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +24 -11
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +13 -10
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/statusbar/StatusBarController.kt +9 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/statusbar/StatusBarPresenter.kt +9 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/{TopBarAnimator.kt → TopBarAppearanceAnimator.kt} +4 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarCollapseBehavior.kt +1 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +122 -27
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/LayoutDirectionApplier.kt +8 -4
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +79 -6
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/RootPresenter.java +1 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +5 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/{BaseViewAnimator.kt → BaseViewAppearanceAnimator.kt} +4 -4
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ColorAnimator.kt +22 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/DefaultViewAnimatorCreator.kt +8 -8
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewAnimatorCreator.kt +2 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewBkgColorProperty.kt +17 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorAnimator.kt +6 -4
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorEvaluator.kt +4 -2
- package/lib/android/app/src/reactNative71/java/com/reactnativenavigation/react/modal/ModalContentLayout.kt +6 -6
- package/lib/dist/Mock/Application.d.ts +4 -6
- package/lib/dist/Mock/Components/BottomTabs.d.ts +9 -13
- package/lib/dist/Mock/Components/ComponentScreen.d.ts +5 -7
- package/lib/dist/Mock/Components/ComponentScreen.js +10 -3
- package/lib/dist/Mock/Components/LayoutComponent.d.ts +9 -13
- package/lib/dist/Mock/Components/Modals.d.ts +9 -13
- package/lib/dist/Mock/Components/NavigationButton.d.ts +11 -15
- package/lib/dist/Mock/Components/Overlays.d.ts +9 -13
- package/lib/dist/Mock/Components/Stack.d.ts +9 -13
- package/lib/dist/Mock/Components/TopBar.d.ts +7 -9
- package/lib/dist/Mock/connect.js +2 -1
- package/lib/dist/Mock/index.js +2 -2
- package/lib/dist/src/adapters/NativeEventsReceiver.js +1 -1
- package/lib/dist/src/adapters/TouchablePreview.d.ts +2 -2
- package/lib/dist/src/commands/LayoutType.js +1 -1
- package/lib/dist/src/commands/OptionsProcessor.js +8 -1
- package/lib/dist/src/components/Modal.d.ts +1 -1
- package/lib/dist/src/interfaces/CommandName.js +1 -1
- package/lib/dist/src/interfaces/Options.d.ts +33 -3
- package/lib/dist/src/interfaces/Options.js +2 -2
- package/lib/dist/src/types.d.ts +1 -0
- package/lib/ios/BottomTabsBasePresenter.m +3 -2
- package/lib/ios/RNNAppDelegate.mm +1 -2
- package/lib/ios/RNNConvert.h +2 -0
- package/lib/ios/RNNConvert.m +4 -0
- package/lib/ios/RNNStackPresenter.m +3 -2
- package/lib/src/adapters/NativeEventsReceiver.ts +3 -3
- package/lib/src/adapters/TouchablePreview.tsx +3 -3
- package/lib/src/commands/OptionsProcessor.ts +13 -2
- package/lib/src/interfaces/Options.ts +38 -3
- package/package.json +37 -31
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package com.reactnativenavigation.viewcontrollers.stack.statusbar
|
|
2
|
+
|
|
3
|
+
import android.animation.Animator
|
|
4
|
+
import com.reactnativenavigation.options.Options
|
|
5
|
+
|
|
6
|
+
interface StatusBarPresenter {
|
|
7
|
+
fun getStatusBarPushAnimation(appearingOptions: Options): Animator?
|
|
8
|
+
fun getStatusBarPopAnimation(appearingOptions: Options, disappearingOptions: Options): Animator?
|
|
9
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
package com.reactnativenavigation.viewcontrollers.stack.topbar
|
|
2
2
|
|
|
3
|
-
import com.reactnativenavigation.views.animations.
|
|
3
|
+
import com.reactnativenavigation.views.animations.BaseViewAppearanceAnimator
|
|
4
4
|
import com.reactnativenavigation.views.stack.topbar.TopBar
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class TopBarAppearanceAnimator @JvmOverloads constructor(view: TopBar? = null)
|
|
7
|
+
: BaseViewAppearanceAnimator<TopBar>(HideDirection.Up, view) {
|
|
8
|
+
|
|
7
9
|
@Suppress("UNUSED_PARAMETER")
|
|
8
10
|
fun hideOnScroll(translationStart: Float, translationEndDy: Float) {
|
|
9
11
|
// NOOP for now - this entire mechanism needs to be reimplemented as it relies on bridge events which are obsolete in TurboModules config
|
|
@@ -7,7 +7,7 @@ import com.reactnativenavigation.views.stack.topbar.TopBar
|
|
|
7
7
|
|
|
8
8
|
class TopBarCollapseBehavior(private val topBar: TopBar) : ScrollEventListener.OnScrollListener, ScrollEventListener.OnDragListener {
|
|
9
9
|
private var scrollEventListener: ScrollEventListener? = null
|
|
10
|
-
private val animator:
|
|
10
|
+
private val animator: TopBarAppearanceAnimator = TopBarAppearanceAnimator(topBar)
|
|
11
11
|
|
|
12
12
|
fun enableCollapse(scrollEventListener: ScrollEventListener?) {
|
|
13
13
|
this.scrollEventListener = scrollEventListener
|
|
@@ -1,28 +1,40 @@
|
|
|
1
1
|
package com.reactnativenavigation.viewcontrollers.stack.topbar
|
|
2
2
|
|
|
3
3
|
import android.animation.Animator
|
|
4
|
+
import android.animation.AnimatorSet
|
|
4
5
|
import android.content.Context
|
|
6
|
+
import android.graphics.drawable.ColorDrawable
|
|
5
7
|
import android.view.MenuItem
|
|
6
8
|
import android.view.View
|
|
9
|
+
import androidx.core.animation.addListener
|
|
7
10
|
import androidx.viewpager.widget.ViewPager
|
|
11
|
+
import com.reactnativenavigation.RNNFeatureToggles
|
|
12
|
+
import com.reactnativenavigation.RNNToggles.TOP_BAR_COLOR_ANIMATION
|
|
8
13
|
import com.reactnativenavigation.options.Alignment
|
|
9
14
|
import com.reactnativenavigation.options.AnimationOptions
|
|
10
15
|
import com.reactnativenavigation.options.Options
|
|
16
|
+
import com.reactnativenavigation.options.TopBarOptions
|
|
17
|
+
import com.reactnativenavigation.options.animations.ViewAnimationOptions
|
|
11
18
|
import com.reactnativenavigation.utils.CollectionUtils.forEachIndexed
|
|
12
19
|
import com.reactnativenavigation.utils.ViewUtils
|
|
13
20
|
import com.reactnativenavigation.utils.resetViewProperties
|
|
14
21
|
import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonController
|
|
15
22
|
import com.reactnativenavigation.viewcontrollers.stack.topbar.title.TitleBarReactViewController
|
|
23
|
+
import com.reactnativenavigation.views.animations.ColorAnimator
|
|
16
24
|
import com.reactnativenavigation.views.stack.StackLayout
|
|
17
25
|
import com.reactnativenavigation.views.stack.topbar.TopBar
|
|
18
26
|
import com.reactnativenavigation.views.stack.topbar.titlebar.ButtonBar
|
|
19
27
|
|
|
20
28
|
|
|
21
|
-
open class TopBarController(
|
|
29
|
+
open class TopBarController(
|
|
30
|
+
private val appearAnimator: TopBarAppearanceAnimator = TopBarAppearanceAnimator(),
|
|
31
|
+
private val colorAnimator: ColorAnimator = ColorAnimator(),
|
|
32
|
+
) {
|
|
22
33
|
lateinit var view: TopBar
|
|
23
34
|
private lateinit var leftButtonBar: ButtonBar
|
|
24
35
|
private lateinit var rightButtonBar: ButtonBar
|
|
25
36
|
|
|
37
|
+
private var hasPendingColorAnim = false
|
|
26
38
|
|
|
27
39
|
val height: Int
|
|
28
40
|
get() = view.height
|
|
@@ -31,46 +43,89 @@ open class TopBarController(private val animator: TopBarAnimator = TopBarAnimato
|
|
|
31
43
|
val leftButtonCount: Int
|
|
32
44
|
get() = leftButtonBar.buttonCount
|
|
33
45
|
|
|
34
|
-
fun getRightButton(index: Int): MenuItem = rightButtonBar.getButton(index)
|
|
35
|
-
|
|
36
46
|
fun createView(context: Context, parent: StackLayout): TopBar {
|
|
37
47
|
if (!::view.isInitialized) {
|
|
38
48
|
view = createTopBar(context, parent)
|
|
39
49
|
leftButtonBar = view.leftButtonBar
|
|
40
50
|
rightButtonBar = view.rightButtonBar
|
|
41
|
-
|
|
51
|
+
appearAnimator.bindView(view)
|
|
42
52
|
}
|
|
43
53
|
return view
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
protected open fun createTopBar(context: Context, stackLayout: StackLayout): TopBar {
|
|
47
|
-
return TopBar(context)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
56
|
fun initTopTabs(viewPager: ViewPager?) = view.initTopTabs(viewPager)
|
|
51
57
|
|
|
52
58
|
fun clearTopTabs() = view.clearTopTabs()
|
|
53
59
|
|
|
60
|
+
fun setBackgroundColor(topBarOptions: TopBarOptions, defaultColor: Int) {
|
|
61
|
+
val color = topBarOptions.background.color
|
|
62
|
+
|
|
63
|
+
if (!hasPendingColorAnim) {
|
|
64
|
+
view.setBackgroundColor(color.get(defaultColor)!!)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fun setBackgroundColor(topBarOptions: TopBarOptions) {
|
|
69
|
+
val color = topBarOptions.background.color
|
|
70
|
+
|
|
71
|
+
if (color.hasValue() && !hasPendingColorAnim) {
|
|
72
|
+
view.setBackgroundColor(color.get())
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun getRightButton(index: Int): MenuItem = rightButtonBar.getButton(index)
|
|
77
|
+
|
|
54
78
|
fun getPushAnimation(appearingOptions: Options, additionalDy: Float = 0f): Animator? {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
79
|
+
val topBarOptions = appearingOptions.topBar
|
|
80
|
+
val topBarAnimOptions = appearingOptions.animations.push.topBar
|
|
81
|
+
|
|
82
|
+
hasPendingColorAnim = false
|
|
83
|
+
|
|
84
|
+
mutableListOf(
|
|
85
|
+
getAppearancePushAnimation(topBarOptions, topBarAnimOptions, additionalDy),
|
|
86
|
+
getBkgColorAnimation(topBarOptions)?.apply {
|
|
87
|
+
hasPendingColorAnim = true
|
|
88
|
+
|
|
89
|
+
addListener(onEnd = {
|
|
90
|
+
hasPendingColorAnim = false
|
|
91
|
+
})
|
|
92
|
+
},
|
|
93
|
+
).filterNotNull().let {
|
|
94
|
+
return if (it.isNotEmpty()) {
|
|
95
|
+
AnimatorSet().apply { playTogether(it) }
|
|
96
|
+
} else {
|
|
97
|
+
null
|
|
98
|
+
}
|
|
99
|
+
}
|
|
61
100
|
}
|
|
62
101
|
|
|
63
102
|
fun getPopAnimation(appearingOptions: Options, disappearingOptions: Options): Animator? {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
val topBarOptions = appearingOptions.topBar
|
|
104
|
+
val topBarAnimOptions = disappearingOptions.animations.pop.topBar
|
|
105
|
+
|
|
106
|
+
hasPendingColorAnim = false
|
|
107
|
+
|
|
108
|
+
mutableListOf(
|
|
109
|
+
getAppearancePopAnimation(topBarOptions, topBarAnimOptions),
|
|
110
|
+
getBkgColorAnimation(topBarOptions)?.apply {
|
|
111
|
+
hasPendingColorAnim = true
|
|
112
|
+
|
|
113
|
+
addListener(onEnd = {
|
|
114
|
+
hasPendingColorAnim = false
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
).filterNotNull().let {
|
|
118
|
+
return if (it.isNotEmpty()) {
|
|
119
|
+
AnimatorSet().apply { playTogether(it) }
|
|
120
|
+
} else {
|
|
121
|
+
null
|
|
122
|
+
}
|
|
123
|
+
}
|
|
69
124
|
}
|
|
70
125
|
|
|
71
126
|
fun getSetStackRootAnimation(appearingOptions: Options, additionalDy: Float = 0f): Animator? {
|
|
72
127
|
if (appearingOptions.topBar.animate.isFalse) return null
|
|
73
|
-
return
|
|
128
|
+
return appearAnimator.getSetStackRootAnimation(
|
|
74
129
|
appearingOptions.animations.setStackRoot.topBar,
|
|
75
130
|
appearingOptions.topBar.visible,
|
|
76
131
|
additionalDy
|
|
@@ -78,23 +133,23 @@ open class TopBarController(private val animator: TopBarAnimator = TopBarAnimato
|
|
|
78
133
|
}
|
|
79
134
|
|
|
80
135
|
fun show() {
|
|
81
|
-
if (ViewUtils.isVisible(view) ||
|
|
136
|
+
if (ViewUtils.isVisible(view) || appearAnimator.isAnimatingShow()) return
|
|
82
137
|
view.resetViewProperties()
|
|
83
138
|
view.visibility = View.VISIBLE
|
|
84
139
|
}
|
|
85
140
|
|
|
86
141
|
fun showAnimate(options: AnimationOptions, additionalDy: Float) {
|
|
87
|
-
if (ViewUtils.isVisible(view) ||
|
|
88
|
-
|
|
142
|
+
if (ViewUtils.isVisible(view) || appearAnimator.isAnimatingShow()) return
|
|
143
|
+
appearAnimator.show(options, additionalDy)
|
|
89
144
|
}
|
|
90
145
|
|
|
91
146
|
fun hide() {
|
|
92
|
-
if (!
|
|
147
|
+
if (!appearAnimator.isAnimatingHide()) view.visibility = View.GONE
|
|
93
148
|
}
|
|
94
149
|
|
|
95
150
|
fun hideAnimate(options: AnimationOptions, additionalDy: Float) {
|
|
96
|
-
if (!ViewUtils.isVisible(view) ||
|
|
97
|
-
|
|
151
|
+
if (!ViewUtils.isVisible(view) || appearAnimator.isAnimatingHide()) return
|
|
152
|
+
appearAnimator.hide(options, additionalDy)
|
|
98
153
|
}
|
|
99
154
|
|
|
100
155
|
fun setTitleComponent(component: TitleBarReactViewController) {
|
|
@@ -126,4 +181,44 @@ open class TopBarController(private val animator: TopBarAnimator = TopBarAnimato
|
|
|
126
181
|
toRemove.forEach { view.removeLeftButton(it) }
|
|
127
182
|
forEachIndexed(toAdd) { b: ButtonController, i: Int -> b.addToMenu(leftButtonBar, i * 10) }
|
|
128
183
|
}
|
|
129
|
-
|
|
184
|
+
|
|
185
|
+
protected open fun createTopBar(context: Context, stackLayout: StackLayout): TopBar {
|
|
186
|
+
return TopBar(context)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private fun getBkgColorAnimation(topBarOptions: TopBarOptions): Animator? {
|
|
190
|
+
val targetColor = topBarOptions.background.color
|
|
191
|
+
|
|
192
|
+
if (targetColor.hasValue()
|
|
193
|
+
&& view.background is ColorDrawable
|
|
194
|
+
&& RNNFeatureToggles.isEnabled(TOP_BAR_COLOR_ANIMATION)) {
|
|
195
|
+
return colorAnimator.getAnimation(
|
|
196
|
+
view,
|
|
197
|
+
(view.background as ColorDrawable).color,
|
|
198
|
+
targetColor.get()
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
return null
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private fun getAppearancePushAnimation(topBarOptions: TopBarOptions, topBarAnimOptions: ViewAnimationOptions, additionalDy: Float) =
|
|
205
|
+
if (!topBarOptions.animate.isFalse) {
|
|
206
|
+
appearAnimator.getPushAnimation(
|
|
207
|
+
topBarAnimOptions,
|
|
208
|
+
topBarOptions.visible,
|
|
209
|
+
additionalDy,
|
|
210
|
+
)
|
|
211
|
+
} else {
|
|
212
|
+
null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private fun getAppearancePopAnimation(topBarOptions: TopBarOptions, topBarAnimOptions: ViewAnimationOptions) =
|
|
216
|
+
if (!topBarOptions.animate.isFalse) {
|
|
217
|
+
appearAnimator.getPopAnimation(
|
|
218
|
+
topBarAnimOptions,
|
|
219
|
+
topBarOptions.visible,
|
|
220
|
+
)
|
|
221
|
+
} else {
|
|
222
|
+
null
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
package com.reactnativenavigation.viewcontrollers.viewcontroller
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
3
4
|
import com.facebook.react.ReactInstanceManager
|
|
4
5
|
import com.facebook.react.modules.i18nmanager.I18nUtil
|
|
5
6
|
import com.reactnativenavigation.options.Options
|
|
6
7
|
|
|
7
8
|
class LayoutDirectionApplier {
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
@SuppressLint("WrongConstant")
|
|
10
|
+
fun apply(root: ViewController<*>, options: Options) {
|
|
11
|
+
val currentContext = root.view?.context ?: return
|
|
12
|
+
|
|
13
|
+
if (options.layout.direction.hasValue()) {
|
|
10
14
|
root.activity.window.decorView.layoutDirection = options.layout.direction.get()
|
|
11
|
-
I18nUtil.
|
|
12
|
-
I18nUtil.
|
|
15
|
+
I18nUtil.instance.allowRTL(currentContext, options.layout.direction.isRtl)
|
|
16
|
+
I18nUtil.instance.forceRTL(currentContext, options.layout.direction.isRtl)
|
|
13
17
|
}
|
|
14
18
|
}
|
|
15
19
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
package com.reactnativenavigation.viewcontrollers.viewcontroller;
|
|
2
2
|
|
|
3
|
+
import static com.reactnativenavigation.utils.StubAnimationListener.onAnimatorEnd;
|
|
4
|
+
|
|
5
|
+
import android.animation.Animator;
|
|
6
|
+
import android.animation.ValueAnimator;
|
|
3
7
|
import android.app.Activity;
|
|
4
8
|
import android.graphics.Color;
|
|
5
9
|
import android.graphics.drawable.ColorDrawable;
|
|
@@ -10,6 +14,11 @@ import android.view.ViewGroup;
|
|
|
10
14
|
import android.view.ViewGroup.MarginLayoutParams;
|
|
11
15
|
import android.view.Window;
|
|
12
16
|
|
|
17
|
+
import androidx.annotation.NonNull;
|
|
18
|
+
|
|
19
|
+
import com.reactnativenavigation.RNNFeatureToggles;
|
|
20
|
+
import com.reactnativenavigation.RNNToggles;
|
|
21
|
+
import com.reactnativenavigation.options.AnimationOptions;
|
|
13
22
|
import com.reactnativenavigation.options.NavigationBarOptions;
|
|
14
23
|
import com.reactnativenavigation.options.Options;
|
|
15
24
|
import com.reactnativenavigation.options.OrientationOptions;
|
|
@@ -17,18 +26,31 @@ import com.reactnativenavigation.options.StatusBarOptions;
|
|
|
17
26
|
import com.reactnativenavigation.options.StatusBarOptions.TextColorScheme;
|
|
18
27
|
import com.reactnativenavigation.options.layout.LayoutInsets;
|
|
19
28
|
import com.reactnativenavigation.options.params.Bool;
|
|
29
|
+
import com.reactnativenavigation.options.params.ThemeColour;
|
|
20
30
|
import com.reactnativenavigation.utils.SystemUiUtils;
|
|
21
|
-
import com.reactnativenavigation.viewcontrollers.parent.ParentController;
|
|
22
31
|
import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
|
|
32
|
+
import com.reactnativenavigation.viewcontrollers.parent.ParentController;
|
|
33
|
+
import com.reactnativenavigation.viewcontrollers.stack.statusbar.StatusBarPresenter;
|
|
34
|
+
import com.reactnativenavigation.views.animations.ColorAnimator;
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
import org.jetbrains.annotations.NotNull;
|
|
37
|
+
import org.jetbrains.annotations.Nullable;
|
|
38
|
+
|
|
39
|
+
public class Presenter implements StatusBarPresenter {
|
|
25
40
|
private final Activity activity;
|
|
41
|
+
private final ColorAnimator colorAnimator;
|
|
42
|
+
|
|
26
43
|
private Options defaultOptions;
|
|
44
|
+
private Boolean hasPendingColorAnim = false;
|
|
27
45
|
|
|
28
46
|
public Presenter(Activity activity, Options defaultOptions) {
|
|
47
|
+
this(activity, defaultOptions, new ColorAnimator());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public Presenter(Activity activity, Options defaultOptions, ColorAnimator colorAnimator) {
|
|
29
51
|
this.activity = activity;
|
|
52
|
+
this.colorAnimator = colorAnimator;
|
|
30
53
|
this.defaultOptions = defaultOptions;
|
|
31
|
-
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
public void setDefaultOptions(Options defaultOptions) {
|
|
@@ -106,12 +128,56 @@ public class Presenter {
|
|
|
106
128
|
|
|
107
129
|
private void applyStatusBarOptions(ViewController viewController, Options options) {
|
|
108
130
|
StatusBarOptions statusBar = options.copy().withDefaultOptions(defaultOptions).statusBar;
|
|
109
|
-
|
|
131
|
+
|
|
132
|
+
if (!hasPendingColorAnim) {
|
|
133
|
+
setStatusBarBackgroundColor(statusBar);
|
|
134
|
+
}
|
|
110
135
|
setTextColorScheme(statusBar);
|
|
111
136
|
setTranslucent(statusBar);
|
|
112
137
|
setStatusBarVisible(viewController, statusBar.visible);
|
|
113
138
|
}
|
|
114
139
|
|
|
140
|
+
@Nullable
|
|
141
|
+
@Override
|
|
142
|
+
public Animator getStatusBarPushAnimation(@NotNull Options appearingOptions) {
|
|
143
|
+
StatusBarOptions statusBarOptions = appearingOptions.statusBar;
|
|
144
|
+
return getStatusBarColorAnimation(statusBarOptions);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@androidx.annotation.Nullable
|
|
148
|
+
@Override
|
|
149
|
+
public Animator getStatusBarPopAnimation(@NonNull Options appearingOptions, @NonNull Options disappearingOptions) {
|
|
150
|
+
StatusBarOptions statusBarOptions = appearingOptions.statusBar;
|
|
151
|
+
return getStatusBarColorAnimation(statusBarOptions);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private Animator getStatusBarColorAnimation(StatusBarOptions statusBarOptions) {
|
|
155
|
+
if (RNNFeatureToggles.isEnabled(RNNToggles.TOP_BAR_COLOR_ANIMATION)) {
|
|
156
|
+
ThemeColour targetColor = statusBarOptions.backgroundColor;
|
|
157
|
+
|
|
158
|
+
if (targetColor.hasValue()) {
|
|
159
|
+
boolean translucent = statusBarOptions.translucent.isTrue();
|
|
160
|
+
ValueAnimator animator = colorAnimator.getAnimation(
|
|
161
|
+
getCurrentStatusBarBackgroundColor(),
|
|
162
|
+
targetColor.get()
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
animator.addUpdateListener(animation ->
|
|
166
|
+
setStatusBarBackgroundColor((int) animation.getAnimatedValue(), translucent));
|
|
167
|
+
|
|
168
|
+
animator.addListener(onAnimatorEnd(animation -> {
|
|
169
|
+
hasPendingColorAnim = false;
|
|
170
|
+
return null;
|
|
171
|
+
}));
|
|
172
|
+
|
|
173
|
+
hasPendingColorAnim = true;
|
|
174
|
+
return animator;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
hasPendingColorAnim = false;
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
115
181
|
private void setTranslucent(StatusBarOptions options) {
|
|
116
182
|
Window window = activity.getWindow();
|
|
117
183
|
if (options.translucent.isTrue()) {
|
|
@@ -133,11 +199,14 @@ public class Presenter {
|
|
|
133
199
|
private void setStatusBarBackgroundColor(StatusBarOptions statusBar) {
|
|
134
200
|
if (statusBar.backgroundColor.canApplyValue()) {
|
|
135
201
|
final int statusBarBackgroundColor = getStatusBarBackgroundColor(statusBar);
|
|
136
|
-
|
|
137
|
-
statusBar.translucent.isTrue());
|
|
202
|
+
setStatusBarBackgroundColor(statusBarBackgroundColor, statusBar.translucent.isTrue());
|
|
138
203
|
}
|
|
139
204
|
}
|
|
140
205
|
|
|
206
|
+
private void setStatusBarBackgroundColor(int color, Boolean translucent) {
|
|
207
|
+
SystemUiUtils.setStatusBarColor(activity.getWindow(), color, translucent);
|
|
208
|
+
}
|
|
209
|
+
|
|
141
210
|
private boolean isDarkTextColorScheme(StatusBarOptions statusBar) {
|
|
142
211
|
if (statusBar.textColorScheme == TextColorScheme.Dark) {
|
|
143
212
|
return true;
|
|
@@ -153,6 +222,10 @@ public class Presenter {
|
|
|
153
222
|
return statusBar.backgroundColor.get(defaultColor);
|
|
154
223
|
}
|
|
155
224
|
|
|
225
|
+
private int getCurrentStatusBarBackgroundColor() {
|
|
226
|
+
return SystemUiUtils.getStatusBarColor(activity.getWindow());
|
|
227
|
+
}
|
|
228
|
+
|
|
156
229
|
private void setTextColorScheme(StatusBarOptions statusBar) {
|
|
157
230
|
final View view = activity.getWindow().getDecorView();
|
|
158
231
|
//View.post is a Workaround, added to solve internal Samsung
|
|
@@ -35,7 +35,7 @@ public class RootPresenter {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
public void setRoot(ViewController appearingRoot, ViewController<?> disappearingRoot, Options defaultOptions, CommandListener listener, ReactInstanceManager reactInstanceManager) {
|
|
38
|
-
layoutDirectionApplier.apply(appearingRoot, defaultOptions
|
|
38
|
+
layoutDirectionApplier.apply(appearingRoot, defaultOptions);
|
|
39
39
|
rootLayout.addView(appearingRoot.getView(), matchParentWithBehaviour(new BehaviourDelegate(appearingRoot)));
|
|
40
40
|
Options options = appearingRoot.resolveCurrentOptions(defaultOptions);
|
|
41
41
|
AnimationOptions enter = options.animations.setRoot.getEnter();
|
|
@@ -27,6 +27,7 @@ import com.reactnativenavigation.utils.UiThread;
|
|
|
27
27
|
import com.reactnativenavigation.utils.UiUtils;
|
|
28
28
|
import com.reactnativenavigation.viewcontrollers.parent.ParentController;
|
|
29
29
|
import com.reactnativenavigation.viewcontrollers.stack.StackController;
|
|
30
|
+
import com.reactnativenavigation.viewcontrollers.stack.statusbar.StatusBarController;
|
|
30
31
|
import com.reactnativenavigation.viewcontrollers.viewcontroller.overlay.ViewControllerOverlay;
|
|
31
32
|
import com.reactnativenavigation.views.BehaviourAdapter;
|
|
32
33
|
import com.reactnativenavigation.views.component.Component;
|
|
@@ -91,6 +92,10 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
|
|
|
91
92
|
options = initialOptions.copy();
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
public StatusBarController getStatusBarController() {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
94
99
|
public void setWaitForRender(Bool waitForRender) {
|
|
95
100
|
this.waitForRender = waitForRender;
|
|
96
101
|
}
|
|
@@ -12,7 +12,7 @@ import com.reactnativenavigation.options.animations.ViewAnimationOptions
|
|
|
12
12
|
import com.reactnativenavigation.options.params.Bool
|
|
13
13
|
import com.reactnativenavigation.utils.resetViewProperties
|
|
14
14
|
|
|
15
|
-
open class
|
|
15
|
+
open class BaseViewAppearanceAnimator<T : View>(
|
|
16
16
|
private val hideDirection: HideDirection,
|
|
17
17
|
view: T? = null,
|
|
18
18
|
private val defaultAnimatorCreator: ViewAnimatorCreator = DefaultViewAnimatorCreator()
|
|
@@ -90,16 +90,16 @@ open class BaseViewAnimator<T : View>(
|
|
|
90
90
|
|
|
91
91
|
fun isAnimatingShow() = showAnimator.isRunning
|
|
92
92
|
|
|
93
|
-
fun getPushAnimation(
|
|
93
|
+
fun getPushAnimation(animationOpts: ViewAnimationOptions, visible: Bool, additionalDy: Float = 0f): Animator? {
|
|
94
94
|
if (isOrWillBeVisible && visible.isFalse) {
|
|
95
95
|
showAnimator.cancel()
|
|
96
|
-
hideAnimator =
|
|
96
|
+
hideAnimator = animationOpts.exit.getAnimation(view, defaultAnimatorCreator.getHideAnimator(view, hideDirection, additionalDy))
|
|
97
97
|
return hideAnimator
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
if (isOrWillBeHidden && visible.isTrueOrUndefined) {
|
|
101
101
|
hideAnimator.cancel()
|
|
102
|
-
showAnimator =
|
|
102
|
+
showAnimator = animationOpts.enter.getAnimation(view, defaultAnimatorCreator.getShowAnimator(view, hideDirection, additionalDy))
|
|
103
103
|
return showAnimator
|
|
104
104
|
}
|
|
105
105
|
|
package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ColorAnimator.kt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.reactnativenavigation.views.animations
|
|
2
|
+
|
|
3
|
+
import android.animation.ObjectAnimator
|
|
4
|
+
import android.animation.ValueAnimator
|
|
5
|
+
import android.view.View
|
|
6
|
+
|
|
7
|
+
class ColorAnimator {
|
|
8
|
+
fun getAnimation(from: Int, to: Int): ValueAnimator = createObjectAnimator(null, from, to)
|
|
9
|
+
fun getAnimation(view: View, from: Int, to: Int): ValueAnimator = createObjectAnimator(view, from, to)
|
|
10
|
+
|
|
11
|
+
private fun createObjectAnimator(view: View?, from: Int, to: Int) =
|
|
12
|
+
if (view == null) {
|
|
13
|
+
ObjectAnimator.ofArgb(from, to)
|
|
14
|
+
} else {
|
|
15
|
+
ObjectAnimator.ofArgb(
|
|
16
|
+
view,
|
|
17
|
+
view.BkgColorProperty,
|
|
18
|
+
from,
|
|
19
|
+
to,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -13,11 +13,11 @@ class DefaultViewAnimatorCreator : ViewAnimatorCreator {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
override fun getShowAnimator(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
view: View,
|
|
17
|
+
hideDirection: BaseViewAppearanceAnimator.HideDirection,
|
|
18
|
+
translationStart: Float
|
|
19
19
|
): Animator {
|
|
20
|
-
val direction = if (hideDirection ==
|
|
20
|
+
val direction = if (hideDirection == BaseViewAppearanceAnimator.HideDirection.Up) 1 else -1
|
|
21
21
|
return ObjectAnimator.ofFloat(
|
|
22
22
|
view,
|
|
23
23
|
View.TRANSLATION_Y,
|
|
@@ -30,11 +30,11 @@ class DefaultViewAnimatorCreator : ViewAnimatorCreator {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
override fun getHideAnimator(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
view: View,
|
|
34
|
+
hideDirection: BaseViewAppearanceAnimator.HideDirection,
|
|
35
|
+
additionalDy: Float
|
|
36
36
|
): Animator {
|
|
37
|
-
val direction = if (hideDirection ==
|
|
37
|
+
val direction = if (hideDirection == BaseViewAppearanceAnimator.HideDirection.Up) -1 else 1
|
|
38
38
|
return ObjectAnimator.ofFloat(
|
|
39
39
|
view,
|
|
40
40
|
View.TRANSLATION_Y,
|
|
@@ -4,6 +4,6 @@ import android.animation.Animator
|
|
|
4
4
|
import android.view.View
|
|
5
5
|
|
|
6
6
|
interface ViewAnimatorCreator {
|
|
7
|
-
fun getShowAnimator(view: View, hideDirection:
|
|
8
|
-
fun getHideAnimator(view: View, hideDirection:
|
|
7
|
+
fun getShowAnimator(view: View, hideDirection: BaseViewAppearanceAnimator.HideDirection, translationStart: Float): Animator
|
|
8
|
+
fun getHideAnimator(view: View, hideDirection: BaseViewAppearanceAnimator.HideDirection, additionalDy: Float): Animator
|
|
9
9
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.reactnativenavigation.views.animations
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.ColorDrawable
|
|
4
|
+
import android.util.Property
|
|
5
|
+
import android.view.View
|
|
6
|
+
|
|
7
|
+
val View.BkgColorProperty: Property<View, Int>
|
|
8
|
+
// TODO Replace Property with IntProperty (Requires SDK≥24)
|
|
9
|
+
get() = object: Property<View, Int>(Int::class.java, "bkgColor") {
|
|
10
|
+
override fun set(view: View, value: Int) {
|
|
11
|
+
(view.background as ColorDrawable).color = value
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun get(view: View): Int {
|
|
15
|
+
return (view.background as ColorDrawable).color
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -4,21 +4,23 @@ import android.animation.Animator
|
|
|
4
4
|
import android.animation.ObjectAnimator
|
|
5
5
|
import android.view.View
|
|
6
6
|
import android.view.ViewGroup
|
|
7
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
8
|
+
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
|
|
7
9
|
import com.facebook.react.views.text.ReactTextView
|
|
8
|
-
import com.facebook.react.views.view.ReactViewBackgroundDrawable
|
|
9
10
|
import com.reactnativenavigation.options.SharedElementTransitionOptions
|
|
10
11
|
import com.reactnativenavigation.utils.*
|
|
11
12
|
|
|
13
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
12
14
|
class BackgroundColorAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(from, to) {
|
|
13
15
|
override fun shouldAnimateProperty(fromChild: ViewGroup, toChild: ViewGroup): Boolean {
|
|
14
|
-
return fromChild.background is
|
|
15
|
-
toChild.background is
|
|
16
|
+
return fromChild.background is CSSBackgroundDrawable &&
|
|
17
|
+
toChild.background is CSSBackgroundDrawable && (fromChild.background as CSSBackgroundDrawable).color != (toChild.background as CSSBackgroundDrawable).color
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
override fun excludedViews() = listOf(ReactTextView::class.java)
|
|
19
21
|
|
|
20
22
|
override fun create(options: SharedElementTransitionOptions): Animator {
|
|
21
|
-
val backgroundColorEvaluator = BackgroundColorEvaluator(to.background as
|
|
23
|
+
val backgroundColorEvaluator = BackgroundColorEvaluator(to.background as CSSBackgroundDrawable)
|
|
22
24
|
val fromColor = ColorUtils.colorToLAB(ViewUtils.getBackgroundColor(from))
|
|
23
25
|
val toColor = ColorUtils.colorToLAB(ViewUtils.getBackgroundColor(to))
|
|
24
26
|
|
|
@@ -2,11 +2,13 @@ package com.reactnativenavigation.views.element.animators
|
|
|
2
2
|
|
|
3
3
|
import android.animation.TypeEvaluator
|
|
4
4
|
import androidx.core.graphics.ColorUtils
|
|
5
|
-
import com.facebook.react.
|
|
5
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
6
|
+
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
|
|
6
7
|
|
|
7
|
-
class BackgroundColorEvaluator(private val background:
|
|
8
|
+
class BackgroundColorEvaluator @OptIn(UnstableReactNativeAPI::class) constructor(private val background: CSSBackgroundDrawable) : TypeEvaluator<DoubleArray> {
|
|
8
9
|
private val color = DoubleArray(3)
|
|
9
10
|
|
|
11
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
10
12
|
override fun evaluate(ratio: Float, from: DoubleArray, to: DoubleArray): DoubleArray {
|
|
11
13
|
ColorUtils.blendLAB(from, to, ratio.toDouble(), color)
|
|
12
14
|
background.color = com.reactnativenavigation.utils.ColorUtils.labToColor(color)
|
|
@@ -49,17 +49,17 @@ class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView{
|
|
|
49
49
|
updateFirstChildView()
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
override fun onChildStartedNativeGesture(child: View, androidEvent: MotionEvent
|
|
52
|
+
override fun onChildStartedNativeGesture(child: View, androidEvent: MotionEvent) {
|
|
53
53
|
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, this.getEventDispatcher())
|
|
54
54
|
}
|
|
55
|
-
override fun onChildStartedNativeGesture(androidEvent: MotionEvent
|
|
55
|
+
override fun onChildStartedNativeGesture(androidEvent: MotionEvent) {
|
|
56
56
|
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, this.getEventDispatcher())
|
|
57
57
|
}
|
|
58
|
-
override fun onChildEndedNativeGesture(child: View, androidEvent: MotionEvent
|
|
58
|
+
override fun onChildEndedNativeGesture(child: View, androidEvent: MotionEvent) {
|
|
59
59
|
mJSTouchDispatcher.onChildEndedNativeGesture(androidEvent, this.getEventDispatcher())
|
|
60
60
|
}
|
|
61
61
|
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
|
|
62
|
-
private fun getEventDispatcher(): EventDispatcher
|
|
62
|
+
private fun getEventDispatcher(): EventDispatcher {
|
|
63
63
|
val reactContext: ReactContext = this.getReactContext()
|
|
64
64
|
return reactContext.getNativeModule(UIManagerModule::class.java)!!.eventDispatcher
|
|
65
65
|
}
|
|
@@ -73,12 +73,12 @@ class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView{
|
|
|
73
73
|
return this.context as ReactContext
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
override fun onInterceptTouchEvent(event: MotionEvent
|
|
76
|
+
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
|
77
77
|
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
|
|
78
78
|
return super.onInterceptTouchEvent(event)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
override fun onTouchEvent(event: MotionEvent
|
|
81
|
+
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
82
82
|
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
|
|
83
83
|
super.onTouchEvent(event)
|
|
84
84
|
return true
|