我想实现的效果是这样的:
注意:Modal的背景还是其他的tab,并没有变化,等Modal消失后Screen还是原来的screen。
Solution:
因为中间的自定义图标按钮需要有一部分在Tab中,所以还是把icon作为tab中的一个screen的,于是就借用:tabBarButton 来实现,参考了一些文章,都是把Modal封装为一个组件,然后把Tab.screen的component设置为这个组件,结果怎么调试都有问题,不是这有问题就是那有问题。后来改变了下思路,把Model放置在平行于Tab.Navigator的同级元素上解决了这个问题。代码如下:
// 设置Model是否显示的state,这个state需要放在tab同级组件中,不能放到Model组件中 const [isAddActivityVisible, setIsAddActivityVisible] = useState(false); const clickAddActivity = () => { setIsAddActivityVisible(true); }; const hideAddActivity = () => { setIsAddActivityVisible(false); }; // 借助Tab的listeners方法来做,因为需要preventDefault()来阻止screen跳转 <> </Tab.Navigator> <Tab.Screen name="AddActivity" listeners={ ({ navigation }) => ({ tabPress: (e) => { // Prevent default action e.preventDefault(); clickAddActivity(); }, }) } options={{ tabBarButton: (props) => ( <TouchableOpacity {...props}> <Icon icon="add1" size={58} /> </TouchableOpacity> ) }} > {() => <></>} ...... </Tab.Navigator> // 放在和Tab.Navigator同级 <AddActivityModal isModalVisible={isAddActivityVisible} onHide={hideAddActivity} /> </>
而Modal组件自己定义即可。
interface ModalProps { isModalVisible: boolean; onHide: () => void; } export const AddActivityModal : FC<ModalProps> = ({isModalVisible, onHide}) => { React.useEffect(() => { console.log('AddActivityModal did mount,isModalVisible:'+isModalVisible); }, []); return ( <Modal isVisible={isModalVisible} onHide={onHide} onBackdropPress={onHide}> <Modal.Container> <View style={styles.modal}> <Modal.Header title="LogRocket is fab!" /> <Modal.Body> <Text style={styles.text}>Agree to continue with this guide</Text> </Modal.Body> <Modal.Footer> <Button title="I agree" onPress={onHide} /> </Modal.Footer> </View> </Modal.Container> </Modal> ); }
----------------------------------------------------------------------------------------------
尝试过的有问题的方案:
1. 尝试把Modal的component放在Tab.Screen中。参考:https://medium.com/@my.maithi/react-native-navigation-add-custom-button-in-the-middle-of-tabbar-6c390201a2bb ,这个方案把圆形button和Modal放到一个Screen component中,其中也包括了state。
问题在于:中间圆形button的样式总是调不好。
2. 把中间圆形Button放在Tab.Screen中,用TabBarButton来控制,这种方案如下:
<Tab.Screen name="AddActivity" options={ ({ navigation }) => ({ tabBarButton: (props) => ( <TouchableOpacity onPress={() => console.log("1111")} {...props}> <Icon icon="add1" size={58} /> </TouchableOpacity> ), }) } > {() => <AddActivityModal isModalVisible={isAddActivityVisible} onHide={hideAddActivity} />} </Tab.Screen>
问题有:a) AddActivityModal 是Tab.Screen的child component, 根据react推荐做法,需要把state从child component中提升到父类的compoenent中 b) 在TouchableOpacity中点击onPress方法,总是不能加载child component,好像这个onPress方法阻碍了系统默认的behavior(转到childScreen),没有很好的解决办法 c) 即便b的问题解决了,点击中间的button的时候会转到Modal的Screen,但是当Modal窗口取消后整个Screen就变空白了,因为navigation转到modal的screen了,modal隐藏后就是空白了。
所以这两个方案都有问题,思路不对。
需要注意的技术点:
1)当有Parent Component和其Child Component时候,不要尝试直接在parent组件中直接调用child组件的方法,这不是推荐的做法,推荐的做法是用prop来传递值,由child component来做处理。当然在特殊情况下也可以做到这一点,主要用Ref, CreateRef, UseRef,参考:https://refine.dev/blog/react-useref-hook-and-ref/#using-the-useref-hook-in-an-application , https://blog.logrocket.com/use-forwardref-react/
2)当父component中有个button,点击后想要change 子component中的state变化,这种情况下,根据推荐做法,需要把state lift提升,参考:https://legacy.reactjs.org/docs/lifting-state-up.html
标签:tap,Modal,自定义,bottom,Screen,component,state,Tab,组件 From: https://www.cnblogs.com/saaspeter/p/18110340