react-native-navigation 7.25.1 → 7.25.3

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 (34) hide show
  1. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java +7 -9
  2. package/lib/android/app/src/main/java/com/reactnativenavigation/options/BottomTabOptions.java +4 -0
  3. package/lib/android/app/src/main/java/com/reactnativenavigation/options/OverlayOptions.java +3 -2
  4. package/lib/android/app/src/main/java/com/reactnativenavigation/options/OverlayOptions.kt +31 -0
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/options/parsers/JSONParser.java +0 -2
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenter.java +2 -1
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +31 -4
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +6 -13
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +35 -11
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalStack.java +4 -0
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java +20 -6
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/overlay/OverlayManager.kt +104 -33
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/parent/ParentController.java +86 -9
  14. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuController.java +12 -0
  15. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +18 -1
  16. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +51 -0
  17. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +4 -2
  18. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonController.kt +7 -1
  19. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt +1 -1
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/RootPresenter.java +0 -1
  21. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +12 -0
  22. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabs.java +29 -1
  23. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsContainer.kt +1 -0
  24. package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsLayout.java +10 -1
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java +10 -2
  26. package/lib/android/app/src/main/java/com/reactnativenavigation/views/overlay/AttachedOverlayContainer.kt +69 -0
  27. package/lib/android/app/src/main/java/com/reactnativenavigation/views/overlay/ViewTooltip.java +921 -0
  28. package/lib/android/app/src/main/java/com/reactnativenavigation/views/sidemenu/SideMenuRoot.java +9 -1
  29. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/StackLayout.java +14 -4
  30. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java +0 -1
  31. package/lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsStyleHelper.java +0 -1
  32. package/lib/dist/src/interfaces/Options.d.ts +25 -1
  33. package/lib/src/interfaces/Options.ts +27 -1
  34. package/package.json +1 -1
@@ -3,28 +3,26 @@ package com.reactnativenavigation;
3
3
  import android.annotation.TargetApi;
4
4
  import android.content.Intent;
5
5
  import android.content.res.Configuration;
6
- import android.graphics.Color;
7
6
  import android.os.Build;
8
7
  import android.os.Bundle;
9
8
  import android.view.KeyEvent;
10
9
  import android.view.View;
11
10
 
11
+ import androidx.annotation.NonNull;
12
+ import androidx.annotation.Nullable;
13
+ import androidx.appcompat.app.AppCompatActivity;
14
+
12
15
  import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
13
16
  import com.facebook.react.modules.core.PermissionAwareActivity;
14
17
  import com.facebook.react.modules.core.PermissionListener;
15
- import com.reactnativenavigation.options.Options;
16
- import com.reactnativenavigation.viewcontrollers.overlay.OverlayManager;
17
- import com.reactnativenavigation.viewcontrollers.viewcontroller.RootPresenter;
18
+ import com.reactnativenavigation.react.CommandListenerAdapter;
18
19
  import com.reactnativenavigation.react.JsDevReloadHandler;
19
20
  import com.reactnativenavigation.react.ReactGateway;
20
- import com.reactnativenavigation.react.CommandListenerAdapter;
21
21
  import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
22
22
  import com.reactnativenavigation.viewcontrollers.modal.ModalStack;
23
23
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
24
-
25
- import androidx.annotation.NonNull;
26
- import androidx.annotation.Nullable;
27
- import androidx.appcompat.app.AppCompatActivity;
24
+ import com.reactnativenavigation.viewcontrollers.overlay.OverlayManager;
25
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.RootPresenter;
28
26
 
