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.
Files changed (67) hide show
  1. package/lib/Mock/Components/ComponentScreen.tsx +29 -15
  2. package/lib/Mock/Components/LayoutComponent.tsx +2 -2
  3. package/lib/Mock/index.js +2 -2
  4. package/lib/android/app/build.gradle +1 -0
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt +60 -0
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java +20 -4
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/options/ValueAnimationOptions.kt +3 -3
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java +3 -3
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalHostLayout.kt +1 -1
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactTypefaceUtils.java +3 -2
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactViewGroup.kt +4 -2
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StubAnimationListener.kt +19 -0
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +16 -10
  14. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java +6 -4
  15. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsAnimator.kt +2 -2
  16. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +7 -14
  17. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +37 -13
  18. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +24 -11
  19. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +13 -10
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/statusbar/StatusBarController.kt +9 -0
  21. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/statusbar/StatusBarPresenter.kt +9 -0
  22. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/{TopBarAnimator.kt → TopBarAppearanceAnimator.kt} +4 -2
  23. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarCollapseBehavior.kt +1 -1
  24. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +122 -27
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/LayoutDirectionApplier.kt +8 -4
  26. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +79 -6
  27. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/RootPresenter.java +1 -1
  28. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +5 -0
  29. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/{BaseViewAnimator.kt → BaseViewAppearanceAnimator.kt} +4 -4
  30. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ColorAnimator.kt +22 -0
  31. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/DefaultViewAnimatorCreator.kt +8 -8
  32. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewAnimatorCreator.kt +2 -2
  33. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewBkgColorProperty.kt +17 -0
  34. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorAnimator.kt +6 -4
  35. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorEvaluator.kt +4 -2
  36. package/lib/android/app/src/reactNative71/java/com/reactnativenavigation/react/modal/ModalContentLayout.kt +6 -6
  37. package/lib/dist/Mock/Application.d.ts +4 -6
  38. package/lib/dist/Mock/Components/BottomTabs.d.ts +9 -13
  39. package/lib/dist/Mock/Components/ComponentScreen.d.ts +5 -7
  40. package/lib/dist/Mock/Components/ComponentScreen.js +10 -3
  41. package/lib/dist/Mock/Components/LayoutComponent.d.ts +9 -13
  42. package/lib/dist/Mock/Components/Modals.d.ts +9 -13
  43. package/lib/dist/Mock/Components/NavigationButton.d.ts +11 -15
  44. package/lib/dist/Mock/Components/Overlays.d.ts +9 -13
  45. package/lib/dist/Mock/Components/Stack.d.ts +9 -13
  46. package/lib/dist/Mock/Components/TopBar.d.ts +7 -9
  47. package/lib/dist/Mock/connect.js +2 -1
  48. package/lib/dist/Mock/index.js +2 -2
  49. package/lib/dist/src/adapters/NativeEventsReceiver.js +1 -1
  50. package/lib/dist/src/adapters/TouchablePreview.d.ts +2 -2
  51. package/lib/dist/src/commands/LayoutType.js +1 -1
  52. package/lib/dist/src/commands/OptionsProcessor.js +8 -1
  53. package/lib/dist/src/components/Modal.d.ts +1 -1
  54. package/lib/dist/src/interfaces/CommandName.js +1 -1
  55. package/lib/dist/src/interfaces/Options.d.ts +33 -3
  56. package/lib/dist/src/interfaces/Options.js +2 -2
  57. package/lib/dist/src/types.d.ts +1 -0
  58. package/lib/ios/BottomTabsBasePresenter.m +3 -2
  59. package/lib/ios/RNNAppDelegate.mm +1 -2
  60. package/lib/ios/RNNConvert.h +2 -0
  61. package/lib/ios/RNNConvert.m +4 -0
  62. package/lib/ios/RNNStackPresenter.m +3 -2
  63. package/lib/src/adapters/NativeEventsReceiver.ts +3 -3
  64. package/lib/src/adapters/TouchablePreview.tsx +3 -3
  65. package/lib/src/commands/OptionsProcessor.ts +13 -2
  66. package/lib/src/interfaces/Options.ts +38 -3
  67. 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.BaseViewAnimator
3
+ import com.reactnativenavigation.views.animations.BaseViewAppearanceAnimator
4
4
  import com.reactnativenavigation.views.stack.topbar.TopBar
5
5
 
