From 1d9e0d675c45666b3b08d81d30eeab1bd98378fb Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 10:06:03 -0500 Subject: [PATCH 01/31] Update base activity name to get example running --- .../android/app/src/main/java/com/example/MainActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/android/app/src/main/java/com/example/MainActivity.java b/example/android/app/src/main/java/com/example/MainActivity.java index 4ab781d93ee..82ed971d48e 100644 --- a/example/android/app/src/main/java/com/example/MainActivity.java +++ b/example/android/app/src/main/java/com/example/MainActivity.java @@ -1,9 +1,9 @@ package com.example; -import com.reactnativenavigation.activities.RctActivity; +import com.reactnativenavigation.activities.RootActivity; -public class MainActivity extends RctActivity { +public class MainActivity extends RootActivity { @Override protected String getMainComponentName() { From 28f3cc76193f2cd9024449cf4fed2ea2baba70f4 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 10:06:46 -0500 Subject: [PATCH 02/31] Update toolbar along with style update (may want to rename setNavigationStyle later) --- .../activities/BaseReactActivity.java | 13 ++++++------- .../activities/BottomTabActivity.java | 1 - .../activities/SingleScreenActivity.java | 7 ++----- .../activities/TabActivity.java | 8 ++++---- .../adapters/ViewPagerAdapter.java | 3 --- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 7068d30757b..2802545ce85 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -175,6 +175,7 @@ protected void handleOnCreate() { public void setNavigationStyle(Screen screen) { if (mToolbar != null) { mToolbar.setStyle(screen); + mToolbar.update(screen); } StyleHelper.setWindowStyle(getWindow(), this, screen); @@ -219,13 +220,10 @@ protected void onDestroy() { @CallSuper public void push(Screen screen) { setNavigationStyle(screen); - if (mToolbar != null) { - mToolbar.update(screen); - - if (getCurrentNavigatorId().equals(screen.navigatorId) && - getScreenStackSize() >= 1) { - mToolbar.showBackButton(screen); - } + if (mToolbar != null && + getCurrentNavigatorId().equals(screen.navigatorId) && + getScreenStackSize() >= 1) { + mToolbar.showBackButton(screen); } } @@ -236,6 +234,7 @@ public Screen pop(String navigatorId) { getScreenStackSize() <= 2) { mToolbar.hideBackButton(); } + return null; } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index ceaa3064a31..3850b9e52c4 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -65,7 +65,6 @@ private void setupPages(ArrayList screens) { private void setupToolbar(ArrayList screens) { mToolbar.setScreens(screens); Screen initialScreen = screens.get(0); - mToolbar.update(initialScreen); setNavigationStyle(initialScreen); } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index ae29f54e15e..63b742f2aed 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -36,10 +36,9 @@ protected void handleOnCreate() { } protected void setupToolbar(Screen screen) { - mToolbar.update(screen); setNavigationStyle(screen); } - + @Override public void push(Screen screen) { super.push(screen); @@ -50,9 +49,7 @@ public void push(Screen screen) { public Screen pop(String navigatorId) { super.pop(navigatorId); Screen screen = mScreenStack.pop(); - Screen currentScreen = getCurrentScreen(); - setNavigationStyle(currentScreen); - mToolbar.update(currentScreen); + setNavigationStyle(getCurrentScreen()); return screen; } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index e841027b9a3..b7120a5bb0b 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -42,7 +42,6 @@ protected void handleOnCreate() { private void setupToolbar(ArrayList screens) { Screen initialScreen = screens.get(0); mToolbar.setScreens(screens); - mToolbar.update(initialScreen); setNavigationStyle(initialScreen); } @@ -77,9 +76,10 @@ public void push(Screen screen) { @Override public Screen pop(String navigatorId) { super.pop(navigatorId); - Screen screen = mAdapter.pop(navigatorId); - setNavigationStyle(getCurrentScreen()); - return screen; + Screen popped = mAdapter.pop(navigatorId); + Screen screen = getCurrentScreen(); + setNavigationStyle(screen); + return popped; } @Override diff --git a/android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java b/android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java index b5cf71e10d1..c904ac58fdf 100644 --- a/android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java +++ b/android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java @@ -107,9 +107,6 @@ public void onTabSelected(TabLayout.Tab tab) { Screen newScreen = mScreenStacks.get(position).peek(); mToolbar.setupToolbarButtonsAsync(prevScreen, newScreen); - // Set title - mToolbar.setTitle(newScreen.title == null ? "" : newScreen.title); - // Set navigation color ContextProvider.getActivityContext().setNavigationStyle(newScreen); From 128d2f7fe95afaed66370c9eba19cc95b4e6f454 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 14:14:03 -0500 Subject: [PATCH 03/31] Add basic setNavigationTitle method --- .../activities/BaseReactActivity.java | 9 +++++++++ .../modules/RctActivityModule.java | 16 +++++++++++++++- src/platformSpecific.android.js | 7 ++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 2802545ce85..0c8e8a70280 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -43,6 +43,7 @@ */ public abstract class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { + protected static final String KEY_TITLE = "title"; private static final String TAG = "BaseReactActivity"; private static final String REDBOX_PERMISSION_MESSAGE = "Overlay permissions needs to be granted in order for react native apps to run in dev mode"; @@ -329,4 +330,12 @@ public void setNavigationButtons(ReadableMap buttons){ getCurrentScreen().setButtons(buttons); mToolbar.setupToolbarButtonsAsync(getCurrentScreen()); } + + public void setNavigationTitle(ReadableMap title) { + if (mToolbar == null) { + return; + } + + mToolbar.setTitle(title.getString(KEY_TITLE)); + } } diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 6796d6706df..602b4f9ba51 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -49,7 +49,7 @@ public void startTabBasedApp(ReadableArray screens, ReadableMap style) { BridgeUtils.addMapToBundle(((ReadableNativeMap) style).toHashMap(), extras); } intent.putExtras(extras); - + context.startActivity(intent); } } @@ -91,6 +91,20 @@ public void run() { }); } + @ReactMethod + public void setNavigatorTitle(final ReadableMap title) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.setNavigationTitle(title); + } + }); + } + @ReactMethod public void navigatorPush(final ReadableMap skreen) { final Screen screen = new Screen(skreen); diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 24eb7219557..d99149aff20 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -69,6 +69,10 @@ function navigatorPop(navigator, params) { RctActivity.navigatorPop(navigator); } +function navigatorSetTitle(navigator, params) { + RctActivity.setNavigatorTitle(params); +} + function showModal(params) { addNavigatorParams(params); addNavigatorButtons(params); @@ -120,5 +124,6 @@ export default { showModal, dismissModal, dismissAllModals, - navigatorSetButtons + navigatorSetButtons, + navigatorSetTitle } From 26821476d469a7d9251a4b7d77bc841368b796cc Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 14:19:35 -0500 Subject: [PATCH 04/31] Make the modal work and presentable on Android --- example/src/screens/FirstTabScreen.android.js | 18 ++++++++---------- example/src/screens/ModalScreen.js | 2 +- example/src/screens/index.android.js | 1 + 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/example/src/screens/FirstTabScreen.android.js b/example/src/screens/FirstTabScreen.android.js index aca8fdc844a..829211604e3 100644 --- a/example/src/screens/FirstTabScreen.android.js +++ b/example/src/screens/FirstTabScreen.android.js @@ -76,18 +76,16 @@ export default class FirstTabScreen extends Component { }); } onPushStyledPress() { - console.warn('navigator.push not implemented yet'); - // this.props.navigator.push({ - // title: "Styled", - // screen: "example.StyledScreen" - // }); + this.props.navigator.push({ + title: "Styled", + screen: "example.StyledScreen" + }); } onModalPress() { - console.warn('navigator.showModal not implemented yet'); - // this.props.navigator.showModal({ - // title: "Modal", - // screen: "example.ModalScreen" - // }); + this.props.navigator.showModal({ + title: "Modal", + screen: "example.ModalScreen" + }); } onLightBoxPress() { console.warn('navigator.showLightBox not implemented yet'); diff --git a/example/src/screens/ModalScreen.js b/example/src/screens/ModalScreen.js index 1a875083dd1..e2aa3feff5f 100644 --- a/example/src/screens/ModalScreen.js +++ b/example/src/screens/ModalScreen.js @@ -21,7 +21,7 @@ export default class ModalScreen extends Component { } render() { return ( - + Push Plain Screen diff --git a/example/src/screens/index.android.js b/example/src/screens/index.android.js index 17f934b33a7..3b3385fa853 100644 --- a/example/src/screens/index.android.js +++ b/example/src/screens/index.android.js @@ -16,5 +16,6 @@ export function registerScreens() { Navigation.registerComponent('example.ThirdTabScreen', () => ThirdTabScreen); Navigation.registerComponent('example.PushedScreen', () => PushedScreen); Navigation.registerComponent('example.StyledScreen', () => StyledScreen); + Navigation.registerComponent('example.ModalScreen', () => ModalScreen); Navigation.registerComponent('example.SideMenu', () => SideMenu); } From c4433d11370246189af11f785492476525757dcf Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 15:31:56 -0500 Subject: [PATCH 05/31] Fix Android modal not closing on first try --- .../java/com/reactnativenavigation/modal/RnnModal.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java b/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java index c010b339229..bf076c724dd 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java +++ b/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java @@ -77,12 +77,12 @@ public Screen pop() { @Override public void onBackPressed() { - if (mScreenStack.isEmpty()) { - ModalController.getInstance().remove(); - super.onBackPressed(); - } else { + if (!mScreenStack.isEmpty()) { mScreenStack.pop(); } + + ModalController.getInstance().remove(); + super.onBackPressed(); } @Override From 9d8c0d2ea530d6c84a83a573f6746504e22f9d6c Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 17:01:02 -0500 Subject: [PATCH 06/31] Wire up tab show/hide and tab selection --- .../activities/BaseReactActivity.java | 11 ++++++++ .../activities/BottomTabActivity.java | 18 ++++++++++++ .../modules/RctActivityModule.java | 28 +++++++++++++++++++ src/platformSpecific.android.js | 17 ++++++++++- 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 0c8e8a70280..4d2c2146cda 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -43,6 +43,9 @@ */ public abstract class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { + protected static final String KEY_ANIMATED = "animated"; + protected static final String KEY_HIDDEN = "hidden"; + protected static final String KEY_TAB_INDEX = "tabIndex"; protected static final String KEY_TITLE = "title"; private static final String TAG = "BaseReactActivity"; private static final String REDBOX_PERMISSION_MESSAGE = @@ -338,4 +341,12 @@ public void setNavigationTitle(ReadableMap title) { mToolbar.setTitle(title.getString(KEY_TITLE)); } + + public void switchToTab(ReadableMap params) { + return; + } + + public void toggleTabs(ReadableMap params) { + return; + } } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index 3850b9e52c4..dfe2b73d771 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -9,6 +9,7 @@ import com.aurelhubert.ahbottomnavigation.AHBottomNavigation; import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem; +import com.facebook.react.bridge.ReadableMap; import com.reactnativenavigation.R; import com.reactnativenavigation.core.RctManager; import com.reactnativenavigation.core.objects.Screen; @@ -139,6 +140,23 @@ public void onTabSelected(int position, boolean wasSelected) { setNavigationStyle(getCurrentScreen()); } + @Override + public void switchToTab(ReadableMap params) { + int tabIndex = params.getInt(KEY_TAB_INDEX); + mBottomNavigation.setCurrentItem(tabIndex); + } + + @Override + public void toggleTabs(ReadableMap params) { + boolean hide = params.getBoolean(KEY_HIDDEN); + boolean animated = params.getBoolean(KEY_ANIMATED); + if (hide) { + mBottomNavigation.hideBottomNavigation(animated); + } else { + mBottomNavigation.restoreBottomNavigation(animated); + } + } + private static class SetupTabsTask extends AsyncTask> { private BottomTabActivity mActivity; private ArrayList mScreens; diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 602b4f9ba51..d3ab57a102f 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -105,6 +105,34 @@ public void run() { }); } + @ReactMethod + public void switchToTab(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.switchToTab(params); + } + }); + } + + @ReactMethod + public void toggleNavigatorTabs(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.toggleTabs(params); + } + }); + } + @ReactMethod public void navigatorPush(final ReadableMap skreen) { final Screen screen = new Screen(skreen); diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index d99149aff20..6e7ecfc7430 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -73,6 +73,19 @@ function navigatorSetTitle(navigator, params) { RctActivity.setNavigatorTitle(params); } +function navigatorSwitchToTab(navigator, params) { + RctActivity.switchToTab({ + tabIndex: params.tabIndex + }); +} + +function navigatorToggleTabs(navigator, params) { + RctActivity.toggleNavigatorTabs({ + hidden: params.to == 'hidden', + animated: !(params.animated === false) + }); +} + function showModal(params) { addNavigatorParams(params); addNavigatorButtons(params); @@ -125,5 +138,7 @@ export default { dismissModal, dismissAllModals, navigatorSetButtons, - navigatorSetTitle + navigatorSetTitle, + navigatorSwitchToTab, + navigatorToggleTabs } From 2e4834887ab19666d5689e96245064700db231bf Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 17:27:45 -0500 Subject: [PATCH 07/31] Wire up Android setTabBadge --- .../activities/BaseReactActivity.java | 5 +++++ .../activities/BottomTabActivity.java | 15 +++++++++++++++ .../modules/RctActivityModule.java | 14 ++++++++++++++ src/platformSpecific.android.js | 8 ++++++++ 4 files changed, 42 insertions(+) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 4d2c2146cda..16ebd1a9807 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -44,6 +44,7 @@ public abstract class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { protected static final String KEY_ANIMATED = "animated"; + protected static final String KEY_BADGE = "badge"; protected static final String KEY_HIDDEN = "hidden"; protected static final String KEY_TAB_INDEX = "tabIndex"; protected static final String KEY_TITLE = "title"; @@ -342,6 +343,10 @@ public void setNavigationTitle(ReadableMap title) { mToolbar.setTitle(title.getString(KEY_TITLE)); } + public void setTabBadge(ReadableMap params) { + return; + } + public void switchToTab(ReadableMap params) { return; } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index dfe2b73d771..9726c23b8d3 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -140,6 +140,21 @@ public void onTabSelected(int position, boolean wasSelected) { setNavigationStyle(getCurrentScreen()); } + @Override + public void setTabBadge(ReadableMap params) { + // Badge comes across as int, but if it's 0 clear the notification + int badgeCount = params.getInt(KEY_BADGE); + String badge = (badgeCount > 0) ? Integer.toString(badgeCount) : ""; + + // Tab index is optional, so default to current tab + int tabIndex = mBottomNavigation.getCurrentItem(); + if (params.hasKey(KEY_TAB_INDEX)) { + tabIndex = params.getInt(KEY_TAB_INDEX); + } + + mBottomNavigation.setNotification(badge, tabIndex); + } + @Override public void switchToTab(ReadableMap params) { int tabIndex = params.getInt(KEY_TAB_INDEX); diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index d3ab57a102f..3e56d71914d 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -105,6 +105,20 @@ public void run() { }); } + @ReactMethod + public void setTabBadge(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.setTabBadge(params); + } + }); + } + @ReactMethod public void switchToTab(final ReadableMap params) { final BaseReactActivity context = ContextProvider.getActivityContext(); diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 6e7ecfc7430..2b3b85c1dbf 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -69,6 +69,13 @@ function navigatorPop(navigator, params) { RctActivity.navigatorPop(navigator); } +function navigatorSetTabBadge(navigator, params) { + RctActivity.setTabBadge({ + tabIndex: params.tabIndex, + badge: params.badge + }); +} + function navigatorSetTitle(navigator, params) { RctActivity.setNavigatorTitle(params); } @@ -138,6 +145,7 @@ export default { dismissModal, dismissAllModals, navigatorSetButtons, + navigatorSetTabBadge, navigatorSetTitle, navigatorSwitchToTab, navigatorToggleTabs From 714b31e633ffdc8f73d7b92bf9212a55f77277e4 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 18:48:31 -0500 Subject: [PATCH 08/31] Add toolbar toggle, not sure if animation is working --- .../activities/BaseReactActivity.java | 14 ++++++++++++++ .../modules/RctActivityModule.java | 14 ++++++++++++++ .../views/RnnToolBar.java | 19 ++++++++++++++++--- src/platformSpecific.android.js | 12 ++++++++++-- 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 16ebd1a9807..ceeb7f59fd2 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -354,4 +354,18 @@ public void switchToTab(ReadableMap params) { public void toggleTabs(ReadableMap params) { return; } + + public void toggleNavigationBar(ReadableMap params) { + if (mToolbar == null) { + return; + } + + boolean hide = params.getBoolean(KEY_HIDDEN); + boolean animated = params.getBoolean(KEY_ANIMATED); + if (hide) { + mToolbar.hideToolbar(animated); + } else { + mToolbar.showToolbar(animated); + } + } } diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 3e56d71914d..193c7c33880 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -133,6 +133,20 @@ public void run() { }); } + @ReactMethod + public void toggleNavigationBar(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.toggleNavigationBar(params); + } + }); + } + @ReactMethod public void toggleNavigatorTabs(final ReadableMap params) { final BaseReactActivity context = ContextProvider.getActivityContext(); diff --git a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java index f6ca7f31c3c..9f06dacc281 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java @@ -12,6 +12,7 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; +import android.view.animation.LinearInterpolator; import android.view.Menu; import android.view.MenuItem; @@ -32,6 +33,8 @@ */ public class RnnToolBar extends Toolbar { + private static final int ANIMATE_DURATION = 180; + private List mScreens; private AsyncTask mSetupToolbarTask; private Drawable mBackground; @@ -71,7 +74,7 @@ public void setStyle(Screen screen) { } else { resetTitleTextColor(); } - + if (screen.toolBarHidden != null && screen.toolBarHidden) { hideToolbar(); } else { @@ -102,20 +105,30 @@ public void setupToolbarButtonsAsync(Screen oldScreen, Screen newScreen) { } } - private void showToolbar() { + public void showToolbar(boolean animated) { ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar(); if (actionBar != null) { + actionBar.setShowHideAnimationEnabled(animated); actionBar.show(); } } - private void hideToolbar() { + public void hideToolbar(boolean animated) { ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar(); if (actionBar != null) { + actionBar.setShowHideAnimationEnabled(animated); actionBar.hide(); } } + private void showToolbar() { + showToolbar(false); + } + + private void hideToolbar() { + hideToolbar(false); + } + @SuppressWarnings({"ConstantConditions"}) public void showBackButton(Screen screen) { ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar(); diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 2b3b85c1dbf..d711d6dcfcb 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -86,9 +86,16 @@ function navigatorSwitchToTab(navigator, params) { }); } +function navigatorToggleNavBar(navigator, params) { + RctActivity.toggleNavigationBar({ + hidden: params.to === 'hidden', + animated: !(params.animated === false) + }); +} + function navigatorToggleTabs(navigator, params) { RctActivity.toggleNavigatorTabs({ - hidden: params.to == 'hidden', + hidden: params.to === 'hidden', animated: !(params.animated === false) }); } @@ -148,5 +155,6 @@ export default { navigatorSetTabBadge, navigatorSetTitle, navigatorSwitchToTab, - navigatorToggleTabs + navigatorToggleTabs, + navigatorToggleNavBar } From 005d1e549440349d7e66ad5460476b8d4e44eb08 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 19:59:14 -0500 Subject: [PATCH 09/31] Consolidate example code since everything but lightbox should now work on the three main tabs --- example/src/screens/FirstTabScreen.android.js | 109 -------------- ...irstTabScreen.ios.js => FirstTabScreen.js} | 10 +- .../src/screens/SecondTabScreen.android.js | 133 ------------------ ...ondTabScreen.ios.js => SecondTabScreen.js} | 15 +- example/src/screens/index.android.js | 1 + example/src/util/Alert.android.js | 11 ++ example/src/util/Alert.ios.js | 10 ++ 7 files changed, 34 insertions(+), 255 deletions(-) delete mode 100644 example/src/screens/FirstTabScreen.android.js rename example/src/screens/{FirstTabScreen.ios.js => FirstTabScreen.js} (93%) delete mode 100644 example/src/screens/SecondTabScreen.android.js rename example/src/screens/{SecondTabScreen.ios.js => SecondTabScreen.js} (91%) create mode 100644 example/src/util/Alert.android.js create mode 100644 example/src/util/Alert.ios.js diff --git a/example/src/screens/FirstTabScreen.android.js b/example/src/screens/FirstTabScreen.android.js deleted file mode 100644 index 829211604e3..00000000000 --- a/example/src/screens/FirstTabScreen.android.js +++ /dev/null @@ -1,109 +0,0 @@ -import React, {Component} from 'react'; -import { - Text, - View, - ScrollView, - TouchableOpacity, - StyleSheet -} from 'react-native'; - -export default class FirstTabScreen extends Component { - static navigatorButtons = { - leftButtons: [{ - icon: require('../../img/navicon_menu.png'), - id: 'menu' - }], - rightButtons: [ - { - title: 'Edit', - id: 'edit' - }, - { - icon: require('../../img/navicon_add.png'), - id: 'add' - } - ] - }; - static navigatorStyle = { - drawUnderTabBar: true - }; - constructor(props) { - super(props); - // if you want to listen on navigator events, set this up - // this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); - } - onNavigatorEvent(event) { - if (event.id == 'menu') { - this.props.navigator.toggleDrawer({ - side: 'left', - animated: true - }); - } - if (event.id == 'edit') { - // AlertIOS.alert('NavBar', 'Edit button pressed'); - } - if (event.id == 'add') { - // AlertIOS.alert('NavBar', 'Add button pressed'); - } - } - render() { - return ( - - - - Push Plain Screen - - - - Push Styled Screen - - - - Show Modal Screen - - - - Show LightBox - - - - ); - } - onPushPress() { - this.props.navigator.push({ - title: "More", - screen: "example.PushedScreen" - }); - } - onPushStyledPress() { - this.props.navigator.push({ - title: "Styled", - screen: "example.StyledScreen" - }); - } - onModalPress() { - this.props.navigator.showModal({ - title: "Modal", - screen: "example.ModalScreen" - }); - } - onLightBoxPress() { - console.warn('navigator.showLightBox not implemented yet'); - // this.props.navigator.showLightBox({ - // screen: "example.LightBoxScreen", - // style: { - // backgroundBlur: "dark" - // } - // }); - } -} - -const styles = StyleSheet.create({ - button: { - textAlign: 'center', - fontSize: 18, - marginBottom: 10, - marginTop:10, - color: 'blue' - } -}); diff --git a/example/src/screens/FirstTabScreen.ios.js b/example/src/screens/FirstTabScreen.js similarity index 93% rename from example/src/screens/FirstTabScreen.ios.js rename to example/src/screens/FirstTabScreen.js index b35aee14b52..6022ad02eee 100644 --- a/example/src/screens/FirstTabScreen.ios.js +++ b/example/src/screens/FirstTabScreen.js @@ -4,9 +4,9 @@ import { View, ScrollView, TouchableOpacity, - StyleSheet, - AlertIOS + StyleSheet } from 'react-native'; +import Alert from '../util/Alert'; export default class FirstTabScreen extends Component { static navigatorButtons = { @@ -26,7 +26,7 @@ export default class FirstTabScreen extends Component { ] }; static navigatorStyle = { - drawUnderTabBar: true + drawUnderTabBar: false }; constructor(props) { super(props); @@ -41,10 +41,10 @@ export default class FirstTabScreen extends Component { }); } if (event.id == 'edit') { - AlertIOS.alert('NavBar', 'Edit button pressed'); + Alert.show('NavBar', 'Edit button pressed'); } if (event.id == 'add') { - AlertIOS.alert('NavBar', 'Add button pressed'); + Alert.show('NavBar', 'Add button pressed'); } } render() { diff --git a/example/src/screens/SecondTabScreen.android.js b/example/src/screens/SecondTabScreen.android.js deleted file mode 100644 index 89d4b43826d..00000000000 --- a/example/src/screens/SecondTabScreen.android.js +++ /dev/null @@ -1,133 +0,0 @@ -import React, {Component} from 'react'; -import { - Text, - View, - ScrollView, - TouchableOpacity, - StyleSheet -} from 'react-native'; - -export default class SecondTabScreen extends Component { - static navigatorStyle = { - drawUnderTabBar: true - }; - constructor(props) { - super(props); - this.buttonsCounter = 0; - // if you want to listen on navigator events, set this up - // this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this)); - } - render() { - return ( - - - - Change Buttons - - - - Change Title - - - - Switch To Tab#1 - - - - Set Tab Badge - - - - Toggle Tabs - - - - ); - } - onChangeTitlePress() { - this.props.navigator.setTitle({ - title: Math.round(Math.random() * 100000).toString() - }); - } - onChangeButtonsPress() { - let buttons; - if (this.buttonsCounter % 3 == 0) { - buttons = [ - { - title: 'Edit', - id: 'edit', - disabled: true - }, - { - icon: require('../../img/navicon_add.png'), - id: 'add' - } - ]; - } else if (this.buttonsCounter % 3 == 1) { - buttons = [{ - title: 'Save', - id: 'save' - }]; - } else { - buttons = []; - } - this.buttonsCounter++; - - this.props.navigator.setButtons({ - rightButtons: buttons, - animated: true - }); - } - onSwitchTabPress() { - this.props.navigator.switchToTab({ - tabIndex: 0 - }); - } - onSetTabBadgePress() { - this.props.navigator.setTabBadge({ - badge: 12 - }); - } - onToggleTabsPress() { - this.props.navigator.toggleTabs({ - to: this.tabsHidden ? 'shown' : 'hidden' - }); - this.tabsHidden = !this.tabsHidden; - } - onNavigatorEvent(event) { - // handle a deep link - if (event.type == 'DeepLink') { - const parts = event.link.split('/'); - if (parts[0] == 'tab2') { - this.props.navigator.resetTo({ - title: "Replaced Root", - screen: parts[1], - animated: true - }); - this.props.navigator.switchToTab(); - } - } - // handle a button press - // if (event.type == 'NavBarButtonPress') { - // if (event.id == 'edit') { - // AlertIOS.alert('NavBar', 'Dynamic Edit button pressed'); - // } - // if (event.id == 'add') { - // AlertIOS.alert('NavBar', 'Dynamic Add button pressed'); - // } - // if (event.id == 'save') { - // AlertIOS.alert('NavBar', 'Dynamic Save button pressed'); - // } - // } - } -} - -const styles = StyleSheet.create({ - button: { - textAlign: 'center', - fontSize: 18, - marginBottom: 10, - marginTop:10, - color: 'blue' - } -}); diff --git a/example/src/screens/SecondTabScreen.ios.js b/example/src/screens/SecondTabScreen.js similarity index 91% rename from example/src/screens/SecondTabScreen.ios.js rename to example/src/screens/SecondTabScreen.js index e5e3452672c..43cef901d66 100644 --- a/example/src/screens/SecondTabScreen.ios.js +++ b/example/src/screens/SecondTabScreen.js @@ -4,9 +4,9 @@ import { View, ScrollView, TouchableOpacity, - StyleSheet, - AlertIOS + StyleSheet } from 'react-native'; +import Alert from '../util/Alert'; export default class SecondTabScreen extends Component { static navigatorStyle = { @@ -107,17 +107,16 @@ export default class SecondTabScreen extends Component { }); this.props.navigator.switchToTab(); } - } - // handle a button press - if (event.type == 'NavBarButtonPress') { + } else { + // handle a button press if (event.id == 'edit') { - AlertIOS.alert('NavBar', 'Dynamic Edit button pressed'); + Alert.show('NavBar', 'Dynamic Edit button pressed'); } if (event.id == 'add') { - AlertIOS.alert('NavBar', 'Dynamic Add button pressed'); + Alert.show('NavBar', 'Dynamic Add button pressed'); } if (event.id == 'save') { - AlertIOS.alert('NavBar', 'Dynamic Save button pressed'); + Alert.show('NavBar', 'Dynamic Save button pressed'); } } } diff --git a/example/src/screens/index.android.js b/example/src/screens/index.android.js index 3b3385fa853..c6b77df52ab 100644 --- a/example/src/screens/index.android.js +++ b/example/src/screens/index.android.js @@ -17,5 +17,6 @@ export function registerScreens() { Navigation.registerComponent('example.PushedScreen', () => PushedScreen); Navigation.registerComponent('example.StyledScreen', () => StyledScreen); Navigation.registerComponent('example.ModalScreen', () => ModalScreen); + Navigation.registerComponent('example.LightBoxScreen', () => LightBoxScreen); Navigation.registerComponent('example.SideMenu', () => SideMenu); } diff --git a/example/src/util/Alert.android.js b/example/src/util/Alert.android.js new file mode 100644 index 00000000000..9f5f6cc55b8 --- /dev/null +++ b/example/src/util/Alert.android.js @@ -0,0 +1,11 @@ +import { ToastAndroid } from 'react-native'; + +/** + * Generic alert interface for Android and iOS. + * Title is currently ignored on Android since toasts don't have titles. + */ +function show(title, message) { + ToastAndroid.show(message, ToastAndroid.SHORT); +} + +export default { show }; diff --git a/example/src/util/Alert.ios.js b/example/src/util/Alert.ios.js new file mode 100644 index 00000000000..cd770a82440 --- /dev/null +++ b/example/src/util/Alert.ios.js @@ -0,0 +1,10 @@ +import { AlertIOS } from 'react-native' + +/** + * Generic alert interface for Android and iOS. + */ +function show(title, message) { + AlertIOS.alert(title, message); +} + +export default { show }; \ No newline at end of file From 229fd5dc05e22c75002bfc586b87c2b2ad923473 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 22:58:23 -0500 Subject: [PATCH 10/31] Fix circular reference error parsing navigatorEventSubscription --- src/platformSpecific.android.js | 2 +- src/utils.js | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index d711d6dcfcb..7f04118949c 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -66,7 +66,7 @@ function navigatorSetButtons(navigator, navigatorEventID, params) { } function navigatorPop(navigator, params) { - RctActivity.navigatorPop(navigator); + RctActivity.navigatorPop(utils.stripRefs(navigator)); } function navigatorSetTabBadge(navigator, params) { diff --git a/src/utils.js b/src/utils.js index ef3cdfed79b..a975ca5deeb 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,6 +2,23 @@ function getRandomId() { return (Math.random()*1e20).toString(36); } +function stripRefs(obj) { + var cache = []; + const result = JSON.stringify(obj, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + // Circular reference found, discard key + return; + } + cache.push(value); + } + return value; + }); + + return JSON.parse(result); +} + export default { - getRandomId + getRandomId, + stripRefs } From 4515e13b27987b2692fadb153476fb87f2e2e12c Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Wed, 8 Jun 2016 23:40:48 -0500 Subject: [PATCH 11/31] Implement popToRoot --- .../activities/BaseReactActivity.java | 9 +++++++ .../activities/BottomTabActivity.java | 13 +++++++++ .../activities/SingleScreenActivity.java | 8 ++++++ .../modules/RctActivityModule.java | 19 ++++++++++++- .../views/ScreenStack.java | 27 +++++++++++++++++++ src/platformSpecific.android.js | 8 ++++++ 6 files changed, 83 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index ceeb7f59fd2..b670346a3ce 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -243,6 +243,15 @@ public Screen pop(String navigatorId) { return null; } + @CallSuper + public Screen popToRoot(String navigatorId) { + if (mToolbar != null) { + mToolbar.hideBackButton(); + } + + return null; + } + protected abstract String getCurrentNavigatorId(); protected abstract Screen getCurrentScreen(); diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index 9726c23b8d3..f9706d2bb00 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -113,6 +113,19 @@ public Screen pop(String navigatorId) { return null; } + @Override + public Screen popToRoot(String navigatorId) { + super.popToRoot(navigatorId); + for (ScreenStack stack: mScreenStacks) { + if (stack.peek().navigatorId.equals(navigatorId)) { + Screen popped = stack.popToRoot(); + setNavigationStyle(getCurrentScreen()); + return popped; + } + } + return null; + } + @Override protected Screen getCurrentScreen() { return mScreenStacks.get(mCurrentStackPosition).peek(); diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index 63b742f2aed..8b5c6a535f7 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -53,6 +53,14 @@ public Screen pop(String navigatorId) { return screen; } + @Override + public Screen popToRoot(String navigatorId) { + super.popToRoot(navigatorId); + Screen screen = mScreenStack.popToRoot(); + setNavigationStyle(getCurrentScreen()); + return screen; + } + @Override public String getCurrentNavigatorId() { return mNavigatorId; diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 193c7c33880..098f57d391f 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -26,6 +26,7 @@ */ public class RctActivityModule extends ReactContextBaseJavaModule { public static final String REACT_CLASS = "RctActivity"; + private static final String KEY_NAVIGATOR_ID = "navigatorID"; public RctActivityModule(ReactApplicationContext reactContext) { super(reactContext); @@ -195,7 +196,7 @@ public void run() { @ReactMethod public void navigatorPop(final ReadableMap navigator) { - final String navigatorId = navigator.getString("navigatorID"); + final String navigatorId = navigator.getString(KEY_NAVIGATOR_ID); final BaseReactActivity context = ContextProvider.getActivityContext(); if (context == null || context.isFinishing()) { return; @@ -222,6 +223,22 @@ public void run() { } }); } + } + + @ReactMethod + public void navigatorPopToRoot(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + + final String navigatorID = params.getString(KEY_NAVIGATOR_ID); + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.popToRoot(navigatorID); + } + }); } diff --git a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java index 8eb44065de7..bf876e13d5d 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java @@ -81,6 +81,33 @@ public Screen pop() { return popped.screen; } + public Screen popToRoot() { + if (mStack.isEmpty()) { + return null; + } + + int stackSize = getStackSize(); + if (stackSize < 2) { + return null; + } + + ScreenView lastView = null; + while (getStackSize() >= 2) { + ScreenView popped = mStack.pop(); + ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); + removeView(popped.view); + if (lastView == null) { + lastView = popped; + } + } + + if (!mStack.isEmpty()) { + addView(mStack.peek().view, 0); + } + + return lastView.screen; + } + public boolean isEmpty() { return mStack.isEmpty(); } diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 7f04118949c..67439627654 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -69,6 +69,13 @@ function navigatorPop(navigator, params) { RctActivity.navigatorPop(utils.stripRefs(navigator)); } +function navigatorPopToRoot(navigator, params) { + RctActivity.navigatorPopToRoot({ + navigatorID: navigator.navigatorID, + animated: !(params.animated !== false) + }); +} + function navigatorSetTabBadge(navigator, params) { RctActivity.setTabBadge({ tabIndex: params.tabIndex, @@ -148,6 +155,7 @@ export default { startSingleScreenApp, navigatorPush, navigatorPop, + navigatorPopToRoot, showModal, dismissModal, dismissAllModals, From be6c8e2656610171eee7f28b479ac938c7671dce Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 01:21:42 -0500 Subject: [PATCH 12/31] Implement resetTo --- .../activities/BaseReactActivity.java | 10 ++++ .../activities/BottomTabActivity.java | 7 +++ .../activities/SingleScreenActivity.java | 7 +++ .../activities/TabActivity.java | 3 +- .../modules/RctActivityModule.java | 15 ++++++ .../views/ScreenStack.java | 54 +++++++++++++------ src/platformSpecific.android.js | 8 +++ 7 files changed, 87 insertions(+), 17 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index b670346a3ce..bcd3783290b 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -252,6 +252,16 @@ public Screen popToRoot(String navigatorId) { return null; } + @CallSuper + public Screen resetTo(Screen screen) { + setNavigationStyle(screen); + if (mToolbar != null) { + mToolbar.hideBackButton(); + } + + return null; + } + protected abstract String getCurrentNavigatorId(); protected abstract Screen getCurrentScreen(); diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index f9706d2bb00..7db19a7fc75 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -126,6 +126,13 @@ public Screen popToRoot(String navigatorId) { return null; } + @Override + public Screen resetTo(Screen screen) { + super.resetTo(screen); + Screen popped = mScreenStacks.get(mCurrentStackPosition).resetTo(screen); + return popped; + } + @Override protected Screen getCurrentScreen() { return mScreenStacks.get(mCurrentStackPosition).peek(); diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index 8b5c6a535f7..f4017c7c186 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -61,6 +61,13 @@ public Screen popToRoot(String navigatorId) { return screen; } + @Override + public Screen resetTo(Screen screen) { + super.resetTo(screen); + Screen popped = mScreenStack.resetTo(screen); + return popped; + } + @Override public String getCurrentNavigatorId() { return mNavigatorId; diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index b7120a5bb0b..8fff0c480af 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -77,8 +77,7 @@ public void push(Screen screen) { public Screen pop(String navigatorId) { super.pop(navigatorId); Screen popped = mAdapter.pop(navigatorId); - Screen screen = getCurrentScreen(); - setNavigationStyle(screen); + setNavigationStyle(getCurrentScreen()); return popped; } diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 098f57d391f..a4032775018 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -239,7 +239,22 @@ public void run() { context.popToRoot(navigatorID); } }); + } + + @ReactMethod + public void navigatorResetTo(final ReadableMap skreen) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + final Screen screen = new Screen(skreen); + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.resetTo(screen); + } + }); } @ReactMethod diff --git a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java index bf876e13d5d..2e7646341f0 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java @@ -68,13 +68,12 @@ public void push(Screen screen, RctView.OnDisplayedListener onDisplayed) { } public Screen pop() { - if (mStack.isEmpty()) { + if (mStack.isEmpty() || getStackSize() == 1) { return null; } + ScreenView popped = mStack.pop(); - if (!mStack.isEmpty()) { - addView(mStack.peek().view, 0); - } + addView(mStack.peek().view, 0); ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); removeView(popped.view); @@ -82,22 +81,17 @@ public Screen pop() { } public Screen popToRoot() { - if (mStack.isEmpty()) { - return null; - } - - int stackSize = getStackSize(); - if (stackSize < 2) { + if (mStack.isEmpty() || getStackSize() <= 1) { return null; } - ScreenView lastView = null; - while (getStackSize() >= 2) { + ScreenView oldScreenView = null; + while (getStackSize() > 1) { ScreenView popped = mStack.pop(); ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); removeView(popped.view); - if (lastView == null) { - lastView = popped; + if (oldScreenView == null) { + oldScreenView = popped; } } @@ -105,7 +99,37 @@ public Screen popToRoot() { addView(mStack.peek().view, 0); } - return lastView.screen; + return oldScreenView.screen; + } + + public Screen resetTo(Screen screen) { + return resetTo(screen, null); + } + + public Screen resetTo(Screen screen, RctView.OnDisplayedListener onDisplayed) { + RctView view = new RctView(mReactActivity, mReactInstanceManager, screen, onDisplayed); + addView(view, MATCH_PARENT, MATCH_PARENT); + + ScreenView oldScreenView = null; + if (!mStack.isEmpty()) { + while (getStackSize() > 0) { + ScreenView screenView = mStack.pop(); + ReflectionUtils.setBooleanField(screenView.view.getReactRootView(), "mAttachScheduled", false); + removeView(screenView.view); + if (oldScreenView == null) { + oldScreenView = screenView; + } + } + } + + // Add screen to stack after it's clear + mStack.push(new ScreenView(screen, view)); + + if (oldScreenView == null) { + return null; + } + + return oldScreenView.screen; } public boolean isEmpty() { diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 67439627654..81e317b9c89 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -76,6 +76,13 @@ function navigatorPopToRoot(navigator, params) { }); } +function navigatorResetTo(navigator, params) { + addNavigatorParams(params, navigator); + addNavigatorButtons(params); + addNavigationStyleParams(params); + RctActivity.navigatorResetTo(params); +} + function navigatorSetTabBadge(navigator, params) { RctActivity.setTabBadge({ tabIndex: params.tabIndex, @@ -156,6 +163,7 @@ export default { navigatorPush, navigatorPop, navigatorPopToRoot, + navigatorResetTo, showModal, dismissModal, dismissAllModals, From 05b511c0739b548f2d4f3faff568f9566c28a619 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:00:08 -0500 Subject: [PATCH 13/31] Use update styles --- .../activities/BaseReactActivity.java | 14 ++++++++++---- .../activities/BottomTabActivity.java | 3 ++- .../activities/SingleScreenActivity.java | 3 ++- .../activities/TabActivity.java | 4 ++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 4f0b7edd1ed..e5cb24e6125 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -180,7 +180,6 @@ protected void handleOnCreate() { public void setNavigationStyle(Screen screen) { if (mToolbar != null) { mToolbar.setStyle(screen); - mToolbar.update(screen); } StyleHelper.setWindowStyle(getWindow(), this, screen); @@ -197,10 +196,17 @@ protected void onResume() { } public void updateStyles() { + updateStyles(null); + } + + public void updateStyles(Screen otherScreen) { + Screen screen = (otherScreen == null) ? getCurrentScreen() : otherScreen; try { - mToolbar.update(getCurrentScreen()); - setNavigationStyle(getCurrentScreen()); - mToolbar.setupToolbarButtonsAsync(getCurrentScreen()); + setNavigationStyle(screen); + if (mToolbar != null) { + mToolbar.update(screen); + mToolbar.setupToolbarButtonsAsync(screen); + } } catch (Exception e) { Log.w("RNNavigation", "Tried to update styles with no screen!"); } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index 61a6082388e..005cfd89658 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -131,7 +131,7 @@ public Screen popToRoot(String navigatorId) { for (ScreenStack stack: mScreenStacks) { if (stack.peek().navigatorId.equals(navigatorId)) { Screen popped = stack.popToRoot(); - setNavigationStyle(getCurrentScreen()); + updateStyles(); return popped; } } @@ -142,6 +142,7 @@ public Screen popToRoot(String navigatorId) { public Screen resetTo(Screen screen) { super.resetTo(screen); Screen popped = mScreenStacks.get(mCurrentStackPosition).resetTo(screen); + updateStyles(); return popped; } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index 779c199eba9..5ebd1fe5f15 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -58,7 +58,7 @@ public Screen pop(String navigatorId) { public Screen popToRoot(String navigatorId) { super.popToRoot(navigatorId); Screen screen = mScreenStack.popToRoot(); - setNavigationStyle(getCurrentScreen()); + updateStyles(); return screen; } @@ -66,6 +66,7 @@ public Screen popToRoot(String navigatorId) { public Screen resetTo(Screen screen) { super.resetTo(screen); Screen popped = mScreenStack.resetTo(screen); + updateStyles(); return popped; } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index 8fff0c480af..10d551ef210 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -69,7 +69,7 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public void push(Screen screen) { super.push(screen); - setNavigationStyle(screen); + updateStyles(screen); mAdapter.push(screen); } @@ -77,7 +77,7 @@ public void push(Screen screen) { public Screen pop(String navigatorId) { super.pop(navigatorId); Screen popped = mAdapter.pop(navigatorId); - setNavigationStyle(getCurrentScreen()); + updateStyles(); return popped; } From cb48fd575805f229fcb73e5750af8a57d1ea1c48 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:05:12 -0500 Subject: [PATCH 14/31] Remove setNavigationStyle since updatesStyles, which calls setNavigationStyle, is called is all derived methods --- .../com/reactnativenavigation/activities/BaseReactActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index e5cb24e6125..205fe03e739 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -240,7 +240,6 @@ protected void onDestroy() { @CallSuper public void push(Screen screen) { - setNavigationStyle(screen); if (mToolbar != null && getCurrentNavigatorId().equals(screen.navigatorId) && getScreenStackSize() >= 1) { @@ -270,7 +269,6 @@ public Screen popToRoot(String navigatorId) { @CallSuper public Screen resetTo(Screen screen) { - setNavigationStyle(screen); if (mToolbar != null) { mToolbar.hideBackButton(); } From 3d0b6cd314404227086ddde059c5757d024a6c3c Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:05:35 -0500 Subject: [PATCH 15/31] Cleanup --- .../modules/RctActivityModule.java | 2 ++ .../com/reactnativenavigation/views/RnnToolBar.java | 3 --- .../com/reactnativenavigation/views/ScreenStack.java | 10 ++-------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index e04be572df2..728aec19b99 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -27,6 +27,7 @@ */ public class RctActivityModule extends ReactContextBaseJavaModule { public static final String REACT_CLASS = "RctActivity"; + private static final String KEY_ANIMATED = "animated"; private static final String KEY_NAVIGATOR_ID = "navigatorID"; public RctActivityModule(ReactApplicationContext reactContext) { @@ -241,6 +242,7 @@ public void navigatorPopToRoot(final ReadableMap params) { } final String navigatorID = params.getString(KEY_NAVIGATOR_ID); + final boolean animated = params.getBoolean(KEY_ANIMATED); context.runOnUiThread(new Runnable() { @Override public void run() { diff --git a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java index 9f06dacc281..71e99e078ce 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java @@ -12,7 +12,6 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; -import android.view.animation.LinearInterpolator; import android.view.Menu; import android.view.MenuItem; @@ -33,8 +32,6 @@ */ public class RnnToolBar extends Toolbar { - private static final int ANIMATE_DURATION = 180; - private List mScreens; private AsyncTask mSetupToolbarTask; private Drawable mBackground; diff --git a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java index 2e7646341f0..ca5bacb5e05 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java @@ -74,14 +74,13 @@ public Screen pop() { ScreenView popped = mStack.pop(); addView(mStack.peek().view, 0); - ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); removeView(popped.view); return popped.screen; } public Screen popToRoot() { - if (mStack.isEmpty() || getStackSize() <= 1) { + if (mStack.isEmpty() || getStackSize() == 1) { return null; } @@ -94,11 +93,7 @@ public Screen popToRoot() { oldScreenView = popped; } } - - if (!mStack.isEmpty()) { - addView(mStack.peek().view, 0); - } - + addView(mStack.peek().view, 0); return oldScreenView.screen; } @@ -128,7 +123,6 @@ public Screen resetTo(Screen screen, RctView.OnDisplayedListener onDisplayed) { if (oldScreenView == null) { return null; } - return oldScreenView.screen; } From 2a18c6b63723f9144a19b6ea4214e98fd3a69e45 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:06:24 -0500 Subject: [PATCH 16/31] Fix boolean test --- src/platformSpecific.android.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 81e317b9c89..6841deb08b0 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -72,7 +72,7 @@ function navigatorPop(navigator, params) { function navigatorPopToRoot(navigator, params) { RctActivity.navigatorPopToRoot({ navigatorID: navigator.navigatorID, - animated: !(params.animated !== false) + animated: !(params.animated === false) }); } From 89a9ea40e49355f6e5c6ee89fdce13603c3f4917 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:06:49 -0500 Subject: [PATCH 17/31] Revert drawer flag --- example/src/screens/FirstTabScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/src/screens/FirstTabScreen.js b/example/src/screens/FirstTabScreen.js index 6022ad02eee..3ad4166b1ef 100644 --- a/example/src/screens/FirstTabScreen.js +++ b/example/src/screens/FirstTabScreen.js @@ -26,7 +26,7 @@ export default class FirstTabScreen extends Component { ] }; static navigatorStyle = { - drawUnderTabBar: false + drawUnderTabBar: true }; constructor(props) { super(props); From 692e2e9da5c8d47c9b3a10346fac4fe0cfd33831 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:12:59 -0500 Subject: [PATCH 18/31] Update remaining alert references --- example/src/screens/SideMenu.js | 3 +-- example/src/screens/StyledScreen.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/example/src/screens/SideMenu.js b/example/src/screens/SideMenu.js index d49754f86ee..c1adcdd212a 100644 --- a/example/src/screens/SideMenu.js +++ b/example/src/screens/SideMenu.js @@ -4,8 +4,7 @@ import { View, ScrollView, TouchableOpacity, - StyleSheet, - AlertIOS + StyleSheet } from 'react-native'; export default class SideMenu extends Component { diff --git a/example/src/screens/StyledScreen.js b/example/src/screens/StyledScreen.js index 7591e123644..5a9b73c5ed0 100644 --- a/example/src/screens/StyledScreen.js +++ b/example/src/screens/StyledScreen.js @@ -5,9 +5,9 @@ import { ScrollView, TouchableOpacity, Image, - StyleSheet, - AlertIOS + StyleSheet } from 'react-native'; +import Alert from '../util/Alert'; export default class StyledScreen extends Component { static navigatorStyle = { @@ -54,7 +54,7 @@ export default class StyledScreen extends Component { } onNavigatorEvent(event) { if (event.id == 'compose') { - AlertIOS.alert('NavBar', 'Compose button pressed'); + Alert.show('NavBar', 'Compose button pressed'); } } onPushPress() { From 1a7129ffa29002487862cee35b76248225bb9f5c Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:22:51 -0500 Subject: [PATCH 19/31] Restore super call for modal back --- .../src/main/java/com/reactnativenavigation/modal/RnnModal.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java b/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java index ccbb04f46ae..ef062f61433 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java +++ b/android/app/src/main/java/com/reactnativenavigation/modal/RnnModal.java @@ -78,6 +78,7 @@ public Screen pop() { @Override public void onBackPressed() { + super.onBackPressed(); pop(); } From 1da63435e18ca5df7409352fcd8d700b95f50080 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:33:41 -0500 Subject: [PATCH 20/31] Restore update --- .../com/reactnativenavigation/activities/BottomTabActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index 005cfd89658..0f75666914d 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -66,6 +66,7 @@ private void setupPages(ArrayList screens) { private void setupToolbar(ArrayList screens) { mToolbar.setScreens(screens); Screen initialScreen = screens.get(0); + mToolbar.update(initialScreen); setNavigationStyle(initialScreen); } From efa84a2fb4e4b5acae8640f303b8a77e3dafff9b Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 10:51:09 -0500 Subject: [PATCH 21/31] Update tab title and persist title on tab change --- .../activities/BaseReactActivity.java | 1 + .../activities/BottomTabActivity.java | 9 +++++++++ .../com/reactnativenavigation/core/objects/Screen.java | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 205fe03e739..2f4f6725954 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -373,6 +373,7 @@ public void setNavigationTitle(ReadableMap title) { return; } + getCurrentScreen().setTitle(title); mToolbar.setTitle(title.getString(KEY_TITLE)); } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index 0f75666914d..be5b7bdcedc 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -173,6 +173,15 @@ public void onTabSelected(int position, boolean wasSelected) { updateStyles(); } + @Override + public void setNavigationTitle(ReadableMap title) { + super.setNavigationTitle(title); + + AHBottomNavigationItem currentItem = mBottomNavigation.getItem(mBottomNavigation.getCurrentItem()); + currentItem.setTitle(title.getString(KEY_TITLE)); + mBottomNavigation.refresh(); + } + @Override public void setTabBadge(ReadableMap params) { // Badge comes across as int, but if it's 0 clear the notification diff --git a/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java b/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java index 7a56ed15f41..74919bd2700 100644 --- a/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java +++ b/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java @@ -43,7 +43,7 @@ public class Screen extends JsonObject implements Serializable { private static final String KEY_TAB_INDICATOR_COLOR = "tabIndicatorColor"; private static final String KEY_PROPS = "passProps"; - public final String title; + public String title; public final String label; public final String screenId; public final String screenInstanceId; @@ -84,6 +84,10 @@ public Screen(ReadableMap screen) { setToolbarStyle(screen); } + public void setTitle(ReadableMap params) { + this.title = getString(params, KEY_TITLE); + } + public void setButtons(ReadableMap params) { this.buttons = getButtons(params); } From 7f3d9ba71d312d5bd1e9b789d56d3f6dcd32a644 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Thu, 9 Jun 2016 12:57:55 -0500 Subject: [PATCH 22/31] Make sure addView is called before removeView to get fade transition --- .../views/ScreenStack.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java index ca5bacb5e05..775389d4247 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/ScreenStack.java @@ -88,12 +88,13 @@ public Screen popToRoot() { while (getStackSize() > 1) { ScreenView popped = mStack.pop(); ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); - removeView(popped.view); if (oldScreenView == null) { oldScreenView = popped; } } + addView(mStack.peek().view, 0); + removeView(oldScreenView.view); return oldScreenView.screen; } @@ -102,24 +103,23 @@ public Screen resetTo(Screen screen) { } public Screen resetTo(Screen screen, RctView.OnDisplayedListener onDisplayed) { - RctView view = new RctView(mReactActivity, mReactInstanceManager, screen, onDisplayed); - addView(view, MATCH_PARENT, MATCH_PARENT); + if (mStack.isEmpty()) { + return null; + } ScreenView oldScreenView = null; - if (!mStack.isEmpty()) { - while (getStackSize() > 0) { - ScreenView screenView = mStack.pop(); - ReflectionUtils.setBooleanField(screenView.view.getReactRootView(), "mAttachScheduled", false); - removeView(screenView.view); - if (oldScreenView == null) { - oldScreenView = screenView; - } + while (getStackSize() > 0) { + ScreenView popped = mStack.pop(); + ReflectionUtils.setBooleanField(popped.view.getReactRootView(), "mAttachScheduled", false); + if (oldScreenView == null) { + oldScreenView = popped; } } - // Add screen to stack after it's clear + RctView view = new RctView(mReactActivity, mReactInstanceManager, screen, onDisplayed); + addView(view, MATCH_PARENT, MATCH_PARENT); + removeView(oldScreenView.view); mStack.push(new ScreenView(screen, view)); - if (oldScreenView == null) { return null; } From 8d34eacf8a326efcd3e4a73258daf50856c27ecd Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Sat, 11 Jun 2016 15:57:56 -0500 Subject: [PATCH 23/31] Restore toolbar updates --- .../reactnativenavigation/activities/SingleScreenActivity.java | 1 + .../java/com/reactnativenavigation/activities/TabActivity.java | 1 + 2 files changed, 2 insertions(+) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index 5ebd1fe5f15..f3fb0bb63f1 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -36,6 +36,7 @@ protected void handleOnCreate() { } protected void setupToolbar(Screen screen) { + mToolbar.update(screen); setNavigationStyle(screen); } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index 10d551ef210..4a4a35ff049 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -42,6 +42,7 @@ protected void handleOnCreate() { private void setupToolbar(ArrayList screens) { Screen initialScreen = screens.get(0); mToolbar.setScreens(screens); + mToolbar.update(screen); setNavigationStyle(initialScreen); } From c79c92c011c895ed196d5914b93a4c22fe4f03a0 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Sat, 11 Jun 2016 16:09:25 -0500 Subject: [PATCH 24/31] Fix reference --- .../java/com/reactnativenavigation/activities/TabActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index 4a4a35ff049..66299f52953 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -42,7 +42,7 @@ protected void handleOnCreate() { private void setupToolbar(ArrayList screens) { Screen initialScreen = screens.get(0); mToolbar.setScreens(screens); - mToolbar.update(screen); + mToolbar.update(initialScreen); setNavigationStyle(initialScreen); } From f5964a44096e00c4579d1e28cc79106e53573634 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Sat, 11 Jun 2016 16:09:25 -0500 Subject: [PATCH 25/31] Fix reference --- .../java/com/reactnativenavigation/activities/TabActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java index 4a4a35ff049..66299f52953 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java @@ -42,7 +42,7 @@ protected void handleOnCreate() { private void setupToolbar(ArrayList screens) { Screen initialScreen = screens.get(0); mToolbar.setScreens(screens); - mToolbar.update(screen); + mToolbar.update(initialScreen); setNavigationStyle(initialScreen); } From e2f3bb0be2b55e7515bc546c9f0d8925b1c5fcf5 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Sat, 11 Jun 2016 16:49:37 -0500 Subject: [PATCH 26/31] Fix navbar bg color and text color --- .../java/com/reactnativenavigation/core/objects/Screen.java | 4 ++-- src/platformSpecific.android.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java b/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java index 74919bd2700..e457be29f6c 100644 --- a/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java +++ b/android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java @@ -33,11 +33,11 @@ public class Screen extends JsonObject implements Serializable { private static final String KEY_RIGHT_BUTTONS = "rightButtons"; private static final String KEY_TOOL_BAR_STYLE = "navigatorStyle"; private static final String KEY_STATUS_BAR_COLOR = "statusBarColor"; - private static final String KEY_TOOL_BAR_COLOR = "toolBarColor"; + private static final String KEY_TOOL_BAR_COLOR = "navBarBackgroundColor"; private static final String KEY_TOOL_BAR_HIDDEN = "navBarHidden"; private static final String KEY_NAVIGATION_BAR_COLOR = "navigationBarColor"; private static final String KEY_BUTTONS_TINT_COLOR = "buttonsTint"; - private static final String KEY_TITLE_COLOR = "titleColor"; + private static final String KEY_TITLE_COLOR = "navBarTextColor"; private static final String KEY_TAB_NORMAL_TEXT_COLOR = "tabNormalTextColor"; private static final String KEY_TAB_SELECTED_TEXT_COLOR = "tabSelectedTextColor"; private static final String KEY_TAB_INDICATOR_COLOR = "tabIndicatorColor"; diff --git a/src/platformSpecific.android.js b/src/platformSpecific.android.js index 6841deb08b0..35916edca56 100644 --- a/src/platformSpecific.android.js +++ b/src/platformSpecific.android.js @@ -154,7 +154,7 @@ function addNavigatorButtons(screen) { function addNavigationStyleParams(screen) { const Screen = Navigation.getRegisteredScreen(screen.screen); - screen.navigatorStyle = Screen.navigatorStyle; + Object.assign(screen.navigatorStyle, Screen.navigatorStyle); } export default { From 7ef6dbf4c7a893807fc8ffe3fbd811866cdc7a14 Mon Sep 17 00:00:00 2001 From: Jason Skuby Date: Sun, 12 Jun 2016 16:19:19 -0500 Subject: [PATCH 27/31] Add left drawer for Android --- .../activities/BaseReactActivity.java | 56 +++++++- .../activities/BottomTabActivity.java | 21 +++ .../activities/SingleScreenActivity.java | 25 +++- .../core/objects/Drawer.java | 23 +++ .../modules/RctActivityModule.java | 25 +++- .../views/RnnToolBar.java | 135 ++++++++++++++++-- .../views/ScreenStack.java | 2 +- .../main/res/layout/bottom_tab_activity.xml | 18 ++- .../res/layout/single_screen_activity.xml | 16 ++- android/app/src/main/res/values/strings.xml | 5 + src/platformSpecific.android.js | 31 +++- 11 files changed, 328 insertions(+), 29 deletions(-) create mode 100644 android/app/src/main/java/com/reactnativenavigation/core/objects/Drawer.java create mode 100644 android/app/src/main/res/values/strings.xml diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java index 2f4f6725954..85f21e35181 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java @@ -1,11 +1,13 @@ package com.reactnativenavigation.activities; import android.content.Intent; +import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; import android.support.annotation.CallSuper; +import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; @@ -46,8 +48,10 @@ public abstract class BaseReactActivity extends AppCompatActivity implements Def protected static final String KEY_ANIMATED = "animated"; protected static final String KEY_BADGE = "badge"; protected static final String KEY_HIDDEN = "hidden"; + protected static final String KEY_SIDE = "side"; protected static final String KEY_TAB_INDEX = "tabIndex"; protected static final String KEY_TITLE = "title"; + protected static final String KEY_TO = "to"; private static final String TAG = "BaseReactActivity"; private static final String REDBOX_PERMISSION_MESSAGE = "Overlay permissions needs to be granted in order for react native apps to run in dev mode"; @@ -57,6 +61,7 @@ public abstract class BaseReactActivity extends AppCompatActivity implements Def private boolean mDoRefresh = false; private Menu mMenu; protected RnnToolBar mToolbar; + protected ActionBarDrawerToggle mDrawerToggle; /** * Returns the name of the bundle in assets. If this is null, and no file path is specified for @@ -243,7 +248,7 @@ public void push(Screen screen) { if (mToolbar != null && getCurrentNavigatorId().equals(screen.navigatorId) && getScreenStackSize() >= 1) { - mToolbar.showBackButton(screen); + mToolbar.setNavUpButton(screen); } } @@ -252,7 +257,7 @@ public Screen pop(String navigatorId) { if (mToolbar != null && getCurrentNavigatorId().equals(navigatorId) && getScreenStackSize() <= 2) { - mToolbar.hideBackButton(); + mToolbar.setNavUpButton(); } return null; @@ -261,7 +266,7 @@ public Screen pop(String navigatorId) { @CallSuper public Screen popToRoot(String navigatorId) { if (mToolbar != null) { - mToolbar.hideBackButton(); + mToolbar.setNavUpButton(); } return null; @@ -270,7 +275,7 @@ public Screen popToRoot(String navigatorId) { @CallSuper public Screen resetTo(Screen screen) { if (mToolbar != null) { - mToolbar.hideBackButton(); + mToolbar.setNavUpButton(); } return null; @@ -282,6 +287,14 @@ public Screen resetTo(Screen screen) { public abstract int getScreenStackSize(); + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mDrawerToggle != null) { + mDrawerToggle.onConfigurationChanged(newConfig); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { mMenu = menu; @@ -290,6 +303,12 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { + if (mDrawerToggle != null && + getScreenStackSize() == 1 && + mDrawerToggle.onOptionsItemSelected(item)) { + return true; + } + if (item.getItemId() == android.R.id.home) { onBackPressed(); } else { @@ -302,6 +321,14 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } + @Override + public void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + if (mDrawerToggle != null) { + mDrawerToggle.syncState(); + } + } + public Menu getMenu() { return mMenu; } @@ -402,4 +429,25 @@ public void toggleNavigationBar(ReadableMap params) { mToolbar.showToolbar(animated); } } + + public void toggleDrawer(ReadableMap params) { + if (mToolbar == null || mDrawerToggle == null) { + return; + } + + boolean animated = params.getBoolean(KEY_ANIMATED); + String side = params.getString(KEY_SIDE); + String to = params.getString(KEY_TO); + switch (to) { + case "open": + mToolbar.showDrawer(animated); + break; + case "closed": + mToolbar.hideDrawer(animated); + break; + default: + mToolbar.toggleDrawer(animated); + break; + } + } } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java index be5b7bdcedc..566308facce 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java @@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.widget.DrawerLayout; import android.view.Menu; import android.widget.FrameLayout; @@ -12,6 +13,7 @@ import com.facebook.react.bridge.ReadableMap; import com.reactnativenavigation.R; import com.reactnativenavigation.core.RctManager; +import com.reactnativenavigation.core.objects.Drawer; import com.reactnativenavigation.core.objects.Screen; import com.reactnativenavigation.views.RnnToolBar; import com.reactnativenavigation.views.ScreenStack; @@ -26,6 +28,7 @@ * Created by guyc on 02/04/16. */ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener { + public static final String DRAWER_PARAMS = "drawerParams"; public static final String EXTRA_SCREENS = "extraScreens"; private static final String TAB_STYLE_BUTTON_COLOR = "tabBarButtonColor"; @@ -41,6 +44,8 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi private AHBottomNavigation mBottomNavigation; private FrameLayout mContentFrame; private ArrayList mScreenStacks; + private ScreenStack mDrawerStack; + private DrawerLayout mDrawerLayout; private int mCurrentStackPosition = 0; @Override @@ -53,12 +58,28 @@ protected void handleOnCreate() { mContentFrame = (FrameLayout) findViewById(R.id.contentFrame); ArrayList screens = (ArrayList) getIntent().getSerializableExtra(EXTRA_SCREENS); + Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS); mBottomNavigation.setForceTint(true); + setupDrawer(drawer, screens.get(0)); setupToolbar(screens); setupTabs(getIntent().getExtras()); setupPages(screens); } + protected void setupDrawer(Drawer drawer, Screen screen) { + if (drawer == null || drawer.left == null) { + return; + } + + mDrawerStack = new ScreenStack(this); + FrameLayout drawerFrame = (FrameLayout) findViewById(R.id.drawerFrame); + drawerFrame.addView(mDrawerStack); + mDrawerStack.push(drawer.left); + + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout); + mDrawerToggle = mToolbar.setupDrawer(mDrawerLayout, drawer.left, screen); + } + private void setupPages(ArrayList screens) { new SetupTabsTask(this, screens).execute(); } diff --git a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java index f3fb0bb63f1..29b4a9ded39 100644 --- a/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java +++ b/android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java @@ -1,9 +1,11 @@ package com.reactnativenavigation.activities; +import android.support.v4.widget.DrawerLayout; import android.widget.FrameLayout; import com.reactnativenavigation.R; import com.reactnativenavigation.core.RctManager; +import com.reactnativenavigation.core.objects.Drawer; import com.reactnativenavigation.core.objects.Screen; import com.reactnativenavigation.views.RnnToolBar; import com.reactnativenavigation.views.ScreenStack; @@ -12,11 +14,13 @@ * Created by guyc on 05/04/16. */ public class SingleScreenActivity extends BaseReactActivity { - + public static final String DRAWER_PARAMS = "drawerParams"; public static final String EXTRA_SCREEN = "extraScreen"; - private ScreenStack mScreenStack; private String mNavigatorId; + private ScreenStack mScreenStack; + private ScreenStack mDrawerStack; + private DrawerLayout mDrawerLayout; @Override protected void handleOnCreate() { @@ -26,7 +30,10 @@ protected void handleOnCreate() { mToolbar = (RnnToolBar) findViewById(R.id.toolbar); Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN); + Drawer drawer = (Drawer) getIntent().getSerializableExtra(DRAWER_PARAMS); + mNavigatorId = screen.navigatorId; + setupDrawer(drawer, screen); setupToolbar(screen); mScreenStack = new ScreenStack(this); @@ -35,6 +42,20 @@ protected void handleOnCreate() { mScreenStack.push(screen); } + protected void setupDrawer(Drawer drawer, Screen screen) { + if (drawer == null || drawer.left == null) { + return; + } + + mDrawerStack = new ScreenStack(this); + FrameLayout drawerFrame = (FrameLayout) findViewById(R.id.drawerFrame); + drawerFrame.addView(mDrawerStack); + mDrawerStack.push(drawer.left); + + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout); + mDrawerToggle = mToolbar.setupDrawer(mDrawerLayout, drawer.left, screen); + } + protected void setupToolbar(Screen screen) { mToolbar.update(screen); setNavigationStyle(screen); diff --git a/android/app/src/main/java/com/reactnativenavigation/core/objects/Drawer.java b/android/app/src/main/java/com/reactnativenavigation/core/objects/Drawer.java new file mode 100644 index 00000000000..4f87c55e813 --- /dev/null +++ b/android/app/src/main/java/com/reactnativenavigation/core/objects/Drawer.java @@ -0,0 +1,23 @@ +package com.reactnativenavigation.core.objects; + +import com.facebook.react.bridge.ReadableMap; + +import java.io.Serializable; + +public class Drawer extends JsonObject implements Serializable { + private static final long serialVersionUID = 982836768712398756L; + + private static final String KEY_LEFT = "left"; + private static final String KEY_RIGHT = "right"; + private static final String KEY_DISABLE_OPEN_GESTURE = "disableOpenGesture"; + + public final Screen left; + public final Screen right; + public final boolean disableOpenGesture; + + public Drawer(ReadableMap params) { + left = params.hasKey(KEY_LEFT) ? new Screen(params.getMap(KEY_LEFT)) : null; + right = params.hasKey(KEY_RIGHT) ? new Screen(params.getMap(KEY_RIGHT)) : null; + disableOpenGesture = getBoolean(params, KEY_DISABLE_OPEN_GESTURE); + } +} diff --git a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java index 728aec19b99..b066eb52283 100644 --- a/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java +++ b/android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java @@ -15,6 +15,7 @@ import com.reactnativenavigation.activities.RootActivity; import com.reactnativenavigation.activities.SingleScreenActivity; import com.reactnativenavigation.controllers.ModalController; +import com.reactnativenavigation.core.objects.Drawer; import com.reactnativenavigation.core.objects.Screen; import com.reactnativenavigation.modal.RnnModal; import com.reactnativenavigation.utils.BridgeUtils; @@ -40,7 +41,7 @@ public String getName() { } @ReactMethod - public void startTabBasedApp(ReadableArray screens, ReadableMap style) { + public void startTabBasedApp(ReadableArray screens, ReadableMap style, ReadableMap drawerParams) { Activity context = ContextProvider.getActivityContext(); if (context != null && !context.isFinishing()) { Intent intent = new Intent(context, BottomTabActivity.class); @@ -48,6 +49,9 @@ public void startTabBasedApp(ReadableArray screens, ReadableMap style) { Bundle extras = new Bundle(); extras.putSerializable(BottomTabActivity.EXTRA_SCREENS, createScreens(screens)); + if (drawerParams != null) { + extras.putSerializable(BottomTabActivity.DRAWER_PARAMS, new Drawer(drawerParams)); + } if (style != null) { BridgeUtils.addMapToBundle(((ReadableNativeMap) style).toHashMap(), extras); } @@ -70,7 +74,7 @@ private ArrayList createScreens(ReadableArray screens) { } @ReactMethod - public void startSingleScreenApp(ReadableMap screen) { + public void startSingleScreenApp(ReadableMap screen, ReadableMap drawerParams) { BaseReactActivity context = ContextProvider.getActivityContext(); if (context != null && !context.isFinishing()) { Intent intent = new Intent(context, SingleScreenActivity.class); @@ -78,6 +82,9 @@ public void startSingleScreenApp(ReadableMap screen) { Bundle extras = new Bundle(); extras.putSerializable(SingleScreenActivity.EXTRA_SCREEN, new Screen(screen)); + if (drawerParams != null) { + extras.putSerializable(SingleScreenActivity.DRAWER_PARAMS, new Drawer(drawerParams)); + } intent.putExtras(extras); context.startActivity(intent); @@ -143,6 +150,20 @@ public void run() { }); } + @ReactMethod + public void toggleDrawer(final ReadableMap params) { + final BaseReactActivity context = ContextProvider.getActivityContext(); + if (context == null || context.isFinishing()) { + return; + } + context.runOnUiThread(new Runnable() { + @Override + public void run() { + context.toggleDrawer(params); + } + }); + } + @ReactMethod public void toggleNavigationBar(final ReadableMap params) { final BaseReactActivity context = ContextProvider.getActivityContext(); diff --git a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java index 71e99e078ce..6722980763a 100644 --- a/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java +++ b/android/app/src/main/java/com/reactnativenavigation/views/RnnToolBar.java @@ -8,10 +8,13 @@ import android.support.annotation.UiThread; import android.support.v4.content.ContextCompat; import android.support.v4.content.res.ResourcesCompat; +import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; +import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; @@ -20,6 +23,7 @@ import com.reactnativenavigation.core.objects.Button; import com.reactnativenavigation.core.objects.Screen; import com.reactnativenavigation.utils.ContextProvider; +import com.reactnativenavigation.utils.IconUtils; import com.reactnativenavigation.utils.ImageUtils; import java.lang.ref.WeakReference; @@ -33,8 +37,13 @@ public class RnnToolBar extends Toolbar { private List mScreens; + private AsyncTask mDrawerIconTask; private AsyncTask mSetupToolbarTask; private Drawable mBackground; + private Drawable mDrawerIcon; + private Screen mDrawerScreen; + private DrawerLayout mDrawerLayout; + private ActionBarDrawerToggle mDrawerToggle; public RnnToolBar(Context context) { super(context); @@ -91,11 +100,70 @@ public void handleOnCreateOptionsMenuAsync() { setupToolbarButtonsAsync(null, mScreens.get(0)); } + public ActionBarDrawerToggle setupDrawer(DrawerLayout drawerLayout, Screen drawerScreen, Screen screen) { + if (drawerLayout == null || drawerScreen == null) { + return null; + } + + mDrawerLayout = drawerLayout; + mDrawerScreen = drawerScreen; + mDrawerToggle = new ActionBarDrawerToggle( + ContextProvider.getActivityContext(), + mDrawerLayout, + this, + R.string.drawer_open, + R.string.drawer_close + ); + mDrawerLayout.setDrawerListener(mDrawerToggle); + setupDrawerIconAsync(drawerScreen.icon, screen); + + return mDrawerToggle; + } + + public void setDrawerIcon(Drawable drawerIcon) { + mDrawerIcon = drawerIcon; + setNavUpButton(); + } + + public void showDrawer(boolean animated) { + if (mDrawerLayout == null) { + return; + } + + mDrawerLayout.openDrawer(Gravity.LEFT); + } + + public void hideDrawer(boolean animated) { + if (mDrawerLayout == null) { + return; + } + + mDrawerLayout.closeDrawer(Gravity.LEFT); + } + + public void toggleDrawer(boolean animated) { + if (mDrawerLayout == null) { + return; + } + + boolean visible = mDrawerLayout.isDrawerOpen(Gravity.LEFT); + if (visible) { + hideDrawer(animated); + } else { + showDrawer(animated); + } + } + + public void setupDrawerIconAsync(String drawerIconSource, Screen screen) { + if (mDrawerIconTask == null) { + mDrawerIconTask = new SetupDrawerIconTask(this, drawerIconSource, screen).execute(); + } + } + public void setupToolbarButtonsAsync(Screen newScreen) { this.setupToolbarButtonsAsync(null, newScreen); } - public void setupToolbarButtonsAsync(Screen oldScreen, Screen newScreen) { if (mSetupToolbarTask == null) { mSetupToolbarTask = new SetupToolbarButtonsTask(this, oldScreen, newScreen).execute(); @@ -126,12 +194,28 @@ private void hideToolbar() { hideToolbar(false); } + public void setNavUpButton() { + setNavUpButton(null); + } + @SuppressWarnings({"ConstantConditions"}) - public void showBackButton(Screen screen) { + public void setNavUpButton(Screen screen) { ActionBar actionBar = ContextProvider.getActivityContext().getSupportActionBar(); - Drawable backButton = setupBackButton(screen); - actionBar.setHomeAsUpIndicator(backButton); - actionBar.setDisplayHomeAsUpEnabled(true); + Drawable button = null; + boolean isBack = screen != null; + if (isBack) { + button = setupBackButton(screen); + } else if (mDrawerIcon != null) { + button = mDrawerIcon; + } + + actionBar.setHomeAsUpIndicator(button); + actionBar.setDisplayHomeAsUpEnabled(button != null || mDrawerToggle != null); + + // This will get us back the default theme icon for the drawer + if (!isBack && mDrawerToggle != null && mDrawerIcon == null) { + mDrawerToggle.syncState(); + } } @SuppressLint("PrivateResource") @@ -152,11 +236,6 @@ private Drawable setupBackButton(Screen screen) { return backButton; } - @SuppressWarnings({"ConstantConditions"}) - public void hideBackButton() { - ContextProvider.getActivityContext().getSupportActionBar().setDisplayHomeAsUpEnabled(false); - } - /** * Update the ToolBar from screen. This function sets any properties that are defined * in the screen. @@ -170,6 +249,42 @@ public void update(Screen screen) { setupToolbarButtonsAsync(screen); } + private static class SetupDrawerIconTask extends AsyncTask { + private final WeakReference mToolbarWR; + private final String mDrawerIconSource; + private final Integer mTintColor; + + public SetupDrawerIconTask(RnnToolBar toolBar, String drawerIconSource, Screen screen) { + mToolbarWR = new WeakReference<>(toolBar); + mDrawerIconSource = drawerIconSource; + mTintColor = screen.buttonsTintColor; + } + + @Override + protected Drawable doInBackground(Void... params) { + Context context = ContextProvider.getActivityContext(); + if (context == null) { + return null; + } + + return IconUtils.getIcon(context, mDrawerIconSource); + } + + @Override + protected void onPostExecute(Drawable drawerIcon) { + if (drawerIcon == null) { + return; + } + + if (mTintColor != null) { + ImageUtils.tint(drawerIcon, mTintColor); + } + RnnToolBar toolBar = mToolbarWR.get(); + toolBar.setDrawerIcon(drawerIcon); + mToolbarWR.clear(); + } + } + private static class SetupToolbarButtonsTask extends AsyncTask> { private final List