diff --git a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java index a7f97db53ae..16521339af0 100644 --- a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java +++ b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java @@ -68,6 +68,7 @@ public void destroy() { @Override public void mergeNavigationOptions(NavigationOptions options) { this.options.mergeWith(options); + applyOptions(this.options); } String getTabTitle() { diff --git a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsAdapter.java b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsAdapter.java index 225e33d175b..0db27558034 100644 --- a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsAdapter.java +++ b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsAdapter.java @@ -51,4 +51,8 @@ public void onPageSelected(int position) { public void onPageScrollStateChanged(int state) { } + + int getCurrentItem() { + return currentPage; + } } diff --git a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java index 38eb35f4232..3f35832c6bf 100644 --- a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java +++ b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java @@ -6,6 +6,7 @@ import com.reactnativenavigation.parse.NavigationOptions; import com.reactnativenavigation.presentation.NavigationOptionsListener; +import com.reactnativenavigation.utils.Task; import com.reactnativenavigation.viewcontrollers.ParentController; import com.reactnativenavigation.viewcontrollers.ViewController; import com.reactnativenavigation.views.TopTabsLayout; @@ -17,10 +18,12 @@ public class TopTabsController extends ParentController implements NavigationOpt private List tabs; private TopTabsLayout topTabsLayout; + private TopTabsAdapter adapter; public TopTabsController(Activity activity, String id, List tabs) { super(activity, id); this.tabs = tabs; + this.adapter = new TopTabsAdapter(tabs); for (ViewController tab : tabs) { tab.setParentController(this); } @@ -29,7 +32,7 @@ public TopTabsController(Activity activity, String id, List ta @NonNull @Override protected ViewGroup createView() { - topTabsLayout = new TopTabsLayout(getActivity(), tabs); + topTabsLayout = new TopTabsLayout(getActivity(), tabs, adapter); return topTabsLayout; } @@ -41,12 +44,12 @@ public Collection getChildControllers() { @Override public void onViewAppeared() { - topTabsLayout.performOnCurrentTab(TopTabController::onViewAppeared); + performOnCurrentTab(TopTabController::onViewAppeared); } @Override public void onViewDisappear() { - topTabsLayout.performOnCurrentTab(TopTabController::onViewDisappear); + performOnCurrentTab(TopTabController::onViewDisappear); } @Override @@ -62,4 +65,8 @@ public void mergeNavigationOptions(NavigationOptions options) { public void switchToTab(int index) { topTabsLayout.switchToTab(index); } + + private void performOnCurrentTab(Task task) { + task.run(tabs.get(adapter.getCurrentItem())); + } } diff --git a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsViewPager.java b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsViewPager.java index 83f612a4d08..c035fcf7716 100644 --- a/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsViewPager.java +++ b/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsViewPager.java @@ -16,18 +16,17 @@ public class TopTabsViewPager extends ViewPager { private static final int OFFSCREEN_PAGE_LIMIT = 99; private List tabs; - public TopTabsViewPager(Context context, List tabs) { + public TopTabsViewPager(Context context, List tabs, TopTabsAdapter adapter) { super(context); this.tabs = tabs; - init(); + init(adapter); } - private void init() { + private void init(TopTabsAdapter adapter) { setOffscreenPageLimit(OFFSCREEN_PAGE_LIMIT); for (ViewController tab : tabs) { addView(tab.getView(), new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); } - TopTabsAdapter adapter = new TopTabsAdapter(tabs); setAdapter(adapter); addOnPageChangeListener(adapter); } diff --git a/lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsLayout.java b/lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsLayout.java index 9de4547ca82..eda1f7a3e43 100644 --- a/lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsLayout.java +++ b/lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsLayout.java @@ -8,8 +8,8 @@ import com.reactnativenavigation.parse.NavigationOptions; import com.reactnativenavigation.presentation.OptionsPresenter; -import com.reactnativenavigation.utils.Task; import com.reactnativenavigation.viewcontrollers.toptabs.TopTabController; +import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsAdapter; import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsViewPager; import java.util.List; @@ -18,16 +18,14 @@ public class TopTabsLayout extends LinearLayout implements Container { private TopBar topBar; - private List tabs; private TopTabsViewPager viewPager; private final OptionsPresenter optionsPresenter; - public TopTabsLayout(Context context, List tabs) { + public TopTabsLayout(Context context, List tabs, TopTabsAdapter adapter) { super(context); topBar = new TopBar(context); - this.tabs = tabs; - viewPager = new TopTabsViewPager(context, tabs); optionsPresenter = new OptionsPresenter(topBar, viewPager); + viewPager = new TopTabsViewPager(context, tabs, adapter); initViews(); } @@ -54,11 +52,6 @@ public ViewPager getViewPager() { return viewPager; } - - public void performOnCurrentTab(Task task) { - task.run(tabs.get(viewPager.getCurrentItem())); - } - public void switchToTab(int index) { viewPager.setCurrentItem(index); } diff --git a/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabControllerTest.java b/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabControllerTest.java new file mode 100644 index 00000000000..a6f5f50976e --- /dev/null +++ b/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabControllerTest.java @@ -0,0 +1,53 @@ +package com.reactnativenavigation.viewcontrollers; + +import android.app.Activity; + +import com.reactnativenavigation.BaseTest; +import com.reactnativenavigation.mocks.TopTabLayoutMock; +import com.reactnativenavigation.parse.NavigationOptions; +import com.reactnativenavigation.viewcontrollers.toptabs.TopTabController; + +import org.junit.Test; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class TopTabControllerTest extends BaseTest { + private TopTabController uut; + private TopTabLayoutMock view; + private ParentController parentController; + private NavigationOptions initialOptions; + + @Override + public void beforeEach() { + super.beforeEach(); + Activity activity = newActivity(); + view = spy(new TopTabLayoutMock(activity)); + initialOptions = new NavigationOptions(); + uut = new TopTabController(activity, + "containerId", + "containerName", + (activity1, containerId, containerName) -> view, + initialOptions + ); + parentController = spy(new TopTabsControllerMock(activity, "parentContainerId")); + uut.setParentController(parentController); + } + + @Test + public void styleIsAppliedOnParentControllerWhenTabIsVisible() throws Exception { + uut.ensureViewIsCreated(); + uut.onViewAppeared(); + verify(parentController, times(1)).applyOptions(initialOptions); + } + + @Test + public void styleIsAppliedOnParentControllerWhenOptionsAreSetDynamically() throws Exception { + uut.ensureViewIsCreated(); + uut.onViewAppeared(); + uut.mergeNavigationOptions(new NavigationOptions()); + verify(parentController, times(2)).applyOptions(initialOptions); + } + +} diff --git a/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsControllerMock.java b/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsControllerMock.java new file mode 100644 index 00000000000..a47d0c8e5a8 --- /dev/null +++ b/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsControllerMock.java @@ -0,0 +1,25 @@ +package com.reactnativenavigation.viewcontrollers; + +import android.app.Activity; +import android.support.annotation.NonNull; +import android.view.ViewGroup; + +import java.util.Collection; + +public class TopTabsControllerMock extends ParentController { + public TopTabsControllerMock(Activity activity, String id) { + super(activity, id); + } + + @NonNull + @Override + protected ViewGroup createView() { + return null; + } + + @NonNull + @Override + public Collection getChildControllers() { + return null; + } +} diff --git a/playground/src/containers/TopTabOptionsScreen.js b/playground/src/containers/TopTabOptionsScreen.js index a2a513651d3..3fea731e2ef 100644 --- a/playground/src/containers/TopTabOptionsScreen.js +++ b/playground/src/containers/TopTabOptionsScreen.js @@ -1,7 +1,8 @@ const React = require('react'); const { PureComponent } = require('react'); - -const { View, Text } = require('react-native'); +const testIDs = require('../testIDs'); +const { View, Text, Button } = require('react-native'); +const Navigation = require('react-native-navigation'); class TopTabOptionsScreen extends PureComponent { static get navigationOptions() { @@ -15,14 +16,33 @@ class TopTabOptionsScreen extends PureComponent { }; } + constructor(props) { + super(props); + this.onClickDynamicOptions = this.onClickDynamicOptions.bind(this); + } + render() { return ( {this.props.text || 'Top Tab Screen'} {`this.props.containerId = ${this.props.containerId}`} +