29
27
  public class NavigationActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity, JsDevReloadHandler.ReloadListener {
30
28
  @Nullable
@@ -25,6 +25,7 @@ public class BottomTabOptions {
25
25
  BottomTabOptions options = new BottomTabOptions();
26
26
  if (json == null) return options;
27
27
 
28
+ options.id = TextParser.parse(json, "id");
28
29
  options.text = TextParser.parse(json, "text");
29
30
  options.textColor = ThemeColour.parse(context, json.optJSONObject("textColor"));
30
31
  options.selectedTextColor = ThemeColour.parse(context, json.optJSONObject("selectedTextColor"));
@@ -48,6 +49,7 @@ public class BottomTabOptions {
48
49
  return options;
49
50
  }
50
51
 
52
+ public Text id = new NullText();
51
53
  public Text text = new NullText();
52
54
  public ThemeColour textColor = new NullThemeColour();
53
55
  public ThemeColour selectedTextColor = new NullThemeColour();
@@ -70,6 +72,7 @@ public class BottomTabOptions {
70
72
 
71
73
 
72
74
  void mergeWith(final BottomTabOptions other) {
75
+ if (other.id.hasValue()) id = other.id;
73
76
  if (other.textColor.hasValue()) textColor = other.textColor;
74
77
  if (other.selectedTextColor.hasValue()) selectedTextColor = other.selectedTextColor;
75
78
  if (other.iconColor.hasValue()) iconColor = other.iconColor;
@@ -93,6 +96,7 @@ public class BottomTabOptions {
93
96
  }
94
97
 
95
98
  void mergeWithDefault(final BottomTabOptions defaultOptions) {
99
+ if (!id.hasValue()) id = defaultOptions.id;
96
100
  if (!textColor.hasValue()) textColor = defaultOptions.textColor;
97
101
  if (!selectedTextColor.hasValue()) selectedTextColor = defaultOptions.selectedTextColor;
98
102
  if (!iconColor.hasValue()) iconColor = defaultOptions.iconColor;
@@ -1,3 +1,4 @@
1
+
1
2
  package com.reactnativenavigation.options;
2
3
 
3
4
  import com.reactnativenavigation.options.params.Bool;
@@ -8,11 +9,11 @@ import org.json.JSONObject;
8
9
 
9
10
  public class OverlayOptions {
10
11
  public Bool interceptTouchOutside = new NullBool();
11
-
12
+ public OverlayAttachOptions overlayAttachOptions = new OverlayAttachOptions();
12
13
  public static OverlayOptions parse(JSONObject json) {
13
14
  OverlayOptions options = new OverlayOptions();
14
15
  if (json == null) return options;
15
-
16
+ options.overlayAttachOptions = OverlayAttachOptions.parse(json.optJSONObject("attach"));
16
17
  options.interceptTouchOutside = BoolParser.parse(json,"interceptTouchOutside");
17
18
  return options;
18
19
  }
@@ -0,0 +1,31 @@
1
+ package com.reactnativenavigation.options
2
+
3
+ import com.reactnativenavigation.options.params.NullText
4
+ import com.reactnativenavigation.options.params.Text
5
+ import com.reactnativenavigation.options.parsers.TextParser
6
+ import org.json.JSONObject
7
+ class OverlayAttachOptions{
8
+
9
+ @JvmField
10
+ var layoutId :Text = NullText()
11
+ @JvmField
12
+ var anchorId :Text = NullText()
13
+ @JvmField
14
+ var gravity:Text = NullText()
15
+
16
+ fun hasValue() = layoutId.hasValue()
17
+ override fun toString(): String {
18
+ return "OverlayAttachOptions(layoutId=$layoutId, anchorId=$anchorId, gravity=$gravity)"
19
+ }
20
+
21
+ companion object{
22
+ @JvmStatic
23
+ fun parse(json: JSONObject?): OverlayAttachOptions {
24
+ val overlayAttachOptions = OverlayAttachOptions()
25
+ overlayAttachOptions.layoutId = TextParser.parse(json,"layoutId")
26
+ overlayAttachOptions.anchorId = TextParser.parse(json?.optJSONObject("anchor"),"id")
27
+ overlayAttachOptions.gravity = TextParser.parse(json?.optJSONObject("anchor"),"gravity")
28
+ return overlayAttachOptions
29
+ }
30
+ }
31
+ }
@@ -6,8 +6,6 @@ import com.facebook.react.bridge.ReadableMap;
6
6
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
7
7
  import com.facebook.react.bridge.WritableArray;
8
8
  import com.facebook.react.bridge.WritableMap;
9
- import com.facebook.react.bridge.WritableNativeArray;
10
- import com.facebook.react.bridge.WritableNativeMap;
11
9
 
12
10
  import org.json.JSONArray;
13
11
  import org.json.JSONException;
@@ -9,7 +9,6 @@ import android.graphics.drawable.Drawable;
9
9
 
10
10
  import androidx.annotation.NonNull;
11
11
 
12
- import com.aurelhubert.ahbottomnavigation.AHTextView;
13
12
  import com.aurelhubert.ahbottomnavigation.notification.AHNotification;
14
13
  import com.reactnativenavigation.options.BottomTabOptions;
15
14
  import com.reactnativenavigation.options.DotIndicatorOptions;
@@ -58,6 +57,7 @@ public class BottomTabPresenter {
58
57
  bottomTabs.perform(bottomTabs -> {
59
58
  for (int i = 0; i < tabs.size(); i++) {
60
59
  BottomTabOptions tab = tabs.get(i).resolveCurrentOptions(defaultOptions).bottomTabOptions;
60
+ bottomTabs.setTagForTabIndex(i, tab.id.get(null));
61
61
  bottomTabs.setIconWidth(i, tab.iconWidth.get(null));
62
62
  bottomTabs.setIconHeight(i, tab.iconHeight.get(null));
63
63
  bottomTabs.setTitleTypeface(i, tab.font.getTypeface(typefaceLoader, defaultTypeface));
@@ -87,6 +87,7 @@ public class BottomTabPresenter {
87
87
  int index = bottomTabFinder.findByControllerId(child.getId());
88
88
  if (index >= 0) {
89
89
  BottomTabOptions tab = options.bottomTabOptions;
90
+ if (tab.id.hasValue()) bottomTabs.setTagForTabIndex(index, tab.id.get());
90
91
  if (tab.iconWidth.hasValue()) bottomTabs.setIconWidth(index, tab.iconWidth.get(null));
91
92
  if (tab.iconHeight.hasValue()) bottomTabs.setIconHeight(index, tab.iconHeight.get(null));
92
93
  if (tab.font.hasValue()) bottomTabs.setTitleTypeface(index, tab.font.getTypeface(typefaceLoader, defaultTypeface));
@@ -1,5 +1,10 @@
1
1
  package com.reactnativenavigation.viewcontrollers.bottomtabs;
2
2
 
3
+ import static com.reactnativenavigation.utils.CollectionUtils.forEach;
4
+ import static com.reactnativenavigation.utils.CollectionUtils.map;
5
+ import static com.reactnativenavigation.utils.ObjectUtils.perform;
6
+ import static com.reactnativenavigation.views.bottomtabs.BottomTabs.TAB_NOT_FOUND;
7
+
3
8
  import android.animation.Animator;
4
9
  import android.app.Activity;
5
10
  import android.content.res.Configuration;
@@ -7,6 +12,7 @@ import android.view.View;
7
12
  import android.view.ViewGroup;
8
13
 
9
14
  import androidx.annotation.NonNull;
15
+ import androidx.annotation.Nullable;
10
16
  import androidx.annotation.RestrictTo;
11
17
  import androidx.coordinatorlayout.widget.CoordinatorLayout;
12
18
 
@@ -15,6 +21,7 @@ import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
15
21
  import com.reactnativenavigation.options.BottomTabOptions;
16
22
  import com.reactnativenavigation.options.HwBackBottomTabsBehaviour;
17
23
  import com.reactnativenavigation.options.Options;
24
+ import com.reactnativenavigation.options.OverlayAttachOptions;
18
25
  import com.reactnativenavigation.react.CommandListener;
19
26
  import com.reactnativenavigation.react.CommandListenerAdapter;
20
27
  import com.reactnativenavigation.react.events.EventEmitter;
@@ -25,6 +32,7 @@ import com.reactnativenavigation.viewcontrollers.parent.ParentController;
25
32
  import com.reactnativenavigation.viewcontrollers.stack.StackController;
26
33
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
27
34
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
35
+ import com.reactnativenavigation.views.overlay.ViewTooltip;
28
36
  import com.reactnativenavigation.views.bottomtabs.BottomTabs;
29
37
  import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer;
30
38
  import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout;
@@ -34,10 +42,6 @@ import java.util.Deque;
34
42
  import java.util.LinkedList;
35
43
  import java.util.List;
36
44
 
37
- import static com.reactnativenavigation.utils.CollectionUtils.forEach;
38
- import static com.reactnativenavigation.utils.CollectionUtils.map;
39
- import static com.reactnativenavigation.utils.ObjectUtils.perform;
40
-
41
45
  public class BottomTabsController extends ParentController<BottomTabsLayout> implements AHBottomNavigation.OnTabSelectedListener, TabSelector {
42
46
 
43
47
  private BottomTabsContainer bottomTabsContainer;
@@ -238,6 +242,29 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
238
242
  return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
239
243
  }
240
244
 
245
+ @Override
246
+ public ViewTooltip.TooltipView showAnchoredOverlay(@NonNull View anchorView, @NonNull OverlayAttachOptions overlayAttachOptions,
247
+ @NonNull ViewController<?> overlayViewController) {
248
+ if(view!=null){
249
+ return view.getAttachedOverlayContainer().addAnchoredView(anchorView, overlayViewController.getView(),
250
+ overlayAttachOptions.gravity.get());
251
+ }
252
+ return null;
253
+ }
254
+
255
+ public View getTabViewByTag(String id) {
256
+ int tabIndex = bottomTabs.getTabIndexByTag(id);
257
+ if (tabIndex != TAB_NOT_FOUND) {
258
+ return bottomTabs.getViewAtPosition(tabIndex);
259
+ }
260
+ return null;
261
+ }
262
+
263
+ @Override
264
+ public List<ViewController<?>> getChildren() {
265
+ return tabs;
266
+ }
267
+
241
268
  @Override
242
269
  public int getBottomInset(ViewController<?> child) {
243
270
  return presenter.getBottomInset(resolveChildOptions(child)) + perform(getParentController(), 0, p -> p.getBottomInset(this));
@@ -2,28 +2,21 @@ package com.reactnativenavigation.viewcontrollers.child;
2
2
 
3
3
  import android.app.Activity;
4
4
  import android.content.res.Configuration;
5
- import android.os.Build;
6
- import android.util.Log;
7
5
  import android.view.View;
8
6
  import android.view.ViewGroup;
9
- import android.view.WindowInsets;
7
+
8
+ import androidx.annotation.CallSuper;
9
+ import androidx.core.view.ViewCompat;
10
+ import androidx.core.view.WindowInsetsCompat;
10
11
 
11
12
  import com.reactnativenavigation.options.Options;
12
- import com.reactnativenavigation.utils.LogKt;
13
- import com.reactnativenavigation.viewcontrollers.parent.ParentController;
14
- import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
15
- import com.reactnativenavigation.viewcontrollers.viewcontroller.NoOpYellowBoxDelegate;
16
13
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
14
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.NoOpYellowBoxDelegate;
15
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
17
16
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
18
17
  import com.reactnativenavigation.viewcontrollers.viewcontroller.overlay.ViewControllerOverlay;
19
18
  import com.reactnativenavigation.views.component.Component;
20
19
 
21
- import androidx.annotation.CallSuper;
22
- import androidx.core.graphics.Insets;
23
- import androidx.core.view.ViewCompat;
24
- import androidx.core.view.WindowCompat;
25
- import androidx.core.view.WindowInsetsCompat;
26
-
27
20
  public abstract class ChildController<T extends ViewGroup> extends ViewController<T> {
28
21
  private final Presenter presenter;
29
22
  private final ChildControllersRegistry childRegistry;
@@ -3,8 +3,9 @@ package com.reactnativenavigation.viewcontrollers.component;
3
3
  import android.app.Activity;
4
4
  import android.content.res.Configuration;
5
5
  import android.view.View;
6
+ import android.view.ViewGroup;
6
7
 
7
- import com.reactnativenavigation.utils.LogKt;
8
+ import com.reactnativenavigation.options.OverlayAttachOptions;
8
9
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
9
10
  import com.reactnativenavigation.options.Options;
10
11
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
@@ -13,9 +14,11 @@ import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator
13
14
  import com.reactnativenavigation.viewcontrollers.child.ChildController;
14
15
  import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
15
16
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
17
+ import com.reactnativenavigation.views.overlay.ViewTooltip;
16
18
  import com.reactnativenavigation.views.component.ComponentLayout;
17
19
 
18
20
  import androidx.annotation.NonNull;
21
+ import androidx.annotation.Nullable;
19
22
  import androidx.core.graphics.Insets;
20
23
  import androidx.core.view.ViewCompat;
21
24
  import androidx.core.view.WindowInsetsCompat;
@@ -26,6 +29,11 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
26
29
  private final String componentName;
27
30
  private final ComponentPresenter presenter;
28
31
  private final ReactViewCreator viewCreator;
32
+ private boolean ignoreInsets = false;
33
+
34
+ public void ignoreInsets(boolean ignore) {
35
+ ignoreInsets = ignore;
36
+ }
29
37
 
30
38
  private enum VisibilityState {Appear, Disappear}
31
39
 
@@ -78,14 +86,17 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
78
86
  if (view != null)
79
87
  view.sendComponentWillStart();
80
88
  super.onViewDidAppear();
81
- view.requestApplyInsets();
82
- if (view != null && lastVisibilityState == VisibilityState.Disappear) view.sendComponentStart();
89
+ if (view != null) {
90
+ view.requestApplyInsets();
91
+ if (lastVisibilityState == VisibilityState.Disappear)
92
+ view.sendComponentStart();
93
+ }
83
94
  lastVisibilityState = VisibilityState.Appear;
84
95
  }
85
96
 
86
97
  @Override
87
98
  public void onViewDisappear() {
88
- if(lastVisibilityState == VisibilityState.Disappear)return;
99
+ if (lastVisibilityState == VisibilityState.Disappear) return;
89
100
  lastVisibilityState = VisibilityState.Disappear;
90
101
  if (view != null) view.sendComponentStop();
91
102
  super.onViewDisappear();
@@ -125,7 +136,7 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
125
136
 
126
137
  @Override
127
138
  public void applyTopInset() {
128
- if (view != null) presenter.applyTopInsets(view, getTopInset());
139
+ if (view != null && !ignoreInsets) presenter.applyTopInsets(view, getTopInset());
129
140
  }
130
141
 
131
142
  @Override
@@ -137,22 +148,26 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
137
148
 
138
149
  @Override
139
150
  public void applyBottomInset() {
140
- if (view != null) presenter.applyBottomInset(view, getBottomInset());
151
+ if (view != null && !ignoreInsets) presenter.applyBottomInset(view, getBottomInset());
141
152
  }
142
153
 
143
154
  @Override
144
155
  protected WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
145
156
  ViewController<?> viewController = findController(view);
146
- if (viewController == null || viewController.getView() == null) return insets;
147
- final int keyboardBottomInset = options.layout.adjustResize.get(true) ? insets.getInsets( WindowInsetsCompat.Type.ime()).bottom : 0;
148
- final Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() );
149
- final int visibleNavBar = resolveCurrentOptions(presenter.defaultOptions).navigationBar.isVisible.isTrueOrUndefined()?1:0;
157
+ if (viewController == null || viewController.getView() == null || ignoreInsets) return insets;
158
+ final Options currentOptions = resolveCurrentOptions(presenter.defaultOptions);
159
+
160
+ final int keyboardBottomInset = currentOptions.layout.adjustResize.get(true) ? insets.getInsets(WindowInsetsCompat.Type.ime()).bottom : 0;
161
+ final Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
162
+ final int visibleNavBar = currentOptions.navigationBar.isVisible.isTrueOrUndefined() ? 1 : 0;
163
+ final int controllerBottomInset = currentOptions.bottomTabsOptions.isHiddenOrDrawBehind() ? 0 : getBottomInset();
150
164
  final WindowInsetsCompat finalInsets = new WindowInsetsCompat.Builder().setInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime(),
151
165
  Insets.of(systemBarsInsets.left,
152
166
  0,
153
167
  systemBarsInsets.right,
154
- Math.max(visibleNavBar*systemBarsInsets.bottom,keyboardBottomInset))
168
+ Math.max(0, Math.max(visibleNavBar * systemBarsInsets.bottom, keyboardBottomInset) - controllerBottomInset))
155
169
  ).build();
170
+
156
171
  ViewCompat.onApplyWindowInsets(viewController.getView(), finalInsets);
157
172
  return insets;
158
173
  }
@@ -174,6 +189,15 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
174
189
  }
175
190
  }
176
191
 
192
+ @Override
193
+ public ViewTooltip.TooltipView showAnchoredOverlay(@NonNull View anchorView, @NonNull OverlayAttachOptions overlayAttachOptions, @NonNull ViewController<?> overlayViewController) {
194
+ if (view != null) {
195
+ return view.getAttachedOverlayContainer().addAnchoredView(anchorView, overlayViewController.getView(),
196
+ overlayAttachOptions.gravity.get());
197
+ }
198
+ return null;
199
+ }
200
+
177
201
  @Override
178
202
  public void onConfigurationChanged(Configuration newConfig) {
179
203
  super.onConfigurationChanged(newConfig);
@@ -14,6 +14,7 @@ import com.reactnativenavigation.viewcontrollers.viewcontroller.overlay.ModalOve
14
14
 
15
15
  import java.util.ArrayList;
16
16
  import java.util.EmptyStackException;
17
+ import java.util.LinkedList;
17
18
  import java.util.List;
18
19
 
19
20
  import androidx.annotation.Nullable;
@@ -142,6 +143,9 @@ public class ModalStack {
142
143
  public boolean isEmpty() {
143
144
  return modals.isEmpty();
144
145
  }
146
+ public List<ViewController<?>> getChildren(){
147
+ return new LinkedList<>(modals);
148
+ }
145
149
 
146
150
  public int size() {
147
151
  return modals.size();
@@ -82,6 +82,9 @@ public class Navigator extends ParentController<ViewGroup> {
82
82
  rootLayout = new CoordinatorLayout(getActivity());
83
83
  modalsLayout = new CoordinatorLayout(getActivity());
84
84
  overlaysLayout = new CoordinatorLayout(getActivity());
85
+ overlayManager.setFindController(this::findController);
86
+ overlayManager.setFindAnchorView(this::findTooltipAnchorView);
87
+ overlayManager.setMainOverlayContainer(overlaysLayout);
85
88
  }
86
89
 
87
90
 
@@ -124,7 +127,7 @@ public class Navigator extends ParentController<ViewGroup> {
124
127
 
125
128
  public void destroyViews() {
126
129
  modalStack.destroy();
127
- overlayManager.destroy(overlaysLayout);
130
+ overlayManager.destroy();
128
131
  destroyRoot();
129
132
  }
130
133
 
@@ -211,16 +214,27 @@ public class Navigator extends ParentController<ViewGroup> {
211
214
  modalStack.dismissAllModals(root, mergeOptions, listener);
212
215
  }
213
216
 
217
+ @Override
218
+ public List<ViewController<?>> getChildren() {
219
+ final List<ViewController<?>> children = modalStack.getChildren();
220
+ children.add(root);
221
+ return children;
222
+ }
223
+
214
224
  public void showOverlay(ViewController<?> overlay, CommandListener listener) {
215
- overlayManager.show(overlaysLayout, overlay, listener);
225
+ final Options options = overlay.resolveCurrentOptions();
226
+ overlayManager.show( overlay,options.overlayOptions, listener);
227
+
216
228
  }
217
229
 
218
230
  public void dismissOverlay(final String componentId, CommandListener listener) {
219
- overlayManager.dismiss(overlaysLayout, componentId, listener);
231
+ overlayManager.dismiss( componentId, listener);
232
+
220
233
  }
221
234
 
222
235
  public void dismissAllOverlays(CommandListener listener) {
223
- overlayManager.dismissAll(overlaysLayout, listener);
236
+ overlayManager.dismissAll();
237
+ listener.onSuccess("");
224
238
  }
225
239
 
226
240
  @Nullable
@@ -274,7 +288,7 @@ public class Navigator extends ParentController<ViewGroup> {
274
288
  overlayManager.onHostPause();
275
289
  if (!modalStack.isEmpty()) {
276
290
  modalStack.onHostPause();
277
- if(modalStack.peekDisplayedOverCurrentContext()){
291
+ if (modalStack.peekDisplayedOverCurrentContext()) {
278
292
  onViewDisappear();
279
293
  }
280
294
  } else {
@@ -286,7 +300,7 @@ public class Navigator extends ParentController<ViewGroup> {
286
300
  overlayManager.onHostResume();
287
301
  if (!modalStack.isEmpty()) {
288
302
  modalStack.onHostResume();
289
- if(modalStack.peekDisplayedOverCurrentContext()){
303
+ if (modalStack.peekDisplayedOverCurrentContext()) {
290
304
  onViewDidAppear();
291
305
  }
292
306
  } else {
@@ -3,74 +3,145 @@ package com.reactnativenavigation.viewcontrollers.overlay
3
3
  import android.content.res.Configuration
4
4
  import android.view.View
5
5
  import android.view.ViewGroup
6
+ import com.reactnativenavigation.options.OverlayAttachOptions
7
+ import com.reactnativenavigation.options.OverlayOptions
6
8
  import com.reactnativenavigation.react.CommandListener
7
9
  import com.reactnativenavigation.utils.CoordinatorLayoutUtils
10
+ import com.reactnativenavigation.utils.removeFromParent
11
+ import com.reactnativenavigation.viewcontrollers.component.ComponentViewController
8
12
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
9
13
  import com.reactnativenavigation.views.BehaviourDelegate
14
+ import com.reactnativenavigation.views.overlay.ViewTooltip
15
+
16
+ private fun View.closeNow() {
17
+ if (this is ViewTooltip.TooltipView) {
18
+ this.closeNow()
19
+ } else {
20
+ removeFromParent()
21
+ }
22
+ }
23
+
24
+ private class OverlayEntry(
25
+ var overlayView: View,
26
+ val viewController: ViewController<*>
27
+ )
10
28
 
11
29
  class OverlayManager {
12
- private val overlayRegistry = mutableMapOf<String, ViewController<*>>()
13
- fun show(overlaysContainer: ViewGroup, overlay: ViewController<*>, listener: CommandListener) {
14
- overlaysContainer.visibility = View.VISIBLE
15
- overlayRegistry[overlay.id] = overlay
16
- overlay.addOnAppearedListener {
17
- overlay.onViewDidAppear()
18
- listener.onSuccess(overlay.id)
30
+ private val overlayRegistry = mutableMapOf<String, OverlayEntry>()
31
+ var mainOverlayContainer: ViewGroup? = null
32
+ var findController: (String) -> ViewController<*>? = { null }
33
+ var findAnchorView: (OverlayAttachOptions) -> View? = { null }
34
+
35
+ fun show(overlayController: ViewController<*>, overlayOptions: OverlayOptions, listener: CommandListener) {
36
+ val overlayAttachOptions = overlayOptions.overlayAttachOptions
37
+ if (overlayAttachOptions.anchorId.hasValue()) {
38
+ anchorOverlayInParent(overlayAttachOptions, overlayController, listener)
39
+ } else {
40
+ attachOverlayToParent(overlayAttachOptions, overlayController, listener)
19
41
  }
20
- overlaysContainer.addView(
21
- overlay.view,
22
- CoordinatorLayoutUtils.matchParentWithBehaviour(BehaviourDelegate(overlay))
23
- )
42
+ }
43
+
44
+ private fun attachOverlayToParent(
45
+ overlayAttachOptions: OverlayAttachOptions,
46
+ overlayController: ViewController<*>,
47
+ listener: CommandListener
48
+ ) {
49
+ val parent = if (overlayAttachOptions.layoutId.hasValue()) {
50
+ findController(overlayAttachOptions.layoutId.get())?.view
51
+ } else mainOverlayContainer
52
+
53
+ parent?.let {
54
+ it.visibility = View.VISIBLE
55
+ registerOverlay(overlayController.view,overlayController, listener)
56
+ it.addView(
57
+ overlayController.view,
58
+ CoordinatorLayoutUtils.matchParentWithBehaviour(BehaviourDelegate(overlayController))
59
+ )
60
+ } ?: listener.onError("Cannot find layout with id " + overlayAttachOptions.layoutId)
61
+ }
62
+
63
+ private fun anchorOverlayInParent(
64
+ overlayAttachOptions: OverlayAttachOptions,
65
+ overlayController: ViewController<*>,
66
+ listener: CommandListener
67
+ ) {
68
+ val hostController = findController(overlayAttachOptions.layoutId.get())
69
+ if (hostController != null) {
70
+ val anchorView: View? = findAnchorView(overlayAttachOptions)
71
+ if (anchorView != null) {
72
+ if(overlayController is ComponentViewController){
73
+ overlayController.ignoreInsets(true)
74
+ }
75
+ val anchoredView =
76
+ hostController.showAnchoredOverlay(anchorView, overlayAttachOptions, overlayController)
77
+ anchoredView?.let {
78
+ registerOverlay(it,overlayController, listener)
79
+ } ?: listener.onError("Parent could not create anchored view, it could be null parent")
80
+ } else {
81
+ listener.onError("Cannot find anchor view with id " + overlayAttachOptions.anchorId)
82
+ }
83
+ } else {
84
+ listener.onError("Cannot find layout with id " + overlayAttachOptions.layoutId)
85
+ }
86
+ }
87
+
88
+ private fun registerOverlay(
89
+ view:View,
90
+ viewController: ViewController<*>,
91
+ listener: CommandListener
92
+ ) {
93
+ overlayRegistry[viewController.id] = OverlayEntry(view, viewController)
94
+ viewController.onViewDidAppear()
95
+ listener.onSuccess(viewController.id)
24
96
  }
25
97
 
26
98
  fun onConfigurationChanged(configuration: Configuration?) {
27
- overlayRegistry.values.forEach { controller -> controller.onConfigurationChanged(configuration) }
99
+ overlayRegistry.values.forEach { entry -> entry.viewController.onConfigurationChanged(configuration) }
28
100
  }
29
101
 
30
- fun dismiss(overlaysContainer: ViewGroup, componentId: String, listener: CommandListener) {
102
+ fun dismiss(componentId: String, listener: CommandListener) {
31
103
  val overlay = overlayRegistry.remove(componentId)
32
104
  if (overlay == null) {
33
105
  listener.onError("Could not dismiss Overlay. Overlay with id $componentId was not found.")
34
106
  } else {
35
- destroyOverlay(overlaysContainer, overlay)
107
+ destroyOverlay(overlay)
36
108
  listener.onSuccess(componentId)
37
109
  }
38
110
  }
39
111
 
40
- fun dismissAll(overlaysContainer: ViewGroup, listener: CommandListener) {
41
- destroy(overlaysContainer)
42
- listener.onSuccess("")
112
+ fun dismissAll() {
113
+ destroy()
43
114
  }
44
115
 
45
- fun destroy(overlaysContainer: ViewGroup) {
46
- val removedOverlays = overlayRegistry.values.map { overlay ->
47
- destroyOverlay(overlaysContainer, overlay)
48
- overlay.id
49
- }.toList()
50
- removedOverlays.forEach {
51
- overlayRegistry.remove(it)
116
+ fun destroy() {
117
+ val entries = overlayRegistry.entries
118
+ while (entries.isNotEmpty()) {
119
+ val first = entries.first()
120
+ val attachOverlayEntry = first.value
121
+ attachOverlayEntry.overlayView.closeNow()
122
+ attachOverlayEntry.viewController.destroy()
123
+ overlayRegistry.remove(first.key)
52
124
  }
125
+ mainOverlayContainer?.visibility = View.GONE
53
126
  }
54
127
 
55
128
  fun size() = overlayRegistry.size
56
129
 
57
130
  fun findControllerById(id: String?): ViewController<*>? {
58
- return overlayRegistry[id]
131
+ return overlayRegistry[id]?.viewController
59
132
  }
60
133
 
61
- private fun destroyOverlay(overlaysContainer: ViewGroup, overlay: ViewController<*>) {
62
- overlay.destroy()
63
- if (isEmpty) overlaysContainer.visibility = View.GONE
134
+ private fun destroyOverlay(overlay: OverlayEntry?) {
135
+ overlay?.overlayView?.closeNow()
136
+ overlay?.viewController?.destroy()
137
+ if (overlayRegistry.isEmpty()) mainOverlayContainer?.visibility = View.GONE
64
138
  }
65
139
 
66
- private val isEmpty: Boolean
67
- get() = size() == 0
68
-
69
140
  fun onHostPause() {
70
- overlayRegistry.values.forEach(ViewController<*>::onViewDisappear)
141
+ overlayRegistry.values.forEach { it.viewController.onViewDisappear() }
71
142
  }
72
143
 
73
144
  fun onHostResume() {
74
- overlayRegistry.values.forEach(ViewController<*>::onViewDidAppear)
145
+ overlayRegistry.values.forEach { it.viewController.onViewDidAppear() }
75
146
  }
76
147
  }