mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-29 00:38:26 +08:00
Compare commits
13 Commits
2.0.0-alph
...
2.0.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b1b726723 | ||
|
|
4ce9469571 | ||
|
|
cef9b8f393 | ||
|
|
ecc4056559 | ||
|
|
71a02af309 | ||
|
|
c88da09348 | ||
|
|
9aac0b89f2 | ||
|
|
a02dd46eec | ||
|
|
0919404b2e | ||
|
|
e61b8b3bd6 | ||
|
|
77d877f0c1 | ||
|
|
15c27e3fe7 | ||
|
|
ed478a829d |
@@ -127,7 +127,7 @@ Otherwise the views will be attached as long as the parent container is attached
|
||||
|
||||
### `<ScreenStack>`
|
||||
|
||||
Screen stack component expects one or more `Screen` components as direct children and renders them in a platform native stack container (for iOS it is `UINavigationController` and for Android inside `Fragment` container). For `Screen` components placed as children of `ScteenStack` the `active` property is ignored and instead the screen that corresponds to the last child is rendered as active. All type of updates done to the list of children are acceptable, when the top element is exchanged the container will use platform default (unless customized) animation to transition between screens.
|
||||
Screen stack component expects one or more `Screen` components as direct children and renders them in a platform native stack container (for iOS it is `UINavigationController` and for Android inside `Fragment` container). For `Screen` components placed as children of `ScreenStack` the `active` property is ignored and instead the screen that corresponds to the last child is rendered as active. All type of updates done to the list of children are acceptable, when the top element is exchanged the container will use platform default (unless customized) animation to transition between screens.
|
||||
|
||||
`StackScreen` extends the capabilities of `Screen` component to allow additional customizations and to make it possible to handle events such as using hardware back or back gesture to dismiss the top screen. Below is the list of additional properties that can be used for `Screen` component:
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
@@ -15,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.views.text.ReactFontManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -184,6 +186,17 @@ public class ScreenStackHeaderConfig extends ViewGroup {
|
||||
ScreenStackHeaderSubview view = mConfigSubviews.get(i);
|
||||
ScreenStackHeaderSubview.Type type = view.getType();
|
||||
|
||||
if (type == ScreenStackHeaderSubview.Type.BACK) {
|
||||
// we special case BACK button header config type as we don't add it as a view into toolbar
|
||||
// but instead just copy the drawable from imageview that's added as a first child to it.
|
||||
View firstChild = view.getChildAt(0);
|
||||
if (!(firstChild instanceof ImageView)) {
|
||||
throw new JSApplicationIllegalArgumentException("Back button header config view should have Image as first child");
|
||||
}
|
||||
actionBar.setHomeAsUpIndicator(((ImageView) firstChild).getDrawable());
|
||||
continue;
|
||||
}
|
||||
|
||||
Toolbar.LayoutParams params =
|
||||
new Toolbar.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ public class ScreenStackHeaderSubview extends ReactViewGroup {
|
||||
LEFT,
|
||||
CENTER,
|
||||
TITLE,
|
||||
RIGHT
|
||||
RIGHT,
|
||||
BACK
|
||||
}
|
||||
|
||||
private int mReactWidth, mReactHeight;
|
||||
|
||||
@@ -47,6 +47,8 @@ public class ScreenStackHeaderSubviewManager extends ReactViewManager {
|
||||
view.setType(ScreenStackHeaderSubview.Type.TITLE);
|
||||
} else if ("right".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.RIGHT);
|
||||
} else if ("back".equals(type)) {
|
||||
view.setType(ScreenStackHeaderSubview.Type.BACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ScreenStack,
|
||||
Screen,
|
||||
ScreenStackHeaderConfig,
|
||||
ScreenStackHeaderBackButtonImage,
|
||||
ScreenStackHeaderLeftView,
|
||||
ScreenStackHeaderRightView,
|
||||
ScreenStackHeaderTitleView,
|
||||
@@ -29,7 +30,8 @@ class StackView extends React.Component {
|
||||
this.props.navigation.dispatch(StackActions.pop({ key: route.key }));
|
||||
};
|
||||
|
||||
_onSceneFocus = route => {
|
||||
_onSceneFocus = (route, descriptor) => {
|
||||
descriptor.options && descriptor.options.onAppear && descriptor.options.onAppear()
|
||||
this.props.navigation.dispatch(
|
||||
StackActions.completeTransition({ toChildKey: route.key })
|
||||
);
|
||||
@@ -93,6 +95,15 @@ class StackView extends React.Component {
|
||||
|
||||
const children = [];
|
||||
|
||||
if (options.backButtonImage) {
|
||||
children.push(
|
||||
<ScreenStackHeaderBackButtonImage
|
||||
key="backImage"
|
||||
source={options.backButtonImage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (options.headerLeft !== undefined) {
|
||||
children.push(
|
||||
<ScreenStackHeaderLeftView key="left">
|
||||
@@ -168,7 +179,7 @@ class StackView extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
let stackAnimation;
|
||||
let stackAnimation = options.stackAnimation;
|
||||
if (options.animationEnabled === false) {
|
||||
stackAnimation = 'none';
|
||||
}
|
||||
@@ -180,7 +191,7 @@ class StackView extends React.Component {
|
||||
style={options.cardStyle}
|
||||
stackAnimation={stackAnimation}
|
||||
stackPresentation={stackPresentation}
|
||||
onAppear={() => this._onSceneFocus(route)}
|
||||
onAppear={() => this._onSceneFocus(route, descriptor)}
|
||||
onDismissed={() => this._removeScene(route)}>
|
||||
{this._renderHeaderConfig(index, route, descriptor)}
|
||||
<SceneView
|
||||
@@ -211,7 +222,6 @@ const styles = StyleSheet.create({
|
||||
|
||||
function createStackNavigator(routeConfigMap, stackConfig = {}) {
|
||||
const router = StackRouter(routeConfigMap, stackConfig);
|
||||
|
||||
// Create a navigator with StackView as the view
|
||||
let Navigator = createNavigator(StackView, router, stackConfig);
|
||||
// if (!stackConfig.disableKeyboardHandling) {
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
if (_active) {
|
||||
[super reactSetFrame:frame];
|
||||
}
|
||||
// ignore setFrame call from react, the frame of this view
|
||||
// is controlled by the UIViewController it is contained in
|
||||
}
|
||||
|
||||
@@ -137,12 +137,16 @@
|
||||
|
||||
- (void)setModalViewControllers:(NSArray<UIViewController *> *)controllers
|
||||
{
|
||||
// when there is no change we return immediately. This check is important because sometime we may
|
||||
// accidently trigger modal dismiss if we don't verify to run the below code only when an actual
|
||||
// change in the list of presented modal was made.
|
||||
if ([_presentedModals isEqualToArray:controllers]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray<UIViewController *> *newControllers = [NSMutableArray arrayWithArray:controllers];
|
||||
[newControllers removeObjectsInArray:_presentedModals];
|
||||
|
||||
NSMutableArray<UIViewController *> *controllersToRemove = [NSMutableArray arrayWithArray:_presentedModals];
|
||||
[controllersToRemove removeObjectsInArray:controllers];
|
||||
|
||||
// find bottom-most controller that should stay on the stack for the duration of transition
|
||||
NSUInteger changeRootIndex = 0;
|
||||
UIViewController *changeRootController = _controller;
|
||||
@@ -173,9 +177,6 @@
|
||||
completion:nil];
|
||||
previous = next;
|
||||
}
|
||||
|
||||
[self->_presentedModals removeAllObjects];
|
||||
[self->_presentedModals addObjectsFromArray:controllers];
|
||||
};
|
||||
|
||||
if (changeRootController.presentedViewController) {
|
||||
@@ -185,10 +186,16 @@
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
[_presentedModals setArray:controllers];
|
||||
}
|
||||
|
||||
- (void)setPushViewControllers:(NSArray<UIViewController *> *)controllers
|
||||
{
|
||||
// when there is no change we return immediately
|
||||
if ([_controller.viewControllers isEqualToArray:controllers]) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIViewController *top = controllers.lastObject;
|
||||
UIViewController *lastTop = _controller.viewControllers.lastObject;
|
||||
|
||||
@@ -198,7 +205,7 @@
|
||||
// controller is still there
|
||||
BOOL firstTimePush = ![lastTop isKindOfClass:[RNSScreen class]];
|
||||
|
||||
BOOL shouldAnimate = !firstTimePush && ((RNSScreenView *) lastTop.view).stackAnimation != RNSScreenStackAnimationNone;
|
||||
BOOL shouldAnimate = !firstTimePush && ((RNSScreenView *) lastTop.view).stackAnimation != RNSScreenStackAnimationNone && !_controller.presentedViewController;
|
||||
|
||||
if (firstTimePush) {
|
||||
// nothing pushed yet
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
@end
|
||||
|
||||
typedef NS_ENUM(NSInteger, RNSScreenStackHeaderSubviewType) {
|
||||
RNSScreenStackHeaderSubviewTypeBackButton,
|
||||
RNSScreenStackHeaderSubviewTypeLeft,
|
||||
RNSScreenStackHeaderSubviewTypeRight,
|
||||
RNSScreenStackHeaderSubviewTypeTitle,
|
||||
|
||||
@@ -5,6 +5,20 @@
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUIManagerUtils.h>
|
||||
#import <React/RCTShadowView.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <React/RCTImageView.h>
|
||||
#import <React/RCTImageSource.h>
|
||||
|
||||
// Some RN private method hacking below. Couldn't figure out better way to access image data
|
||||
// of a given RCTImageView. See more comments in the code section processing SubviewTypeBackButton
|
||||
@interface RCTImageView (Private)
|
||||
- (UIImage*)image;
|
||||
@end
|
||||
|
||||
@interface RCTImageLoader (Private)
|
||||
- (id<RCTImageCache>)imageCache;
|
||||
@end
|
||||
|
||||
|
||||
@interface RNSScreenHeaderItemMeasurements : NSObject
|
||||
@property (nonatomic, readonly) CGSize headerSize;
|
||||
@@ -30,6 +44,7 @@
|
||||
|
||||
@interface RNSScreenStackHeaderSubview : UIView
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *bridge;
|
||||
@property (nonatomic, weak) UIView *reactSuperview;
|
||||
@property (nonatomic) RNSScreenStackHeaderSubviewType type;
|
||||
|
||||
@@ -150,6 +165,15 @@
|
||||
[navbar setLargeTitleTextAttributes:largeAttrs];
|
||||
}
|
||||
}
|
||||
|
||||
UIImage *backButtonImage = [self loadBackButtonImageInViewController:vc withConfig:config];
|
||||
if (backButtonImage) {
|
||||
navbar.backIndicatorImage = backButtonImage;
|
||||
navbar.backIndicatorTransitionMaskImage = backButtonImage;
|
||||
} else if (navbar.backIndicatorImage) {
|
||||
navbar.backIndicatorImage = nil;
|
||||
navbar.backIndicatorTransitionMaskImage = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +188,59 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ (UIImage*)loadBackButtonImageInViewController:(UIViewController *)vc
|
||||
withConfig:(RNSScreenStackHeaderConfig *)config
|
||||
{
|
||||
BOOL hasBackButtonImage = NO;
|
||||
for (RNSScreenStackHeaderSubview *subview in config.reactSubviews) {
|
||||
if (subview.type == RNSScreenStackHeaderSubviewTypeBackButton && subview.subviews.count > 0) {
|
||||
hasBackButtonImage = YES;
|
||||
RCTImageView *imageView = subview.subviews[0];
|
||||
UIImage *image = imageView.image;
|
||||
// IMPORTANT!!!
|
||||
// image can be nil in DEV MODE ONLY
|
||||
//
|
||||
// It is so, because in dev mode images are loaded over HTTP from the packager. In that case
|
||||
// we first check if image is already loaded in cache and if it is, we take it from cache and
|
||||
// display immediately. Otherwise we wait for the transition to finish and retry updating
|
||||
// header config.
|
||||
// Unfortunately due to some problems in UIKit we cannot update the image while the screen
|
||||
// transition is ongoing. This results in the settings being reset after the transition is done
|
||||
// to the state from before the transition.
|
||||
if (image == nil) {
|
||||
// in DEV MODE we try to load from cache (we use private API for that as it is not exposed
|
||||
// publically in headers).
|
||||
RCTImageSource *source = imageView.imageSources[0];
|
||||
image = [subview.bridge.imageLoader.imageCache
|
||||
imageForUrl:source.request.URL.absoluteString
|
||||
size:source.size
|
||||
scale:source.scale
|
||||
resizeMode:imageView.resizeMode];
|
||||
}
|
||||
if (image == nil) {
|
||||
// This will be triggered if the image is not in the cache yet. What we do is we wait until
|
||||
// the end of transition and run header config updates again. We could potentially wait for
|
||||
// image on load to trigger, but that would require even more private method hacking.
|
||||
if (vc.transitionCoordinator) {
|
||||
[vc.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
||||
// nothing, we just want completion
|
||||
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
||||
// in order for new back button image to be loaded we need to trigger another change
|
||||
// in back button props that'd make UIKit redraw the button. Otherwise the changes are
|
||||
// not reflected. Here we change back button visibility which is then immediately restored
|
||||
vc.navigationItem.hidesBackButton = YES;
|
||||
[config updateViewControllerIfNeeded];
|
||||
}];
|
||||
}
|
||||
return [UIImage new];
|
||||
} else {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)willShowViewController:(UIViewController *)vc withConfig:(RNSScreenStackHeaderConfig *)config
|
||||
{
|
||||
[self updateViewController:vc withConfig:config];
|
||||
@@ -201,7 +278,6 @@
|
||||
}
|
||||
|
||||
navitem.title = config.title;
|
||||
navitem.hidesBackButton = config.hideBackButton;
|
||||
if (config.backTitle != nil) {
|
||||
prevItem.backBarButtonItem = [[UIBarButtonItem alloc]
|
||||
initWithTitle:config.backTitle
|
||||
@@ -290,11 +366,19 @@
|
||||
appearance.largeTitleTextAttributes = largeAttrs;
|
||||
}
|
||||
|
||||
UIImage *backButtonImage = [self loadBackButtonImageInViewController:vc withConfig:config];
|
||||
if (backButtonImage) {
|
||||
[appearance setBackIndicatorImage:backButtonImage transitionMaskImage:backButtonImage];
|
||||
} else if (appearance.backIndicatorImage) {
|
||||
[appearance setBackIndicatorImage:nil transitionMaskImage:nil];
|
||||
}
|
||||
|
||||
navitem.standardAppearance = appearance;
|
||||
navitem.compactAppearance = appearance;
|
||||
navitem.scrollEdgeAppearance = appearance;
|
||||
}
|
||||
#endif
|
||||
navitem.hidesBackButton = config.hideBackButton;
|
||||
navitem.leftBarButtonItem = nil;
|
||||
navitem.rightBarButtonItem = nil;
|
||||
navitem.titleView = nil;
|
||||
@@ -378,6 +462,7 @@ RCT_EXPORT_VIEW_PROPERTY(gestureEnabled, BOOL)
|
||||
@implementation RCTConvert (RNSScreenStackHeader)
|
||||
|
||||
RCT_ENUM_CONVERTER(RNSScreenStackHeaderSubviewType, (@{
|
||||
@"back": @(RNSScreenStackHeaderSubviewTypeBackButton),
|
||||
@"left": @(RNSScreenStackHeaderSubviewTypeLeft),
|
||||
@"right": @(RNSScreenStackHeaderSubviewTypeRight),
|
||||
@"title": @(RNSScreenStackHeaderSubviewTypeTitle),
|
||||
@@ -386,9 +471,7 @@ RCT_ENUM_CONVERTER(RNSScreenStackHeaderSubviewType, (@{
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreenStackHeaderSubview {
|
||||
__weak RCTBridge *_bridge;
|
||||
}
|
||||
@implementation RNSScreenStackHeaderSubview
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-screens",
|
||||
"version": "2.0.0-alpha.18",
|
||||
"version": "2.0.0-alpha.23",
|
||||
"description": "First incomplete navigation solution for your react-native app.",
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
|
||||
125
src/screens.d.ts
vendored
125
src/screens.d.ts
vendored
@@ -3,21 +3,140 @@
|
||||
|
||||
declare module 'react-native-screens' {
|
||||
import { ComponentClass } from 'react';
|
||||
import { ViewProps, Animated } from 'react-native';
|
||||
import { ViewProps, Animated, NativeSyntheticEvent, NativeTouchEvent, ImageProps } from 'react-native';
|
||||
|
||||
export function useScreens(shouldUseScreens?: boolean): void;
|
||||
export function enableScreens(shouldEnableScreens?: boolean): void;
|
||||
export function screensEnabled(): boolean;
|
||||
|
||||
export type StackPresentationTypes = 'push' | 'modal' | 'transparentModal';
|
||||
export type StackAnimationTypes = 'default' | 'fade' | 'flip' | 'none';
|
||||
|
||||
export interface ScreenProps extends ViewProps {
|
||||
active?: 0 | 1 | Animated.AnimatedInterpolation;
|
||||
onComponentRef?: (view: any) => void;
|
||||
children?: React.ReactNode;
|
||||
onAppear?: (e: NativeSyntheticEvent<NativeTouchEvent>) => void;
|
||||
/**
|
||||
*@description A callback that gets called when the current screen is dismissed by hardware back (on Android) or dismiss gesture (swipe back or down). The callback takes no arguments.
|
||||
*/
|
||||
onDismissed?: (e: NativeSyntheticEvent<NativeTouchEvent>) => void;
|
||||
/**
|
||||
* @type "push" – the new screen will be pushed onto a stack which on iOS means that the default animation will be slide from the side, the animation on Android may vary depending on the OS version and theme.
|
||||
* @type "modal" – the new screen will be presented modally. In addition this allow for a nested stack to be rendered inside such screens
|
||||
* @type "transparentModal" – the new screen will be presented modally but in addition the second to last screen will remain attached to the stack container such that if the top screen is non opaque the content below can still be seen. If "modal" is used instead the below screen will get unmounted as soon as the transition ends.
|
||||
*/
|
||||
stackPresentation: StackPresentationTypes;
|
||||
/**
|
||||
*@description Allows for the customization of how the given screen should appear/dissapear when pushed or popped at the top of the stack. The followin values are currently supported:
|
||||
* @type "default" – uses a platform default animation
|
||||
* @type "fade" – fades screen in or out
|
||||
* @type "flip" – flips the screen, requires stackPresentation: "modal" (iOS only)
|
||||
* @type "none" – the screen appears/dissapears without an animation
|
||||
*/
|
||||
stackAnimation?: StackAnimationTypes;
|
||||
}
|
||||
export const Screen: ComponentClass<ScreenProps>;
|
||||
|
||||
|
||||
export type ScreenContainerProps = ViewProps;
|
||||
export const ScreenContainer: ComponentClass<ScreenContainerProps>;
|
||||
|
||||
export interface ScreenStackProps extends ViewProps {
|
||||
transitioning?: number;
|
||||
progress?: number;
|
||||
}
|
||||
|
||||
export interface ScreenStackHeaderConfigProps extends ViewProps {
|
||||
/**
|
||||
*@description String that representing screen title that will get rendered in the middle section of the header. On iOS the title is centered on the header while on Android it is aligned to the left and placed next to back button (if one is present).
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
*@description When set to true the header will be hidden while the parent Screen is on the top of the stack. The default value is false.
|
||||
*/
|
||||
hidden?: boolean;
|
||||
/**
|
||||
*@description Controls the color of items rendered on the header. This includes back icon, back text (iOS only) and title text. If you want the title to have different color use titleColor property.
|
||||
*/
|
||||
color?: string;
|
||||
/**
|
||||
*@description Customize font family to be used for the title.
|
||||
*/
|
||||
titleFontFamily?: string;
|
||||
/**
|
||||
*@description Customize the size of the font to be used for the title.
|
||||
*/
|
||||
titleFontSize?: number;
|
||||
/**
|
||||
*@description Allows for setting text color of the title.
|
||||
*/
|
||||
titleColor?: string;
|
||||
/**
|
||||
*@description Controlls the color of the navigation header.
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* @description Boolean that allows for disabling drop shadow under navigation header. The default value is true.
|
||||
*/
|
||||
hideShadow?: boolean;
|
||||
/**
|
||||
* @description If set to true the back button will not be rendered as a part of navigation header.
|
||||
*/
|
||||
hideBackButton?: boolean;
|
||||
/**
|
||||
* @description When set to false the back swipe gesture will be disabled when the parent Screen is on top of the stack. The default value is true.
|
||||
*/
|
||||
gestureEnabled?: boolean;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description When set to true, it makes native navigation bar on iOS semi transparent with blur effect. It is a common way of presenting navigation bar introduced in iOS 11. The default value is false
|
||||
*/
|
||||
translucent?: boolean;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description Allows for controlling the string to be rendered next to back button. By default iOS uses the title of the previous screen.
|
||||
*/
|
||||
backTitle?: string;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description Allows for customizing font family to be used for back button title on iOS.
|
||||
*/
|
||||
backTitleFontFamily?: string;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description Allows for customizing font size to be used for back button title on iOS.
|
||||
*/
|
||||
backTitleFontSize?: number;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description When set to true it makes the title display using the large title effect.
|
||||
*/
|
||||
largeTitle?: boolean;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description Customize font family to be used for the large title.
|
||||
*/
|
||||
largeTitleFontFamily?: string;
|
||||
/**
|
||||
* @host (iOS only)
|
||||
* @description Customize the size of the font to be used for the large title.
|
||||
*/
|
||||
largeTitleFontSize?: number;
|
||||
/**
|
||||
* Pass HeaderLeft, HeaderRight and HeaderTitle
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Screen: ComponentClass<ScreenProps>;
|
||||
export const ScreenContainer: ComponentClass<ScreenContainerProps>;
|
||||
export const NativeScreen: ComponentClass<ScreenProps>;
|
||||
export const NativeScreenContainer: ComponentClass<ScreenContainerProps>;
|
||||
export const ScreenStack: ComponentClass<ScreenStackProps>;
|
||||
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
|
||||
>;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
requireNativeComponent,
|
||||
View,
|
||||
UIManager,
|
||||
Image,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import { version } from 'react-native/Libraries/Core/ReactNativeVersion';
|
||||
@@ -146,6 +147,14 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const ScreenStackHeaderBackButtonImage = props => (
|
||||
<ScreensNativeModules.NativeScreenStackHeaderSubview
|
||||
type="back"
|
||||
style={styles.headerSubview}>
|
||||
<Image resizeMode="center" fadeDuration={0} {...props} />
|
||||
</ScreensNativeModules.NativeScreenStackHeaderSubview>
|
||||
);
|
||||
|
||||
const ScreenStackHeaderRightView = props => (
|
||||
<ScreensNativeModules.NativeScreenStackHeaderSubview
|
||||
{...props}
|
||||
@@ -198,6 +207,7 @@ module.exports = {
|
||||
get ScreenStackHeaderSubview() {
|
||||
return ScreensNativeModules.NativeScreenStackHeaderSubview;
|
||||
},
|
||||
ScreenStackHeaderBackButtonImage,
|
||||
ScreenStackHeaderRightView,
|
||||
ScreenStackHeaderLeftView,
|
||||
ScreenStackHeaderTitleView,
|
||||
|
||||
Reference in New Issue
Block a user