Skip to content

Commit 6ac2fb7

Browse files
authored
Introduce options to make a floating bottom-tabs (Android) (#8064) (#8071)
1 parent fb2522a commit 6ac2fb7

File tree

29 files changed

+610
-99
lines changed

29 files changed

+610
-99
lines changed

e2e/BottomTabs.test.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Utils from './Utils';
22
import TestIDs from '../playground/src/testIDs';
33
import Android from './AndroidUtils';
44

5-
const { elementByLabel, elementById } = Utils;
5+
const { elementByLabel, elementById, expectImagesToBeEqual } = Utils;
66

77
describe('BottomTabs', () => {
88
beforeEach(async () => {
@@ -79,6 +79,24 @@ describe('BottomTabs', () => {
7979
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeVisible();
8080
});
8181

82+
it.e2e(':android: should set special stylizing options in root bottom-tabs', async () => {
83+
await elementById(TestIDs.SCREEN_ROOT_LIST).scrollTo('bottom');
84+
await elementById(TestIDs.SET_ROOT_BTN).tap();
85+
const snapshotImagePath = `./e2e/assets/bottom_tabs.stylized-root.png`;
86+
const actual =
87+
await elementById('RNN.BottomTabsLayoutRoot').takeScreenshot(`bottom_tabs_stylized-root`);
88+
expectImagesToBeEqual(actual, snapshotImagePath);
89+
});
90+
91+
it.e2e(':android: should merge special stylizing options', async () => {
92+
await elementById(TestIDs.SCREEN_ROOT_LIST).scrollTo('bottom');
93+
await elementById(TestIDs.STYLIZE_TABS_BTN).tap();
94+
const snapshotImagePath = `./e2e/assets/bottom_tabs.stylized.png`;
95+
const actual =
96+
await elementById('RNN.BottomTabsLayoutRoot').takeScreenshot(`bottom_tabs_stylized`);
97+
expectImagesToBeEqual(actual, snapshotImagePath);
98+
});
99+
82100
it('hide Tab Bar on push', async () => {
83101
await elementById(TestIDs.HIDE_TABS_PUSH_BTN).tap();
84102
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeNotVisible();
196 KB
Loading

e2e/assets/bottom_tabs.stylized.png

223 KB
Loading

lib/android/app/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ dependencies {
9494
implementation 'androidx.annotation:annotation:1.2.0'
9595
implementation 'com.google.android.material:material:1.2.0-alpha03'
9696

97-
implementation 'com.github.wix-playground:ahbottomnavigation:3.3.0'
97+
implementation 'com.github.wix-playground:ahbottomnavigation:4.0.0'
98+
implementation 'com.github.Dimezis:BlurView:version-3.0.0'
9899
// implementation project(':AHBottomNavigation')
99100
implementation 'com.github.wix-playground:reflow-animator:1.0.6'
100101
implementation 'com.github.clans:fab:1.6.4'

lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import androidx.annotation.VisibleForTesting
55
enum class RNNToggles {
66
TOP_BAR_COLOR_ANIMATION__PUSH,
77
TOP_BAR_COLOR_ANIMATION__TABS,
8+
TAB_BAR_TRANSLUCENCE,
89
}
910

1011
private val ToggleDefaults = mapOf(
1112
RNNToggles.TOP_BAR_COLOR_ANIMATION__PUSH to false,
1213
RNNToggles.TOP_BAR_COLOR_ANIMATION__TABS to false,
14+
RNNToggles.TAB_BAR_TRANSLUCENCE to false,
1315
)
1416

1517
object RNNFeatureToggles {

lib/android/app/src/main/java/com/reactnativenavigation/options/BottomTabsOptions.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.content.Context;
44

55
import com.reactnativenavigation.options.params.Bool;
6+
import com.reactnativenavigation.options.params.BottomTabsLayoutStyle;
67
import com.reactnativenavigation.options.params.Fraction;
78
import com.reactnativenavigation.options.params.NullBool;
89
import com.reactnativenavigation.options.params.NullFraction;
@@ -27,6 +28,11 @@ public static BottomTabsOptions parse(Context context, JSONObject json) {
2728
if (json == null) return options;
2829

2930
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");
3036
options.currentTabId = TextParser.parse(json, "currentTabId");
3137
options.currentTabIndex = NumberParser.parse(json, "currentTabIndex");
3238
options.hideOnScroll = BoolParser.parse(json, "hideOnScroll");
@@ -46,6 +52,11 @@ public static BottomTabsOptions parse(Context context, JSONObject json) {
4652
}
4753

4854
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();
4960
public Bool hideOnScroll = new NullBool();
5061
public Bool visible = new NullBool();
5162
public Bool drawBehind = new NullBool();
@@ -79,12 +90,21 @@ void mergeWith(final BottomTabsOptions other) {
7990
if (other.shadowOptions.hasValue()) shadowOptions = shadowOptions.copy().mergeWith(other.shadowOptions);
8091
if (other.borderColor.hasValue()) borderColor = other.borderColor;
8192
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;
8398
}
8499

85100
void mergeWithDefault(final BottomTabsOptions defaultOptions) {
86101
if (!borderColor.hasValue()) borderColor = defaultOptions.borderColor;
87102
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;
88108
if (!currentTabId.hasValue()) currentTabId = defaultOptions.currentTabId;
89109
if (!currentTabIndex.hasValue()) currentTabIndex = defaultOptions.currentTabIndex;
90110
if (!hideOnScroll.hasValue()) hideOnScroll = defaultOptions.hideOnScroll;

lib/android/app/src/main/java/com/reactnativenavigation/options/LayoutDirection.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ public boolean hasValue() {
3535
}
3636

3737
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+
};
3944
}
4045

4146
public int inverse() {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

lib/android/app/src/main/java/com/reactnativenavigation/utils/ColorUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ public static boolean isColorLight(int color) {
2121
public static int setAlpha(int color, int alpha) {
2222
return (color & 0x00FFFFFF) | (alpha << 24);
2323
}
24+
25+
public static boolean isOpaque(int color) {
26+
return (color & 0xFF000000) == 0xFF000000;
27+
}
2428
}

lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,15 @@ public void onConfigurationChanged(Configuration newConfig) {
6363
tabPresenter.onConfigurationChanged(resolveCurrentOptions());
6464
}
6565

66-
public BottomTabsController(Activity activity, List<ViewController<?>> tabs, ChildControllersRegistry childRegistry, EventEmitter eventEmitter, ImageLoader imageLoader, String id, Options initialOptions, Presenter presenter, BottomTabsAttacher tabsAttacher, BottomTabsPresenter bottomTabsPresenter, BottomTabPresenter bottomTabPresenter) {
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) {
6775
super(activity, childRegistry, id, presenter, initialOptions);
6876
this.tabs = tabs;
6977
this.eventEmitter = eventEmitter;
@@ -86,15 +94,17 @@ public void setDefaultOptions(Options defaultOptions) {
8694
@Override
8795
public BottomTabsLayout createView() {
8896
BottomTabsLayout root = new BottomTabsLayout(getActivity());
97+
root.setTag("RNN.BottomTabsLayoutRoot");
8998

9099
this.bottomTabsContainer = createBottomTabsContainer();
91100
this.bottomTabs = bottomTabsContainer.getBottomTabs();
92101
Options resolveCurrentOptions = resolveCurrentOptions();
93102
tabsAttacher.init(root, resolveCurrentOptions);
94-
presenter.bindView(bottomTabsContainer, this);
103+
presenter.bindView(bottomTabsContainer, root, this);
95104
tabPresenter.bindView(bottomTabs);
96105
bottomTabs.setOnTabSelectedListener(this);
97106
root.addBottomTabsContainer(bottomTabsContainer);
107+
98108
bottomTabs.addItems(createTabs());
99109
setInitialTab(resolveCurrentOptions);
100110
tabsAttacher.attach();

0 commit comments

Comments
 (0)