mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-26 05:25:30 +08:00
Compare commits
3 Commits
2.0.0-alph
...
2.0.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65bd436cbe | ||
|
|
a0745762ba | ||
|
|
89658d9361 |
@@ -155,9 +155,8 @@ Defines how the method that should be used to present the given screen. It is a
|
||||
The config component is expected to be rendered as a direct children of `<Screen>`. It provides an ability to configure native navigation header that gets rendered as a part of native screen stack. The component acts as a "virtual" element that is not directly rendered under `Screen`. You can use its properties to customize platform native header for the parent screen and also render react-native components that you'd like to be displayed inside the header (e.g. in the title are or on the side).
|
||||
|
||||
Along with this component properties that can be used to customize header behavior one can also use one or the below component containers to render custom react-native content in different areas of the native header:
|
||||
- `ScreenStackHeaderTitleView` – react native views rendered as children will appear on the navigation bar in the place of title. Note that title is aligned next to back button on Android while it is centered on iOS.
|
||||
- `ScreenStackHeaderCenterView` – the childern will render in the center of the native navigation bar (on iOS this has the same behavior as `ScreenStackHeaderTitleView` container)
|
||||
- `ScreenStackHeaderRightView` – the children will render on the right hand side of the navigation bar (or on the left hand side in case LTR locales are set on the user's device)
|
||||
- `ScreenStackHeaderCenterView` – the childern will render in the center of the native navigation bar.
|
||||
- `ScreenStackHeaderRightView` – the children will render on the right hand side of the navigation bar (or on the left hand side in case LTR locales are set on the user's device).
|
||||
- `ScreenStackHeaderLeftView` – the children will render on the left hand side of the navigation bar (or on the right hand side in case LTR locales are set on the user's device).
|
||||
|
||||
Below is a list of properties that can be set with `ScreenStackHeaderConfig` component:
|
||||
|
||||
@@ -215,11 +215,10 @@ public class ScreenStackHeaderConfig extends ViewGroup {
|
||||
case RIGHT:
|
||||
params.gravity = Gravity.RIGHT;
|
||||
break;
|
||||
case TITLE:
|
||||
params.width = LayoutParams.MATCH_PARENT;
|
||||
mToolbar.setTitle(null);
|
||||
case CENTER:
|
||||
params.width = LayoutParams.MATCH_PARENT;
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
mToolbar.setTitle(null);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,21 +9,14 @@ import com.facebook.react.views.view.ReactViewGroup;
|
||||
|
||||
public class ScreenStackHeaderSubview extends ReactViewGroup {
|
||||
|
||||
public class Measurements {
|
||||
public int width;
|
||||
public int height;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
LEFT,
|
||||
CENTER,
|
||||
TITLE,
|
||||
RIGHT,
|
||||
BACK
|
||||
}
|
||||
|
||||
private int mReactWidth, mReactHeight;
|
||||
private final UIManagerModule mUIManager;
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
@@ -43,26 +36,13 @@ public class ScreenStackHeaderSubview extends ReactViewGroup {
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (changed && (mType == Type.CENTER)) {
|
||||
// if we want the view to be centered we need to account for the fact that right and left
|
||||
// paddings may not be equal.
|
||||
Measurements measurements = new Measurements();
|
||||
View parent = (View) getParent();
|
||||
int parentWidth = parent.getWidth();
|
||||
int rightPadding = parentWidth - right;
|
||||
int leftPadding = left;
|
||||
measurements.width = Math.max(0, parentWidth - 2 * Math.max(rightPadding, leftPadding));
|
||||
measurements.height = bottom - top;
|
||||
mUIManager.setViewLocalData(getId(), measurements);
|
||||
}
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
// no-op
|
||||
}
|
||||
|
||||
private Type mType = Type.RIGHT;
|
||||
|
||||
public ScreenStackHeaderSubview(ReactContext context) {
|
||||
super(context);
|
||||
mUIManager = context.getNativeModule(UIManagerModule.class);
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.swmansion.rnscreens;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.views.view.ReactViewGroup;
|
||||
@@ -11,15 +9,6 @@ import com.facebook.react.views.view.ReactViewManager;
|
||||
@ReactModule(name = ScreenStackHeaderSubviewManager.REACT_CLASS)
|
||||
public class ScreenStackHeaderSubviewManager extends ReactViewManager {
|
||||
|
||||
private static class SubviewShadowNode extends LayoutShadowNode {
|
||||
@Override
|
||||
public void setLocalData(Object data) {
|
||||
ScreenStackHeaderSubview.Measurements measurements = (ScreenStackHeaderSubview.Measurements) data;
|
||||
setStyleWidth(measurements.width);
|
||||
setStyleHeight(measurements.height);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String REACT_CLASS = "RNSScreenStackHeaderSubview";
|
||||
|
||||
@Override
|
||||
@@ -32,19 +21,12 @@ public class ScreenStackHeaderSubviewManager extends ReactViewManager {
|
||||
return new ScreenStackHeaderSubview(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutShadowNode createShadowNodeInstance(ReactApplicationContext context) {
|
||||
return new SubviewShadowNode();
|
||||
}
|
||||
|
||||
@ReactProp(name = "type")
|
||||
public void setType(ScreenStackHeaderSubview view, String type) {
|
||||
if ("left".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.LEFT);
|
||||
} else if ("center".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.CENTER);
|
||||
} else if ("title".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.TITLE);
|
||||
} else if ("right".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.RIGHT);
|
||||
} else if ("back".equals(type)) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
ScreenStackHeaderBackButtonImage,
|
||||
ScreenStackHeaderLeftView,
|
||||
ScreenStackHeaderRightView,
|
||||
ScreenStackHeaderTitleView,
|
||||
ScreenStackHeaderCenterView,
|
||||
} from 'react-native-screens';
|
||||
|
||||
function renderComponentOrThunk(componentOrThunk, props) {
|
||||
@@ -141,9 +141,9 @@ class StackView extends React.Component {
|
||||
headerOptions.title = options.headerTitle;
|
||||
} else {
|
||||
children.push(
|
||||
<ScreenStackHeaderTitleView key="title">
|
||||
<ScreenStackHeaderCenterView key="center">
|
||||
{renderComponentOrThunk(options.headerTitle, { scene })}
|
||||
</ScreenStackHeaderTitleView>
|
||||
</ScreenStackHeaderCenterView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,28 +20,6 @@
|
||||
@end
|
||||
|
||||
|
||||
@interface RNSScreenHeaderItemMeasurements : NSObject
|
||||
@property (nonatomic, readonly) CGSize headerSize;
|
||||
@property (nonatomic, readonly) CGFloat leftPadding;
|
||||
@property (nonatomic, readonly) CGFloat rightPadding;
|
||||
|
||||
- (instancetype)initWithHeaderSize:(CGSize)headerSize leftPadding:(CGFloat)leftPadding rightPadding:(CGFloat)rightPadding;
|
||||
@end
|
||||
|
||||
@implementation RNSScreenHeaderItemMeasurements
|
||||
|
||||
- (instancetype)initWithHeaderSize:(CGSize)headerSize leftPadding:(CGFloat)leftPadding rightPadding:(CGFloat)rightPadding
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_headerSize = headerSize;
|
||||
_leftPadding = leftPadding;
|
||||
_rightPadding = rightPadding;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RNSScreenStackHeaderSubview : UIView
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *bridge;
|
||||
@@ -50,6 +28,9 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderSubview
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderConfig {
|
||||
NSMutableArray<RNSScreenStackHeaderSubview *> *_reactSubviews;
|
||||
}
|
||||
@@ -403,7 +384,6 @@
|
||||
}
|
||||
case RNSScreenStackHeaderSubviewTypeCenter:
|
||||
case RNSScreenStackHeaderSubviewTypeTitle: {
|
||||
subview.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
navitem.titleView = subview;
|
||||
break;
|
||||
}
|
||||
@@ -477,67 +457,6 @@ RCT_ENUM_CONVERTER(RNSScreenStackHeaderSubviewType, (@{
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderSubview
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_bridge = bridge;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
if (!self.translatesAutoresizingMaskIntoConstraints) {
|
||||
CGSize size = self.superview.frame.size;
|
||||
CGFloat right = size.width - self.frame.size.width - self.frame.origin.x;
|
||||
CGFloat left = self.frame.origin.x;
|
||||
[_bridge.uiManager
|
||||
setLocalData:[[RNSScreenHeaderItemMeasurements alloc]
|
||||
initWithHeaderSize:size
|
||||
leftPadding:left rightPadding:right]
|
||||
forView:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
if (self.translatesAutoresizingMaskIntoConstraints) {
|
||||
[super reactSetFrame:frame];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)intrinsicContentSize
|
||||
{
|
||||
return UILayoutFittingExpandedSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RNSScreenStackHeaderSubviewShadow : RCTShadowView
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderSubviewShadow
|
||||
|
||||
- (void)setLocalData:(RNSScreenHeaderItemMeasurements *)data
|
||||
{
|
||||
self.width = (YGValue){data.headerSize.width - data.leftPadding - data.rightPadding, YGUnitPoint};
|
||||
self.height = (YGValue){data.headerSize.height, YGUnitPoint};
|
||||
|
||||
if (data.leftPadding > data.rightPadding) {
|
||||
self.paddingLeft = (YGValue){0, YGUnitPoint};
|
||||
self.paddingRight = (YGValue){data.leftPadding - data.rightPadding, YGUnitPoint};
|
||||
} else {
|
||||
self.paddingLeft = (YGValue){data.rightPadding - data.leftPadding, YGUnitPoint};
|
||||
self.paddingRight = (YGValue){0, YGUnitPoint};
|
||||
}
|
||||
[self didSetProps:@[@"width", @"height", @"paddingLeft", @"paddingRight"]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderSubviewManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
@@ -546,12 +465,7 @@ RCT_EXPORT_VIEW_PROPERTY(type, RNSScreenStackHeaderSubviewType)
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RNSScreenStackHeaderSubview alloc] initWithBridge:self.bridge];
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
{
|
||||
return [RNSScreenStackHeaderSubviewShadow new];
|
||||
return [RNSScreenStackHeaderSubview new];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-screens",
|
||||
"version": "2.0.0-alpha.33",
|
||||
"version": "2.0.0-alpha.34",
|
||||
"description": "First incomplete navigation solution for your react-native app.",
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
|
||||
10
src/screens.d.ts
vendored
10
src/screens.d.ts
vendored
@@ -3,7 +3,13 @@
|
||||
|
||||
declare module 'react-native-screens' {
|
||||
import { ComponentClass } from 'react';
|
||||
import { ViewProps, Animated, NativeSyntheticEvent, NativeTouchEvent, ImageProps } from 'react-native';
|
||||
import {
|
||||
ViewProps,
|
||||
Animated,
|
||||
NativeSyntheticEvent,
|
||||
NativeTouchEvent,
|
||||
ImageProps,
|
||||
} from 'react-native';
|
||||
|
||||
export function useScreens(shouldUseScreens?: boolean): void;
|
||||
export function enableScreens(shouldEnableScreens?: boolean): void;
|
||||
@@ -41,7 +47,6 @@ declare module 'react-native-screens' {
|
||||
gestureEnabled?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export type ScreenContainerProps = ViewProps;
|
||||
|
||||
export interface ScreenStackProps extends ViewProps {
|
||||
@@ -135,7 +140,6 @@ declare module 'react-native-screens' {
|
||||
export const ScreenStackHeaderBackButtonImage: ComponentClass<ImageProps>;
|
||||
export const ScreenStackHeaderLeftView: ComponentClass<ViewProps>;
|
||||
export const ScreenStackHeaderRightView: ComponentClass<ViewProps>;
|
||||
export const ScreenStackHeaderTitleView: ComponentClass<ViewProps>;
|
||||
export const ScreenStackHeaderConfig: ComponentClass<
|
||||
ScreenStackHeaderConfigProps
|
||||
>;
|
||||
|
||||
@@ -171,14 +171,6 @@ const ScreenStackHeaderLeftView = props => (
|
||||
/>
|
||||
);
|
||||
|
||||
const ScreenStackHeaderTitleView = props => (
|
||||
<ScreensNativeModules.NativeScreenStackHeaderSubview
|
||||
{...props}
|
||||
type="title"
|
||||
style={styles.headerSubview}
|
||||
/>
|
||||
);
|
||||
|
||||
const ScreenStackHeaderCenterView = props => (
|
||||
<ScreensNativeModules.NativeScreenStackHeaderSubview
|
||||
{...props}
|
||||
@@ -210,7 +202,6 @@ module.exports = {
|
||||
ScreenStackHeaderBackButtonImage,
|
||||
ScreenStackHeaderRightView,
|
||||
ScreenStackHeaderLeftView,
|
||||
ScreenStackHeaderTitleView,
|
||||
ScreenStackHeaderCenterView,
|
||||
|
||||
enableScreens,
|
||||
|
||||
Reference in New Issue
Block a user