react-native-navigation 7.47.0 → 7.49.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/android/app/build.gradle +2 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt +2 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/options/BottomTabsOptions.java +21 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/options/LayoutDirection.java +6 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/options/params/BottomTabsLayoutStyle.kt +20 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ColorUtils.java +4 -0
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +12 -2
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +129 -11
- package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +2 -1
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabs.java +6 -6
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsContainer.kt +83 -5
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabsLayout.java +58 -6
- package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/ShadowLayout.kt +4 -8
- package/lib/dist/src/interfaces/Options.d.ts +46 -3
- package/lib/ios/RNNSideMenu/MMDrawerController/MMDrawerController.h +22 -0
- package/lib/ios/RNNSideMenu/MMDrawerController/MMDrawerController.m +782 -161
- package/lib/ios/RNNSideMenuPresenter.m +27 -0
- package/lib/ios/RNNSideMenuSideOptions.h +6 -0
- package/lib/ios/RNNSideMenuSideOptions.m +13 -1
- package/lib/src/interfaces/Options.ts +46 -3
- package/package.json +1 -1
|
@@ -196,7 +196,8 @@ dependencies {
|
|
|
196
196
|
implementation 'androidx.annotation:annotation:1.2.0'
|
|
197
197
|
implementation 'com.google.android.material:material:1.2.0-alpha03'
|
|
198
198
|
|
|
199
|
-
implementation 'com.github.wix-playground:ahbottomnavigation:
|
|
199
|
+
implementation 'com.github.wix-playground:ahbottomnavigation:4.0.0'
|
|
200
|
+
implementation 'com.github.Dimezis:BlurView:version-3.0.0'
|
|
200
201
|
// implementation project(':AHBottomNavigation')
|
|
201
202
|
implementation 'com.github.wix-playground:reflow-animator:1.0.6'
|
|
202
203
|
implementation 'com.github.clans:fab:1.6.4'
|
|
@@ -5,11 +5,13 @@ import androidx.annotation.VisibleForTesting
|
|
|
5
5
|
enum class RNNToggles {
|
|
6
6
|
TOP_BAR_COLOR_ANIMATION__PUSH,
|
|
7
7
|
TOP_BAR_COLOR_ANIMATION__TABS,
|
|
8
|
+
TAB_BAR_TRANSLUCENCE,
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
private val ToggleDefaults = mapOf(
|
|
11
12
|
RNNToggles.TOP_BAR_COLOR_ANIMATION__PUSH to false,
|
|
12
13
|
RNNToggles.TOP_BAR_COLOR_ANIMATION__TABS to false,
|
|
14
|
+
RNNToggles.TAB_BAR_TRANSLUCENCE to false,
|
|
13
15
|
)
|
|
14
16
|
|
|
15
17
|
object RNNFeatureToggles {
|
package/lib/android/app/src/main/java/com/reactnativenavigation/options/BottomTabsOptions.java
CHANGED
|
@@ -3,6 +3,7 @@ package com.reactnativenavigation.options;
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
|
|
5
5
|
import com.reactnativenavigation.options.params.Bool;
|
|
6
|
+
import com.reactnativenavigation.options.params.BottomTabsLayoutStyle;
|
|
6
7
|
import com.reactnativenavigation.options.params.Fraction;
|
|
7
8
|
import com.reactnativenavigation.options.params.NullBool;
|
|
8
9
|
import com.reactnativenavigation.options.params.NullFraction;
|
|
@@ -27,6 +28,11 @@ public class BottomTabsOptions {
|
|
|
27
28
|
if (json == null) return options;
|
|
28
29
|
|
|
29
30
|
options.backgroundColor = ThemeColour.parse(context, json.optJSONObject("backgroundColor"));
|
|
31
|
+
options.layoutStyle = BottomTabsLayoutStyle.fromString(json.optString("layoutStyle"));
|
|
32
|
+
options.bottomMargin = FractionParser.parse(json, "bottomMargin");
|
|
33
|
+
options.cornerRadius = FractionParser.parse(json, "cornerRadius");
|
|
34
|
+
options.translucent = BoolParser.parse(json, "translucent");
|
|
35
|
+
options.blurRadius = FractionParser.parse(json, "blurRadius");
|
|
30
36
|
options.currentTabId = TextParser.parse(json, "currentTabId");
|
|
31
37
|
options.currentTabIndex = NumberParser.parse(json, "currentTabIndex");
|
|
32
38
|
options.hideOnScroll = BoolParser.parse(json, "hideOnScroll");
|
|
@@ -46,6 +52,11 @@ public class BottomTabsOptions {
|
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
public ThemeColour backgroundColor = new NullThemeColour();
|
|
55
|
+
public BottomTabsLayoutStyle layoutStyle = BottomTabsLayoutStyle.LAYOUT_STYLE_UNDEFINED;
|
|
56
|
+
public Fraction bottomMargin = new NullFraction();
|
|
57
|
+
public Fraction cornerRadius = new NullFraction();
|
|
58
|
+
public Bool translucent = new NullBool();
|
|
59
|
+
public Fraction blurRadius = new NullFraction();
|
|
49
60
|
public Bool hideOnScroll = new NullBool();
|
|
50
61
|
public Bool visible = new NullBool();
|
|
51
62
|
public Bool drawBehind = new NullBool();
|
|
@@ -79,12 +90,21 @@ public class BottomTabsOptions {
|
|
|
79
90
|
if (other.shadowOptions.hasValue()) shadowOptions = shadowOptions.copy().mergeWith(other.shadowOptions);
|
|
80
91
|
if (other.borderColor.hasValue()) borderColor = other.borderColor;
|
|
81
92
|
if (other.backgroundColor.hasValue()) backgroundColor = other.backgroundColor;
|
|
82
|
-
|
|
93
|
+
if (other.translucent.hasValue()) translucent = other.translucent;
|
|
94
|
+
if (other.blurRadius.hasValue()) blurRadius = other.blurRadius;
|
|
95
|
+
if (other.layoutStyle.hasValue()) layoutStyle = other.layoutStyle;
|
|
96
|
+
if (other.bottomMargin.hasValue()) bottomMargin = other.bottomMargin;
|
|
97
|
+
if (other.cornerRadius.hasValue()) cornerRadius = other.cornerRadius;
|
|
83
98
|
}
|
|
84
99
|
|
|
85
100
|
void mergeWithDefault(final BottomTabsOptions defaultOptions) {
|
|
86
101
|
if (!borderColor.hasValue()) borderColor = defaultOptions.borderColor;
|
|
87
102
|
if (!backgroundColor.hasValue()) backgroundColor = defaultOptions.backgroundColor;
|
|
103
|
+
if (!translucent.hasValue()) translucent = defaultOptions.translucent;
|
|
104
|
+
if (!blurRadius.hasValue()) blurRadius = defaultOptions.blurRadius;
|
|
105
|
+
if (!layoutStyle.hasValue()) layoutStyle = defaultOptions.layoutStyle;
|
|
106
|
+
if (!bottomMargin.hasValue()) bottomMargin = defaultOptions.bottomMargin;
|
|
107
|
+
if (!cornerRadius.hasValue()) cornerRadius = defaultOptions.cornerRadius;
|
|
88
108
|
if (!currentTabId.hasValue()) currentTabId = defaultOptions.currentTabId;
|
|
89
109
|
if (!currentTabIndex.hasValue()) currentTabIndex = defaultOptions.currentTabIndex;
|
|
90
110
|
if (!hideOnScroll.hasValue()) hideOnScroll = defaultOptions.hideOnScroll;
|
package/lib/android/app/src/main/java/com/reactnativenavigation/options/LayoutDirection.java
CHANGED
|
@@ -35,7 +35,12 @@ public enum LayoutDirection {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
public int get() {
|
|
38
|
-
return direction
|
|
38
|
+
return switch (direction) {
|
|
39
|
+
case View.LAYOUT_DIRECTION_RTL -> RTL.direction;
|
|
40
|
+
case View.LAYOUT_DIRECTION_LTR -> LTR.direction;
|
|
41
|
+
case View.LAYOUT_DIRECTION_LOCALE -> LOCALE.direction;
|
|
42
|
+
default -> DEFAULT.direction;
|
|
43
|
+
};
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
public int inverse() {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.reactnativenavigation.options.params
|
|
2
|
+
|
|
3
|
+
enum class BottomTabsLayoutStyle {
|
|
4
|
+
STRETCH,
|
|
5
|
+
COMPACT,
|
|
6
|
+
LAYOUT_STYLE_UNDEFINED;
|
|
7
|
+
|
|
8
|
+
fun hasValue(): Boolean = (this != LAYOUT_STYLE_UNDEFINED)
|
|
9
|
+
|
|
10
|
+
companion object {
|
|
11
|
+
@JvmStatic
|
|
12
|
+
fun fromString(mode: String?): BottomTabsLayoutStyle {
|
|
13
|
+
return when (mode?.lowercase()) {
|
|
14
|
+
"stretch" -> STRETCH
|
|
15
|
+
"compact" -> COMPACT
|
|
16
|
+
else -> LAYOUT_STYLE_UNDEFINED
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -63,7 +63,15 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
63
63
|
tabPresenter.onConfigurationChanged(resolveCurrentOptions());
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
public BottomTabsController(Activity activity,
|
|
66
|
+
public BottomTabsController(Activity activity,
|
|
67
|
+
List<ViewController<?>> tabs,
|
|
68
|
+
ChildControllersRegistry childRegistry,
|
|
69
|
+
EventEmitter eventEmitter,
|
|
70
|
+
ImageLoader imageLoader,
|
|
71
|
+
String id, Options initialOptions,
|
|
72
|
+
Presenter presenter,
|
|
73
|
+
BottomTabsAttacher tabsAttacher,
|
|
74
|
+
BottomTabsPresenter bottomTabsPresenter, BottomTabPresenter bottomTabPresenter) {
|
|
67
75
|
super(activity, childRegistry, id, presenter, initialOptions);
|
|
68
76
|
this.tabs = tabs;
|
|
69
77
|
this.eventEmitter = eventEmitter;
|
|
@@ -86,15 +94,17 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
|
|
|
86
94
|
@Override
|
|
87
95
|
public BottomTabsLayout createView() {
|
|
88
96
|
BottomTabsLayout root = new BottomTabsLayout(getActivity());
|
|
97
|
+
root.setTag("RNN.BottomTabsLayoutRoot");
|
|
89
98
|
|
|
90
99
|
this.bottomTabsContainer = createBottomTabsContainer();
|
|
91
100
|
this.bottomTabs = bottomTabsContainer.getBottomTabs();
|
|
92
101
|
Options resolveCurrentOptions = resolveCurrentOptions();
|
|
93
102
|
tabsAttacher.init(root, resolveCurrentOptions);
|
|
94
|
-
presenter.bindView(bottomTabsContainer, this);
|
|
103
|
+
presenter.bindView(bottomTabsContainer, root, this);
|
|
95
104
|
tabPresenter.bindView(bottomTabs);
|
|
96
105
|
bottomTabs.setOnTabSelectedListener(this);
|
|
97
106
|
root.addBottomTabsContainer(bottomTabsContainer);
|
|
107
|
+
|
|
98
108
|
bottomTabs.addItems(createTabs());
|
|
99
109
|
setInitialTab(resolveCurrentOptions);
|
|
100
110
|
tabsAttacher.attach();
|
|
@@ -3,13 +3,20 @@ package com.reactnativenavigation.viewcontrollers.bottomtabs
|
|
|
3
3
|
import android.animation.Animator
|
|
4
4
|
import android.graphics.Color
|
|
5
5
|
import android.view.ViewGroup
|
|
6
|
+
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
|
6
7
|
import androidx.annotation.IntRange
|
|
7
8
|
import androidx.core.view.updateMargins
|
|
8
9
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation.TitleState
|
|
10
|
+
import com.reactnativenavigation.RNNFeatureToggles
|
|
11
|
+
import com.reactnativenavigation.RNNToggles.TAB_BAR_TRANSLUCENCE
|
|
9
12
|
import com.reactnativenavigation.options.Options
|
|
13
|
+
import com.reactnativenavigation.options.params.BottomTabsLayoutStyle
|
|
14
|
+
import com.reactnativenavigation.options.params.Fraction
|
|
15
|
+
import com.reactnativenavigation.utils.UiUtils
|
|
10
16
|
import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
|
|
11
17
|
import com.reactnativenavigation.views.bottomtabs.BottomTabs
|
|
12
18
|
import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer
|
|
19
|
+
import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout
|
|
13
20
|
import kotlin.math.max
|
|
14
21
|
import kotlin.math.roundToInt
|
|
15
22
|
|
|
@@ -20,12 +27,13 @@ class BottomTabsPresenter(
|
|
|
20
27
|
) {
|
|
21
28
|
private val bottomTabFinder: BottomTabFinder = BottomTabFinder(tabs)
|
|
22
29
|
private lateinit var bottomTabsContainer: BottomTabsContainer
|
|
30
|
+
private lateinit var bottomTabsLayout: BottomTabsLayout
|
|
23
31
|
private lateinit var bottomTabs: BottomTabs
|
|
24
32
|
private lateinit var tabSelector: TabSelector
|
|
25
33
|
private val defaultTitleState: TitleState
|
|
26
34
|
get() {
|
|
27
35
|
for (i in 0 until bottomTabs.itemsCount) {
|
|
28
|
-
if (bottomTabs.getItem(i)
|
|
36
|
+
if (bottomTabs.getItem(i)?.hasIcon() == true) return TitleState.SHOW_WHEN_ACTIVE
|
|
29
37
|
}
|
|
30
38
|
return TitleState.ALWAYS_SHOW
|
|
31
39
|
}
|
|
@@ -34,8 +42,9 @@ class BottomTabsPresenter(
|
|
|
34
42
|
this.defaultOptions = defaultOptions
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
fun bindView(bottomTabsContainer: BottomTabsContainer, tabSelector: TabSelector) {
|
|
45
|
+
fun bindView(bottomTabsContainer: BottomTabsContainer, bottomTabsLayout: BottomTabsLayout, tabSelector: TabSelector) {
|
|
38
46
|
this.bottomTabsContainer = bottomTabsContainer
|
|
47
|
+
this.bottomTabsLayout = bottomTabsLayout
|
|
39
48
|
this.bottomTabs = bottomTabsContainer.bottomTabs
|
|
40
49
|
this.tabSelector = tabSelector
|
|
41
50
|
animator.bindView(this.bottomTabs)
|
|
@@ -65,14 +74,51 @@ class BottomTabsPresenter(
|
|
|
65
74
|
|
|
66
75
|
private fun mergeBottomTabsOptions(options: Options, view: ViewController<*>) {
|
|
67
76
|
val bottomTabsOptions = options.bottomTabsOptions
|
|
68
|
-
|
|
69
|
-
if (bottomTabsOptions.
|
|
70
|
-
|
|
71
|
-
bottomTabs.
|
|
77
|
+
|
|
78
|
+
if (bottomTabsOptions.layoutStyle == BottomTabsLayoutStyle.COMPACT) {
|
|
79
|
+
bottomTabs.layoutParams.width = WRAP_CONTENT
|
|
80
|
+
bottomTabs.refresh()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (bottomTabsOptions.bottomMargin.hasValue()) {
|
|
84
|
+
val margin = extractBottomMarginPx(bottomTabsOptions.bottomMargin)
|
|
85
|
+
bottomTabsLayout.setBottomMargin(margin)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (bottomTabsOptions.cornerRadius.hasValue()) {
|
|
89
|
+
val radius = extractCornerRadius(bottomTabsOptions.cornerRadius)
|
|
90
|
+
bottomTabsContainer.setRoundedCorners(radius)
|
|
72
91
|
}
|
|
92
|
+
|
|
93
|
+
// Keep this before the translucent check below
|
|
73
94
|
if (bottomTabsOptions.backgroundColor.hasValue()) {
|
|
74
95
|
bottomTabsContainer.setBackgroundColor(bottomTabsOptions.backgroundColor.get())
|
|
75
96
|
}
|
|
97
|
+
|
|
98
|
+
if (RNNFeatureToggles.isEnabled(TAB_BAR_TRANSLUCENCE)) {
|
|
99
|
+
if (bottomTabsOptions.translucent.isTrue) {
|
|
100
|
+
if (bottomTabsOptions.blurRadius.hasValue()) {
|
|
101
|
+
bottomTabsContainer.setBlurRadius(bottomTabsOptions.blurRadius.get().toFloat())
|
|
102
|
+
}
|
|
103
|
+
if (bottomTabsOptions.backgroundColor.hasValue()) {
|
|
104
|
+
bottomTabsContainer.setBlurColor(bottomTabsOptions.backgroundColor.get())
|
|
105
|
+
}
|
|
106
|
+
bottomTabsContainer.enableBackgroundBlur()
|
|
107
|
+
} else if (bottomTabsOptions.translucent.isFalse) {
|
|
108
|
+
bottomTabsContainer.disableBackgroundBlur()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (bottomTabsOptions.elevation.hasValue()) {
|
|
113
|
+
bottomTabsContainer.setElevation(bottomTabsOptions.elevation)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (options.layout.direction.hasValue()) bottomTabs.setLayoutDirection(options.layout.direction)
|
|
117
|
+
if (bottomTabsOptions.preferLargeIcons.hasValue()) bottomTabs.setPreferLargeIcons(bottomTabsOptions.preferLargeIcons.get())
|
|
118
|
+
if (bottomTabsOptions.titleDisplayMode.hasValue()) {
|
|
119
|
+
bottomTabs.setTitleState(bottomTabsOptions.titleDisplayMode.toState())
|
|
120
|
+
}
|
|
121
|
+
|
|
76
122
|
if (bottomTabsOptions.animateTabSelection.hasValue()) {
|
|
77
123
|
bottomTabs.setAnimateTabSelection(bottomTabsOptions.animateTabSelection.get())
|
|
78
124
|
}
|
|
@@ -88,7 +134,7 @@ class BottomTabsPresenter(
|
|
|
88
134
|
if (tabIndex >= 0) tabSelector.selectTab(tabIndex)
|
|
89
135
|
}
|
|
90
136
|
if (bottomTabsOptions.hideOnScroll.hasValue()) {
|
|
91
|
-
bottomTabs.
|
|
137
|
+
bottomTabs.setBehaviorTranslationEnabled(bottomTabsOptions.hideOnScroll.get())
|
|
92
138
|
}
|
|
93
139
|
|
|
94
140
|
if (bottomTabsOptions.borderColor.hasValue()) {
|
|
@@ -140,10 +186,39 @@ class BottomTabsPresenter(
|
|
|
140
186
|
|
|
141
187
|
private fun applyBottomTabsOptions(options: Options) {
|
|
142
188
|
val bottomTabsOptions = options.bottomTabsOptions
|
|
189
|
+
if (bottomTabsOptions.layoutStyle == BottomTabsLayoutStyle.COMPACT) {
|
|
190
|
+
bottomTabs.layoutParams.width = WRAP_CONTENT
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (bottomTabsOptions.bottomMargin.hasValue()) {
|
|
194
|
+
val margin = extractBottomMarginPx(bottomTabsOptions.bottomMargin)
|
|
195
|
+
bottomTabsLayout.setBottomMargin(margin)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (bottomTabsOptions.cornerRadius.hasValue()) {
|
|
199
|
+
val radius = extractCornerRadius(bottomTabsOptions.cornerRadius)
|
|
200
|
+
bottomTabsContainer.setRoundedCorners(radius)
|
|
201
|
+
} else {
|
|
202
|
+
bottomTabsContainer.clearRoundedCorners()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (RNNFeatureToggles.isEnabled(TAB_BAR_TRANSLUCENCE) && bottomTabsOptions.translucent.isTrue) {
|
|
206
|
+
if (bottomTabsOptions.blurRadius.hasValue()) {
|
|
207
|
+
bottomTabsContainer.setBlurRadius(bottomTabsOptions.blurRadius.get().toFloat())
|
|
208
|
+
}
|
|
209
|
+
if (bottomTabsOptions.backgroundColor.hasValue()) {
|
|
210
|
+
bottomTabsContainer.setBlurColor(bottomTabsOptions.backgroundColor.get())
|
|
211
|
+
}
|
|
212
|
+
bottomTabsContainer.enableBackgroundBlur()
|
|
213
|
+
} else {
|
|
214
|
+
bottomTabsContainer.disableBackgroundBlur()
|
|
215
|
+
bottomTabsContainer.setBackgroundColor(bottomTabsOptions.backgroundColor.get(Color.WHITE)!!)
|
|
216
|
+
}
|
|
217
|
+
|
|
143
218
|
bottomTabs.setLayoutDirection(options.layout.direction)
|
|
144
219
|
bottomTabs.setPreferLargeIcons(options.bottomTabsOptions.preferLargeIcons[false])
|
|
145
|
-
bottomTabs.
|
|
146
|
-
|
|
220
|
+
bottomTabs.setTitleState(bottomTabsOptions.titleDisplayMode[defaultTitleState])
|
|
221
|
+
|
|
147
222
|
bottomTabs.setAnimateTabSelection(bottomTabsOptions.animateTabSelection.get(true))
|
|
148
223
|
if (bottomTabsOptions.currentTabIndex.hasValue()) {
|
|
149
224
|
val tabIndex = bottomTabsOptions.currentTabIndex.get()
|
|
@@ -174,6 +249,7 @@ class BottomTabsPresenter(
|
|
|
174
249
|
bottomTabs.hideBottomNavigation(false)
|
|
175
250
|
}
|
|
176
251
|
}
|
|
252
|
+
|
|
177
253
|
if (bottomTabsOptions.elevation.hasValue()) {
|
|
178
254
|
bottomTabsContainer.setElevation(bottomTabsOptions.elevation)
|
|
179
255
|
}
|
|
@@ -203,7 +279,7 @@ class BottomTabsPresenter(
|
|
|
203
279
|
} else {
|
|
204
280
|
bottomTabsContainer.clearShadow()
|
|
205
281
|
}
|
|
206
|
-
bottomTabs.
|
|
282
|
+
bottomTabs.setBehaviorTranslationEnabled(bottomTabsOptions.hideOnScroll[false])
|
|
207
283
|
}
|
|
208
284
|
|
|
209
285
|
fun applyBottomInset(bottomInset: Int) {
|
|
@@ -246,7 +322,37 @@ class BottomTabsPresenter(
|
|
|
246
322
|
|
|
247
323
|
fun onConfigurationChanged(options: Options) {
|
|
248
324
|
val bottomTabsOptions = options.withDefaultOptions(defaultOptions).bottomTabsOptions
|
|
249
|
-
|
|
325
|
+
|
|
326
|
+
if (bottomTabsOptions.layoutStyle == BottomTabsLayoutStyle.COMPACT) {
|
|
327
|
+
bottomTabs.layoutParams.width = WRAP_CONTENT
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (bottomTabsOptions.bottomMargin.hasValue()) {
|
|
331
|
+
val margin = extractBottomMarginPx(bottomTabsOptions.bottomMargin)
|
|
332
|
+
bottomTabsLayout.setBottomMargin(margin)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (bottomTabsOptions.cornerRadius.hasValue()) {
|
|
336
|
+
val radius = extractCornerRadius(bottomTabsOptions.cornerRadius)
|
|
337
|
+
bottomTabsContainer.setRoundedCorners(radius)
|
|
338
|
+
} else {
|
|
339
|
+
bottomTabsContainer.clearRoundedCorners()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (RNNFeatureToggles.isEnabled(TAB_BAR_TRANSLUCENCE) && bottomTabsOptions.translucent.isTrue) {
|
|
343
|
+
if (bottomTabsOptions.blurRadius.hasValue()) {
|
|
344
|
+
bottomTabsContainer.setBlurRadius(bottomTabsOptions.blurRadius.get().toFloat())
|
|
345
|
+
}
|
|
346
|
+
if (bottomTabsOptions.backgroundColor.hasValue()) {
|
|
347
|
+
bottomTabsContainer.setBlurColor(bottomTabsOptions.backgroundColor.get())
|
|
348
|
+
}
|
|
349
|
+
bottomTabsContainer.enableBackgroundBlur()
|
|
350
|
+
} else {
|
|
351
|
+
bottomTabsContainer.disableBackgroundBlur()
|
|
352
|
+
|
|
353
|
+
// TODO Change to bottomTabsContainer.setBackgroundColor()?
|
|
354
|
+
bottomTabs.setBackgroundColor(bottomTabsOptions.backgroundColor.get(Color.WHITE)!!)
|
|
355
|
+
}
|
|
250
356
|
|
|
251
357
|
if (bottomTabsOptions.shadowOptions.hasValue()) {
|
|
252
358
|
if (bottomTabsOptions.shadowOptions.color.hasValue())
|
|
@@ -258,4 +364,16 @@ class BottomTabsPresenter(
|
|
|
258
364
|
bottomTabsContainer.showTopLine()
|
|
259
365
|
}
|
|
260
366
|
}
|
|
367
|
+
|
|
368
|
+
private fun extractCornerRadius(cornerRadius: Fraction): Float {
|
|
369
|
+
val radiusDp = cornerRadius.get()
|
|
370
|
+
val radius = UiUtils.dpToPx(bottomTabsContainer.context, radiusDp.toFloat())
|
|
371
|
+
return radius
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
private fun extractBottomMarginPx(bottomMargin: Fraction): Int {
|
|
375
|
+
val marginDp = bottomMargin.get()
|
|
376
|
+
val margin = UiUtils.dpToPx(bottomTabsContainer.context, marginDp.toFloat()).roundToInt()
|
|
377
|
+
return margin
|
|
378
|
+
}
|
|
261
379
|
}
|
|
@@ -84,8 +84,9 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
|
|
|
84
84
|
@Override
|
|
85
85
|
public void onViewWillAppear() {
|
|
86
86
|
super.onViewWillAppear();
|
|
87
|
-
if (view != null)
|
|
87
|
+
if (view != null) {
|
|
88
88
|
view.sendComponentWillStart();
|
|
89
|
+
}
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
@Override
|
package/lib/android/app/src/main/java/com/reactnativenavigation/views/bottomtabs/BottomTabs.java
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
package com.reactnativenavigation.views.bottomtabs;
|
|
2
2
|
|
|
3
|
+
import static com.reactnativenavigation.utils.CollectionUtils.forEach;
|
|
4
|
+
import static com.reactnativenavigation.utils.ViewUtils.findChildByClass;
|
|
5
|
+
|
|
3
6
|
import android.annotation.SuppressLint;
|
|
4
7
|
import android.content.Context;
|
|
5
8
|
import android.graphics.Color;
|
|
@@ -7,6 +10,8 @@ import android.graphics.drawable.Drawable;
|
|
|
7
10
|
import android.view.View;
|
|
8
11
|
import android.widget.LinearLayout;
|
|
9
12
|
|
|
13
|
+
import androidx.annotation.IntRange;
|
|
14
|
+
|
|
10
15
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
|
|
11
16
|
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
|
|
12
17
|
import com.reactnativenavigation.R;
|
|
@@ -15,11 +20,6 @@ import com.reactnativenavigation.options.LayoutDirection;
|
|
|
15
20
|
import java.util.ArrayList;
|
|
16
21
|
import java.util.List;
|
|
17
22
|
|
|
18
|
-
import androidx.annotation.IntRange;
|
|
19
|
-
|
|
20
|
-
import static com.reactnativenavigation.utils.CollectionUtils.*;
|
|
21
|
-
import static com.reactnativenavigation.utils.ViewUtils.findChildByClass;
|
|
22
|
-
|
|
23
23
|
@SuppressLint("ViewConstructor")
|
|
24
24
|
public class BottomTabs extends AHBottomNavigation {
|
|
25
25
|
private boolean itemsCreationEnabled = true;
|
|
@@ -60,6 +60,7 @@ public class BottomTabs extends AHBottomNavigation {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
// TODO Find a better way to do this
|
|
63
64
|
public void superCreateItems() {
|
|
64
65
|
super.createItems();
|
|
65
66
|
}
|
|
@@ -77,7 +78,6 @@ public class BottomTabs extends AHBottomNavigation {
|
|
|
77
78
|
onItemCreationEnabled.add(() -> super.setCurrentItem(position, useCallback));
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
|
-
|
|
81
81
|
|
|
82
82
|
@Override
|
|
83
83
|
public void setTitleState(TitleState titleState) {
|
|
@@ -3,12 +3,20 @@ package com.reactnativenavigation.views.bottomtabs
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.graphics.Color
|
|
6
|
+
import android.graphics.Outline
|
|
7
|
+
import android.util.Log
|
|
6
8
|
import android.view.View
|
|
9
|
+
import android.view.ViewOutlineProvider
|
|
10
|
+
import android.widget.FrameLayout.LayoutParams.MATCH_PARENT
|
|
11
|
+
import android.widget.FrameLayout.LayoutParams.WRAP_CONTENT
|
|
7
12
|
import android.widget.LinearLayout
|
|
8
13
|
import androidx.annotation.RestrictTo
|
|
9
14
|
import androidx.core.graphics.ColorUtils
|
|
10
15
|
import com.reactnativenavigation.options.params.Fraction
|
|
11
16
|
import com.reactnativenavigation.utils.UiUtils.dpToPx
|
|
17
|
+
import eightbitlab.com.blurview.BlurTarget
|
|
18
|
+
import eightbitlab.com.blurview.BlurView
|
|
19
|
+
import java.lang.ref.WeakReference
|
|
12
20
|
import kotlin.math.roundToInt
|
|
13
21
|
|
|
14
22
|
|
|
@@ -20,16 +28,24 @@ internal const val DEFAULT_SHADOW_ANGLE = 270f
|
|
|
20
28
|
internal const val DEFAULT_TOP_OUTLINE_SIZE_PX = 1
|
|
21
29
|
internal const val DEFAULT_TOP_OUTLINE_COLOR = Color.DKGRAY
|
|
22
30
|
|
|
31
|
+
private const val LOG_TAG = "BottomTabs"
|
|
32
|
+
|
|
23
33
|
class TopOutlineView(context: Context) : View(context)
|
|
24
34
|
|
|
25
35
|
@SuppressLint("ViewConstructor")
|
|
26
36
|
class BottomTabsContainer(context: Context, val bottomTabs: BottomTabs) : ShadowLayout(context) {
|
|
27
37
|
|
|
38
|
+
private val blurringView: BlurView
|
|
39
|
+
private var blurringSurface = WeakReference<BlurTarget>(null)
|
|
40
|
+
private var blurEnabled: Boolean? = null
|
|
41
|
+
private var blurRadius: Float? = null
|
|
42
|
+
private var blurColor: Int? = null
|
|
43
|
+
|
|
28
44
|
var topOutLineView = TopOutlineView(context)
|
|
29
45
|
@RestrictTo(RestrictTo.Scope.TESTS, RestrictTo.Scope.SUBCLASSES) get
|
|
30
46
|
@RestrictTo(RestrictTo.Scope.TESTS) set(value) {
|
|
31
47
|
this.removeView(field)
|
|
32
|
-
addView(value, LayoutParams(
|
|
48
|
+
addView(value, LayoutParams(MATCH_PARENT, WRAP_CONTENT))
|
|
33
49
|
field = value
|
|
34
50
|
}
|
|
35
51
|
|
|
@@ -39,17 +55,23 @@ class BottomTabsContainer(context: Context, val bottomTabs: BottomTabs) : Shadow
|
|
|
39
55
|
shadowAngle = DEFAULT_SHADOW_ANGLE
|
|
40
56
|
shadowDistance = DEFAULT_SHADOW_DISTANCE
|
|
41
57
|
shadowColor = DEFAULT_SHADOW_COLOR
|
|
58
|
+
|
|
42
59
|
val linearLayout = LinearLayout(context).apply {
|
|
43
60
|
orientation = LinearLayout.VERTICAL
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
addView(topOutLineView, LayoutParams(MATCH_PARENT, DEFAULT_TOP_OUTLINE_SIZE_PX))
|
|
62
|
+
addView(bottomTabs, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
|
46
63
|
}
|
|
64
|
+
|
|
47
65
|
this.clipChildren = false
|
|
48
66
|
this.clipToPadding = false
|
|
49
67
|
setTopOutLineColor(DEFAULT_TOP_OUTLINE_COLOR)
|
|
50
68
|
this.topOutLineView.visibility = View.GONE
|
|
51
69
|
|
|
52
|
-
|
|
70
|
+
blurringView = BlurView(context).apply {
|
|
71
|
+
setBlurEnabled(false)
|
|
72
|
+
addView(linearLayout, WRAP_CONTENT, WRAP_CONTENT)
|
|
73
|
+
}
|
|
74
|
+
addView(blurringView, WRAP_CONTENT, WRAP_CONTENT)
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
override var shadowRadius: Float
|
|
@@ -70,6 +92,63 @@ class BottomTabsContainer(context: Context, val bottomTabs: BottomTabs) : Shadow
|
|
|
70
92
|
shadowColor = ColorUtils.setAlphaComponent(shadowColor, (opacity * 0xFF).roundToInt())
|
|
71
93
|
}
|
|
72
94
|
|
|
95
|
+
fun setBlurSurface(blurSurface: BlurTarget) {
|
|
96
|
+
if (blurSurface == blurringSurface.get()) {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
blurringSurface = WeakReference(blurSurface)
|
|
101
|
+
blurringView
|
|
102
|
+
.setupWith(blurSurface)
|
|
103
|
+
.setBlurEnabled(blurEnabled == true).apply {
|
|
104
|
+
if (blurRadius != null) {
|
|
105
|
+
setBlurRadius(blurRadius!!)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (blurColor != null) {
|
|
109
|
+
setOverlayColor(blurColor!!)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fun enableBackgroundBlur() {
|
|
115
|
+
blurringView.setBlurEnabled(true)
|
|
116
|
+
blurEnabled = true
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fun disableBackgroundBlur() {
|
|
120
|
+
blurringView.setBlurEnabled(false)
|
|
121
|
+
blurEnabled = false
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fun setBlurRadius(radius: Float) {
|
|
125
|
+
blurringView.setBlurRadius(radius)
|
|
126
|
+
blurRadius = radius
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun setBlurColor(color: Int) {
|
|
130
|
+
if (com.reactnativenavigation.utils.ColorUtils.isOpaque(color)) {
|
|
131
|
+
Log.w(LOG_TAG, "Opaque color (#${Integer.toHexString(color)}) set alongside blur-effect in bottom-tabs, rendering blur futile")
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
blurringView.setOverlayColor(color)
|
|
135
|
+
blurColor = color
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fun setRoundedCorners(radius: Float) {
|
|
139
|
+
this.outlineProvider = object: ViewOutlineProvider() {
|
|
140
|
+
override fun getOutline(view: View, outline: Outline) {
|
|
141
|
+
outline.setRoundRect(0, 0, view.width, view.height, radius)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
this.clipToOutline = true
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
fun clearRoundedCorners() {
|
|
148
|
+
this.outlineProvider = null
|
|
149
|
+
this.clipToOutline = true
|
|
150
|
+
}
|
|
151
|
+
|
|
73
152
|
fun showShadow() {
|
|
74
153
|
isShadowed = true
|
|
75
154
|
}
|
|
@@ -98,4 +177,3 @@ class BottomTabsContainer(context: Context, val bottomTabs: BottomTabs) : Shadow
|
|
|
98
177
|
setElevation(dpToPx(context, elevation.get().toFloat()))
|
|
99
178
|
}
|
|
100
179
|
}
|
|
101
|
-
|