Skip to content

Commit

Permalink
Support tabs without icons on Android (#5978)
Browse files Browse the repository at this point in the history
This commit introduces parity with iOS which allows the user to show tabs without icons. While there's no real production use case for this feature, it's helpful when getting started with a new project.
  • Loading branch information
guyca authored Mar 3, 2020
1 parent 30b0b47 commit ef58a6c
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 27 deletions.
2 changes: 1 addition & 1 deletion lib/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ dependencies {
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha03'

implementation 'com.github.wix-playground:ahbottomnavigation:3.1.2'
implementation 'com.github.wix-playground:ahbottomnavigation:3.2.0'
implementation 'com.github.wix-playground:reflow-animator:1.0.6'
implementation 'com.github.clans:fab:1.6.4'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.reactnativenavigation.viewcontrollers.bottomtabs.TabSelector;
import com.reactnativenavigation.views.BottomTabs;

import org.jetbrains.annotations.NotNull;

import java.util.List;

import androidx.annotation.IntRange;
Expand Down Expand Up @@ -118,7 +120,7 @@ private void applyBottomTabsOptions(Options options) {

bottomTabs.setLayoutDirection(options.layout.direction);
bottomTabs.setPreferLargeIcons(options.bottomTabsOptions.preferLargeIcons.get(false));
bottomTabs.setTitleState(bottomTabsOptions.titleDisplayMode.get(TitleState.SHOW_WHEN_ACTIVE));
bottomTabs.setTitleState(bottomTabsOptions.titleDisplayMode.get(getDefaultTitleState()));
bottomTabs.setBackgroundColor(bottomTabsOptions.backgroundColor.get(Color.WHITE));
if (bottomTabsOptions.currentTabIndex.hasValue()) {
int tabIndex = bottomTabsOptions.currentTabIndex.get();
Expand Down Expand Up @@ -148,6 +150,14 @@ private void applyBottomTabsOptions(Options options) {
}
}

@NotNull
private TitleState getDefaultTitleState() {
for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
if (bottomTabs.getItem(i).hasIcon()) return TitleState.SHOW_WHEN_ACTIVE;
}
return TitleState.ALWAYS_SHOW;
}

public void applyBottomInset(int bottomInset) {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) bottomTabs.getLayoutParams();
lp.bottomMargin = bottomInset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private List<AHBottomNavigationItem> createTabs() {
BottomTabOptions options = tab.resolveCurrentOptions().bottomTabOptions;
return new AHBottomNavigationItem(
options.text.get(""),
imageLoader.loadIcon(getActivity(), options.icon.get()),
imageLoader.loadIcon(getActivity(), options.icon.get(null)),
imageLoader.loadIcon(getActivity(), options.selectedIcon.get(null)),
options.testId.get("")
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;

import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
import com.reactnativenavigation.BaseTest;
import com.reactnativenavigation.TestUtils;
import com.reactnativenavigation.mocks.ImageLoaderMock;
import com.reactnativenavigation.mocks.SimpleViewController;
import com.reactnativenavigation.parse.Options;
import com.reactnativenavigation.parse.params.Bool;
import com.reactnativenavigation.parse.params.Colour;
import com.reactnativenavigation.parse.params.NullText;
import com.reactnativenavigation.parse.params.Number;
import com.reactnativenavigation.parse.params.Text;
import com.reactnativenavigation.presentation.BottomTabPresenter;
Expand Down Expand Up @@ -43,6 +45,7 @@
import edu.emory.mathcs.backport.java.util.Collections;

import static com.reactnativenavigation.TestUtils.hideBackButton;
import static com.reactnativenavigation.utils.ObjectUtils.perform;
import static org.assertj.core.api.Java6Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
Expand Down Expand Up @@ -74,32 +77,9 @@ public class BottomTabsControllerTest extends BaseTest {
@Override
public void beforeEach() {
activity = newActivity();
bottomTabs = spy(new BottomTabs(activity) {
@Override
public void superCreateItems() {

}
});
childRegistry = new ChildControllersRegistry();
eventEmitter = Mockito.mock(EventEmitter.class);

child1 = spy(new SimpleViewController(activity, childRegistry, "child1", tabOptions));
child2 = spy(new SimpleViewController(activity, childRegistry, "child2", tabOptions));
child3 = spy(new SimpleViewController(activity, childRegistry, "child3", tabOptions));
child4 = spy(createStack());
child5 = spy(new SimpleViewController(activity, childRegistry, "child5", tabOptions));
when(child5.handleBack(any())).thenReturn(true);
tabs = createTabs();
presenter = spy(new BottomTabsPresenter(tabs, new Options()));
bottomTabPresenter = spy(new BottomTabPresenter(activity, tabs, ImageLoaderMock.mock(), new Options()));
tabsAttacher = spy(new BottomTabsAttacher(tabs, presenter));
uut = createBottomTabs();

uut.setParentController(Mockito.mock(ParentController.class));
CoordinatorLayout parent = new CoordinatorLayout(activity);
parent.addView(uut.getView());
activity.setContentView(parent);

prepareViewsForTests();
StatusBarUtils.saveStatusBarHeight(63);
}

Expand All @@ -110,6 +90,22 @@ public void createView_checkProperStructure() {
assertThat(((CoordinatorLayout.LayoutParams) uut.getBottomTabs().getLayoutParams()).gravity).isEqualTo(Gravity.BOTTOM);
}

@Test
public void createView_tabsWithoutIconsAreAccepted() {
tabOptions.bottomTabOptions.icon = new NullText();
prepareViewsForTests();
assertThat(uut.getBottomTabs().getItemsCount()).isEqualTo(tabs.size());
}

@Test
public void createView_showTitlesWhenAllTabsDontHaveIcons() {
tabOptions.bottomTabOptions.icon = new NullText();
assertThat(tabOptions.bottomTabsOptions.titleDisplayMode.hasValue()).isFalse();
prepareViewsForTests();
presenter.applyOptions(Options.EMPTY);
assertThat(bottomTabs.getTitleState()).isEqualTo(AHBottomNavigation.TitleState.ALWAYS_SHOW);
}

@Test(expected = RuntimeException.class)
public void setTabs_ThrowWhenMoreThan5() {
tabs.add(new SimpleViewController(activity, childRegistry, "6", tabOptions));
Expand Down Expand Up @@ -393,6 +389,36 @@ public void destroy() {
verify(tabsAttacher).destroy();
}

private void prepareViewsForTests() {
perform(uut, ViewController::destroy);
bottomTabs = spy(new BottomTabs(activity) {
@Override
public void superCreateItems() {

}
});
createChildren();
tabs = createTabs();
presenter = spy(new BottomTabsPresenter(tabs, new Options()));
bottomTabPresenter = spy(new BottomTabPresenter(activity, tabs, ImageLoaderMock.mock(), new Options()));
tabsAttacher = spy(new BottomTabsAttacher(tabs, presenter));
uut = createBottomTabs();

uut.setParentController(Mockito.mock(ParentController.class));
CoordinatorLayout parent = new CoordinatorLayout(activity);
parent.addView(uut.getView());
activity.setContentView(parent);
}

private void createChildren() {
child1 = spy(new SimpleViewController(activity, childRegistry, "child1", tabOptions));
child2 = spy(new SimpleViewController(activity, childRegistry, "child2", tabOptions));
child3 = spy(new SimpleViewController(activity, childRegistry, "child3", tabOptions));
child4 = spy(createStack());
child5 = spy(new SimpleViewController(activity, childRegistry, "child5", tabOptions));
when(child5.handleBack(any())).thenReturn(true);
}

@NonNull
private List<ViewController> createTabs() {
return Arrays.asList(child1, child2, child3, child4, child5);
Expand Down

0 comments on commit ef58a6c

Please sign in to comment.