Comments (4)
需要在原生端自定义容器和对应的 Navigator。
例如 iOS 可以这么弄:
// DeckViewController.h
#import <NavigationHybrid/NavigationHybrid.h>
@interface DeckViewController : HBDViewController
@property(nonatomic, strong) UIViewController *firstDeckController;
@property(nonatomic, strong) UIViewController *secondDeckController;
@end
// DeckViewController.m
#import "DeckViewController.h"
@interface DeckViewController ()
@end
@implementation DeckViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self addChildViewController:self.firstDeckController];
self.firstDeckController.view.frame = self.view.bounds;
[self.view addSubview:self.firstDeckController.view];
[self.firstDeckController didMoveToParentViewController:self];
self.firstDeckController.definesPresentationContext = YES;
[self addChildViewController:self.secondDeckController];
self.secondDeckController.view.frame = self.view.bounds;
[self.view addSubview:self.secondDeckController.view];
[self.secondDeckController didMoveToParentViewController:self];
}
- (UINavigationController *)navigationController {
if ([self.firstDeckController isKindOfClass:[UINavigationController class]]) {
return (UINavigationController *)self.firstDeckController;
}
return self.firstDeckController.navigationController;
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.firstDeckController;
}
@end
一个自定义容器对应一个 Navigator
// DeckNavigator.h
#import <NavigationHybrid/NavigationHybrid.h>
@interface DeckNavigator : NSObject <HBDNavigator>
@end
// DeckNavigator.m
#import "DeckNavigator.h"
#import "DeckViewController.h"
@implementation DeckNavigator
- (NSString *)name {
return @"deck";
}
- (NSArray<NSString *> *)supportActions {
return @[];
}
- (UIViewController *)createViewControllerWithLayout:(NSDictionary *)layout {
NSArray *deck = [layout objectForKey:self.name];
if (deck && deck.count == 2) {
NSDictionary *first = [deck objectAtIndex:0];
NSDictionary *second = [deck objectAtIndex:1];
UIViewController *firstController = [[HBDReactBridgeManager sharedInstance] controllerWithLayout:first];
UIViewController *secondController = [[HBDReactBridgeManager sharedInstance] controllerWithLayout:second];
if (firstController && secondController) {
DeckViewController *deckController = [[DeckViewController alloc] init];
deckController.firstDeckController = firstController;
deckController.secondDeckController = secondController;
return deckController;
}
}
return nil;
}
- (BOOL)buildRouteGraphWithController:(UIViewController *)vc graph:(NSMutableArray *)container {
if ([vc isKindOfClass:[DeckViewController class]]) {
DeckViewController *deck = (DeckViewController *)vc;
NSMutableArray *children = [[NSMutableArray alloc] init];
[[HBDReactBridgeManager sharedInstance] routeGraphWithController:deck.firstDeckController container:children];
[[HBDReactBridgeManager sharedInstance] routeGraphWithController:deck.secondDeckController container:children];
UIViewController *presented = deck.firstDeckController.presentedViewController;
while (presented && !presented.isBeingDismissed ) {
[[HBDReactBridgeManager sharedInstance] routeGraphWithController:presented container:children];
presented = presented.presentedViewController;
}
[container addObject:@{ @"type": self.name, self.name: children }];
return YES;
}
return NO;
}
- (HBDViewController *)primaryChildViewControllerInController:(UIViewController *)vc {
if ([vc isKindOfClass:[DeckViewController class]]) {
DeckViewController *deck = (DeckViewController *)vc;
UIViewController *presented = deck.firstDeckController;
while (true) {
if (presented.presentedViewController && !presented.presentedViewController.isBeingDismissed) {
presented = presented.presentedViewController;
} else {
return [[HBDReactBridgeManager sharedInstance] primaryChildViewControllerInController:presented];
}
}
}
return nil;
}
- (void)handleNavigationWithViewController:(UIViewController *)vc action:(NSString *)action extras:(NSDictionary *)extras {
}
@end
注册这个 Navigator
// AppDelegate.m
#import "DeckNavigator.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[HBDReactBridgeManager sharedInstance] registerNavigator:[DeckNavigator new]];
}
在 RN 中使用这个自定义容器
Navigator.setRoot(
{
deck: [
{
tabs: [
{
screen: { moduleName: 'Navigation' },
},
{
screen: { moduleName: 'Options' },
},
],
},
{
// 这一层总是在顶层
screen: { moduleName: 'Transparent' },
},
],
},
true
);
from hybrid-navigation.
Android 可以这么弄:
<!-- fragment_deck.xml -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/first"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/second"
/>
</FrameLayout>
// DoubleDeckFragment.java
public class DoubleDeckFragment extends AwesomeFragment {
private static final String SAVED_STATE_FIRST_TAG = "deck_first_tag";
private static final String SAVED_STATE_SECOND_TAG = "deck_second_tag";
private String firstTag;
private String secondTag;
@Override
public boolean isParentFragment() {
return true;
}
@Override
protected AwesomeFragment childFragmentForAppearance() {
return (AwesomeFragment) getChildFragmentManager().findFragmentById(R.id.second);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_deck, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
if (firstDeckFragment == null || secondDeckFragment == null) {
throw new IllegalArgumentException("必须设定 first and second deck");
}
FragmentHelper.addFragmentToAddedList(getChildFragmentManager(), R.id.second, secondDeckFragment,false);
FragmentHelper.addFragmentToBackStack(getChildFragmentManager(), R.id.first, firstDeckFragment, PresentAnimation.None);
} else {
firstTag = savedInstanceState.getString(SAVED_STATE_FIRST_TAG);
secondTag = savedInstanceState.getString(SAVED_STATE_SECOND_TAG);
firstDeckFragment = (AwesomeFragment) getChildFragmentManager().findFragmentByTag(firstTag);
secondDeckFragment = (AwesomeFragment) getChildFragmentManager().findFragmentByTag(secondTag);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(SAVED_STATE_FIRST_TAG, firstTag);
outState.putString(SAVED_STATE_SECOND_TAG, secondTag);
}
@Nullable
@Override
public NavigationFragment getNavigationFragment() {
if (!firstDeckFragment.isAdded()) {
return null;
}
if (firstDeckFragment instanceof NavigationFragment) {
return (NavigationFragment) firstDeckFragment;
}
return null;
}
private AwesomeFragment firstDeckFragment;
public void setFirstDeckFragment(AwesomeFragment firstDeckFragment) {
this.firstDeckFragment = firstDeckFragment;
firstDeckFragment.setDefinesPresentationContext(true);
this.firstTag = firstDeckFragment.getSceneId();
}
private AwesomeFragment secondDeckFragment;
public void setSecondDeckFragment(AwesomeFragment secondDeckFragment) {
this.secondDeckFragment = secondDeckFragment;
this.secondTag = secondDeckFragment.getSceneId();
}
public AwesomeFragment getFirstDeckFragment() {
return firstDeckFragment;
}
public AwesomeFragment getSecondDeckFragment() {
return secondDeckFragment;
}
public AwesomeFragment getPrimaryFragment() {
return (AwesomeFragment) getChildFragmentManager().findFragmentById(R.id.first);
}
}
// DeckNavigator.java
public class DeckNavigator implements Navigator {
private List<String> supportActions = Collections.emptyList();
@Override
public String name() {
return "deck";
}
@Override
public List<String> supportActions() {
return supportActions;
}
@Nullable
@Override
public AwesomeFragment createFragment(ReadableMap layout) {
if (layout.hasKey(name())) {
ReadableArray deck = layout.getArray(name());
if (deck.size() == 2) {
ReadableMap first = deck.getMap(0);
ReadableMap second = deck.getMap(1);
AwesomeFragment firstFragment = getReactBridgeManager().createFragment(first);
AwesomeFragment secondFragment = getReactBridgeManager().createFragment(second);
DoubleDeckFragment doubleDeckFragment = new DoubleDeckFragment();
doubleDeckFragment.setFirstDeckFragment(firstFragment);
doubleDeckFragment.setSecondDeckFragment(secondFragment);
return doubleDeckFragment;
}
}
return null;
}
@Override
public boolean buildRouteGraph(AwesomeFragment fragment, ArrayList<Bundle> graph, ArrayList<Bundle> modalContainer) {
if (fragment instanceof DoubleDeckFragment) {
DoubleDeckFragment deck = (DoubleDeckFragment) fragment;
ArrayList<Bundle> children = new ArrayList<>();
List<AwesomeFragment> fragments = deck.getChildFragmentsAtAddedList();
for (int i = 0; i < fragments.size(); i++) {
AwesomeFragment child = fragments.get(i);
if (!child.getShowsDialog()) {
getReactBridgeManager().buildRouteGraph(child, children, modalContainer);
}
}
Bundle bundle = new Bundle();
bundle.putString("type", name());
bundle.putParcelableArrayList(name(), children);
graph.add(bundle);
return true;
}
return false;
}
@Override
public HybridFragment primaryChildFragment(@NonNull AwesomeFragment fragment) {
if (fragment instanceof DoubleDeckFragment) {
DoubleDeckFragment doubleDeckFragment = (DoubleDeckFragment) fragment;
return getReactBridgeManager().primaryChildFragment(doubleDeckFragment.getPrimaryFragment());
}
return null;
}
@Override
public void handleNavigation(@NonNull AwesomeFragment fragment, @NonNull String action, @NonNull ReadableMap extras) {
}
private ReactBridgeManager getReactBridgeManager() {
return ReactBridgeManager.instance;
}
}
注册这个 Navigator
public class MainApplication extends MultiDexApplication implements ReactApplication{
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, false);
ReactBridgeManager bridgeManager = ReactBridgeManager.instance;
bridgeManager.install(getReactNativeHost());
bridgeManager.registerNavigator(new DeckNavigator());
}
}
from hybrid-navigation.
本库内置了 drawer、tabs、stack、screen 四个容器和对应的 Navigator, 如果有必要,完全可以自定义自己的容器和 Navigator.
from hybrid-navigation.
放在 deck 顶层的 component 需要设置背景透明,并允许事件穿透
static navigationItem = {
screenColor: '#00000000',
passThroughTouches: true,
};
from hybrid-navigation.
Related Issues (20)
- Navigator.setInterceptor((action, from, to, extras), to字段返回undefined HOT 2
- 请问如何改变 showModal 默认的背景透明度? HOT 4
- npm install后在ios文件夹中未发现podfile。 HOT 1
- Reload后会初始化两次Stack的screen HOT 3
- [Android] 隐藏TopBar并设置titleItem会导致crash
- ReactRegistry.registerComponent可以懒注册吗 HOT 2
- 能否增加一个已有的原生项目相关的例子。 HOT 4
- 建议允许显示多个modal并可关闭指定Modal HOT 7
- navigationBarHiddenAndroid 参数在打开Modal时会发生抖动 HOT 10
- 建议: 能不能出个Demo 能用的? 按照教程来搞完全报错 HOT 4
- 大佬有联系方式吗
- 教程中android配置去掉ReactActivity怎么跑起来的? HOT 1
- app启动闪退 HOT 7
- navigationBarHiddenAndroid 在Android 7上不生效 HOT 1
- react-native-safe-area-context问题 HOT 4
- when will support New Architecture HOT 1
- 怎么和Expo集成? HOT 2
- [Navigation] React Component 还没有注册完毕 HOT 3
- Navigation.setDefaultOptions seems only works in andriod HOT 4
- 编译错误: 找不到符号 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hybrid-navigation.