6
- class TopBarAnimator @JvmOverloads constructor(view: TopBar? = null) : BaseViewAnimator<TopBar>(HideDirection.Up, view) {
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: TopBarAnimator = TopBarAnimator(topBar)
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(private val animator: TopBarAnimator = TopBarAnimator()) {
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
- animator.bindView(view)
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
- if (appearingOptions.topBar.animate.isFalse) return null
56
- return animator.getPushAnimation(
57
- appearingOptions.animations.push.topBar,
58
- appearingOptions.topBar.visible,
59
- additionalDy
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
- if (appearingOptions.topBar.animate.isFalse) return null
65
- return animator.getPopAnimation(
66
- disappearingOptions.animations.pop.topBar,
67
- appearingOptions.topBar.visible
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 animator.getSetStackRootAnimation(
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) || animator.isAnimatingShow()) return
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) || animator.isAnimatingShow()) return
88
- animator.show(options, additionalDy)
142
+ if (ViewUtils.isVisible(view) || appearAnimator.isAnimatingShow()) return
143
+ appearAnimator.show(options, additionalDy)
89
144
  }
90
145
 
91
146
  fun hide() {
92
- if (!animator.isAnimatingHide()) view.visibility = View.GONE
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) || animator.isAnimatingHide()) return
97
- animator.hide(options, additionalDy)
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
- fun apply(root: ViewController<*>, options: Options, instanceManager: ReactInstanceManager) {
9
- if (options.layout.direction.hasValue() && instanceManager.currentReactContext != null) {
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.getInstance().allowRTL(instanceManager.currentReactContext, options.layout.direction.isRtl)
12
- I18nUtil.getInstance().forceRTL(instanceManager.currentReactContext, options.layout.direction.isRtl)
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
- public class Presenter {
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
- setStatusBarBackgroundColor(statusBar);
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
- SystemUiUtils.setStatusBarColor(activity.getWindow(), statusBarBackgroundColor,
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, reactInstanceManager);
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 BaseViewAnimator<T : View>(
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(animation: ViewAnimationOptions, visible: Bool, additionalDy: Float = 0f): Animator? {
93
+ fun getPushAnimation(animationOpts: ViewAnimationOptions, visible: Bool, additionalDy: Float = 0f): Animator? {
94
94
  if (isOrWillBeVisible && visible.isFalse) {
95
95
  showAnimator.cancel()
96
- hideAnimator = animation.exit.getAnimation(view, defaultAnimatorCreator.getHideAnimator(view, hideDirection, additionalDy))
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 = animation.enter.getAnimation(view, defaultAnimatorCreator.getShowAnimator(view, hideDirection, additionalDy))
102
+ showAnimator = animationOpts.enter.getAnimation(view, defaultAnimatorCreator.getShowAnimator(view, hideDirection, additionalDy))
103
103
  return showAnimator
104
104
  }
105
105
 
@@ -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
- view: View,
17
- hideDirection: BaseViewAnimator.HideDirection,
18
- translationStart: Float
16
+ view: View,
17
+ hideDirection: BaseViewAppearanceAnimator.HideDirection,
18
+ translationStart: Float
19
19
  ): Animator {
20
- val direction = if (hideDirection == BaseViewAnimator.HideDirection.Up) 1 else -1
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
- view: View,
34
- hideDirection: BaseViewAnimator.HideDirection,
35
- additionalDy: Float
33
+ view: View,
34
+ hideDirection: BaseViewAppearanceAnimator.HideDirection,
35
+ additionalDy: Float
36
36
  ): Animator {
37
- val direction = if (hideDirection == BaseViewAnimator.HideDirection.Up) -1 else 1
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: BaseViewAnimator.HideDirection, translationStart: Float): Animator
8
- fun getHideAnimator(view: View, hideDirection: BaseViewAnimator.HideDirection, additionalDy: Float): Animator
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 ReactViewBackgroundDrawable &&
15
- toChild.background is ReactViewBackgroundDrawable && (fromChild.background as ReactViewBackgroundDrawable).color != (toChild.background as ReactViewBackgroundDrawable).color
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 ReactViewBackgroundDrawable)
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.views.view.ReactViewBackgroundDrawable
5
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI
6
+ import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
6
7
 
7
- class BackgroundColorEvaluator(private val background: ReactViewBackgroundDrawable) : TypeEvaluator<DoubleArray> {
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?): Boolean {
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?): Boolean {
81
+ override fun onTouchEvent(event: MotionEvent): Boolean {
82
82
  mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
83
83
  super.onTouchEvent(event)
84
84
  return true