Skip to content

Commit

Permalink
feat:添加modal中间显示[#627]
Browse files Browse the repository at this point in the history
  • Loading branch information
SunLxy committed May 25, 2023
1 parent c604b14 commit f1696df
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 14 deletions.
3 changes: 2 additions & 1 deletion example/examples/src/routes/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class ModalView extends Component<ModalViewProps> {
{label: 'left', value: 'left'},
{label: 'top', value: 'top'},
{label: 'bottom', value: 'bottom'},
{label: 'middle', value: 'middle'},
];
render() {
const {route} = this.props;
Expand All @@ -34,7 +35,7 @@ export default class ModalView extends Component<ModalViewProps> {
<Body style={{paddingLeft: 16, paddingRight: 16}}>
<Card title="基础实例">
<Modal
placement={this.state.direction as 'left' | 'right' | 'top' | 'bottom'}
placement={this.state.direction as 'left' | 'right' | 'top' | 'bottom' | 'middle'}
// maskClosable={false}
visible={this.state.modalVisible}
onClosed={() => this.setState({modalVisible: false})}
Expand Down
16 changes: 15 additions & 1 deletion packages/core/src/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function ButtonGroupView() {
const [topModal,setTopModal]= useState(false)
const [leftModal,setLeftModal]= useState(false)
const [rightModal,setRightModal]= useState(false)
const [middleModal,setMiddleModal]= useState(false)
const data = Array.from(new Array(24)).map((_val, i) => {
return { icon: <Icon name="heart-on" color="red" />, text: `${i}`}
});
Expand Down Expand Up @@ -73,6 +74,16 @@ function ButtonGroupView() {
</View>
</SafeAreaView>
</Modal>
<Modal visible={middleModal} placement='middle'>
<SafeAreaView style={{width:600}}>
<View>
<Grid data={data} columns='6' hasLine={false}/>
<Button onPress={() => setMiddleModal(false)}>
隐藏中间弹出的模态框
</Button>
</View>
</SafeAreaView>
</Modal>
<Button onPress={() => setLowerModal(true)}>
下面显示
</Button>
Expand All @@ -85,6 +96,9 @@ function ButtonGroupView() {
<Button onPress={() => setRightModal(true)}>
右边显示
</Button>
<Button onPress={() => setMiddleModal(true)}>
中间显示
</Button>
</Fragment>
);
}
Expand All @@ -97,7 +111,7 @@ export default ButtonGroupView

| 参数 | 说明 | 类型 | 默认值 |
|------|------|-----|------|
| placement | 模态框的方向 | `'top' \| 'right' \| 'bottom' \| 'left'` | bottom |
| placement | 模态框的方向 | `'top' \| 'right' \| 'bottom' \| 'left' \| 'middle'` | bottom |
| onClosed | 关闭函数 | `() => void` | - |
| containerStyle | 样式 | `ViewStyle` | - |

Expand Down
61 changes: 49 additions & 12 deletions packages/core/src/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useMemo, useRef, useEffect } from 'react';
import React, { useState, useMemo, useRef, useEffect, useReducer } from 'react';
import { Animated, StyleSheet, LayoutChangeEvent, Dimensions, ViewStyle } from 'react-native';
import MaskLayer, { MaskLayerProps } from '../MaskLayer';
import { Theme } from '../theme';
Expand All @@ -8,20 +8,35 @@ const MainWidth = Dimensions.get('window').width;
const MainHeight = Dimensions.get('window').height;

export interface ModalProps extends MaskLayerProps {
placement?: 'top' | 'right' | 'bottom' | 'left';
placement?: 'top' | 'right' | 'bottom' | 'left' | 'middle';
onClosed?: () => void;
containerStyle?: ViewStyle;
}

interface StoreType {
layoutHeight: number;
layoutWidth: number;
}

export const reducer: React.Reducer<StoreType, Partial<StoreType>> = (state, action) => {
return {
...state,
...action,
};
};

const Modal = (props: ModalProps = {}) => {
const { onClosed, visible, children, placement = 'bottom', containerStyle, ...otherProps } = props;
const theme = useTheme<Theme>();
const AnimatedOpacity = useRef(new Animated.Value(0)).current;
const [layoutHeight, setLayoutHeight] = useState(0);
const [layoutWidth, setLayoutWidth] = useState(0);
const [{ layoutHeight, layoutWidth }, dispatch] = useReducer(reducer, { layoutHeight: 0, layoutWidth: 0 });
const [translateValue] = useState(new Animated.Value(0));
const isVertical = /^(top|bottom)$/.test(placement);
const isHorizontal = /^(left|right)$/.test(placement);

const { isVertical, isHorizontal } = useMemo(() => {
const isVertical = /^(top|bottom)$/.test(placement);
const isHorizontal = /^(left|right)$/.test(placement);
return { isVertical, isHorizontal };
}, [placement]);

useEffect(() => {
function getTransformSize() {
Expand All @@ -37,6 +52,9 @@ const Modal = (props: ModalProps = {}) => {
if (placement === 'right') {
return layoutWidth;
}
if (placement === 'middle') {
return layoutWidth;
}
return 0;
}
const result = getTransformSize();
Expand Down Expand Up @@ -82,20 +100,30 @@ const Modal = (props: ModalProps = {}) => {
if (isHorizontal) {
translateStyle.translateX = translateValue;
}
if (placement === 'middle') {
translateStyle.translateY = translateValue;
}

const child = useMemo(
() => (
<Animated.View
style={[styles.content, placement && styles[placement], { opacity: AnimatedOpacity }, containerStyle]}
style={[
styles.content,
placement && styles[placement],
placement === 'middle' && styles.middle_warp,
{ opacity: AnimatedOpacity },
containerStyle,
]}
>
<Animated.View
onLayout={(event: LayoutChangeEvent) => {
const { height, width } = event.nativeEvent.layout;
if (!layoutHeight && isVertical) {
setLayoutHeight(height);
}
if (!layoutWidth && isHorizontal) {
setLayoutWidth(width);
if (placement === 'middle') {
dispatch({ layoutHeight: height, layoutWidth: width });
} else if (!layoutHeight && isVertical) {
dispatch({ layoutHeight: height });
} else if (!layoutWidth && isHorizontal) {
dispatch({ layoutWidth: width });
}
}}
style={[
Expand Down Expand Up @@ -165,4 +193,13 @@ const styles = StyleSheet.create({
height: MainHeight,
right: 0,
},
middle: {},
middle_warp: {
bottom: 0,
top: 0,
right: 0,
left: 0,
justifyContent: 'center',
alignItems: 'center',
},
});

0 comments on commit f1696df

Please sign in to comment.