Modal

Modal 组件是一种简单的覆盖在其他视图之上显示内容的方式。

visible

visible属性决定 modal 是否显示。

supportedOrientations

supportedOrientations用于指定在设备切换横竖屏方向时,modal 会在哪些屏幕朝向下跟随旋转。在 鸿蒙 上,除了本属性外,还会受到应用的 Info.plist 文件中UISupportedInterfaceOrientations的限制。如果还设置了presentationStyle属性为pageSheet或formSheet,则在 鸿蒙上本属性将被忽略。

onRequestClose

onRequestClose回调会在用户按下 鸿蒙 设备上的后退按键或是 Apple TV 上的菜单键时触发。请务必注意本属性在 Android 平台上为必需,且会在 modal 处于开启状态时阻止BackHandler事件。


React Native的Modal组件用于创建覆盖在主界面之上的模态视图(如弹窗、菜单等),支持跨平台(iOS/Android)使用,具备动画、透明背景等特性。以下是详细说明:

核心属性

  • visible:布尔值,控制模态是否显示。
  • animationType:动画类型,可选 none(无动画)、slide(从底部滑入)、fade(淡入)。
  • transparent:布尔值,设置背景透明度(默认白色)。
  • onRequestClose:Android平台必填,用户点击返回键时触发。
  • onShow:模态显示时调用的回调函数。

使用示例

import React, { Component } from 'react';
import { View, Modal, Text, Button, StyleSheet } from 'react-native';

class MyModal extends Component {
  state = { visible: false };

  toggleModal = () => {
    this.setState({ visible: !this.state.visible });
  };

  render() {
    return (
      <View style={styles.container}>
        <Button title="开启" onPress={this.toggleModal} />
        <Modal
          visible={this.state.visible}
          animationType="slide"
          transparent={true}
          onRequestClose={this.toggleModal}
        >
          <View style={styles.modalContainer}>
            <Text style={styles.modalText}>我是Modal组件</Text>
            <Button title="关闭" onPress={this.toggleModal} />
          </View>
        </Modal>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'rgba(0,0,0,0.5)',
  },
  modalText: {
    fontSize: 20,
    fontWeight: 'bold',
  },
});

注意事项

  • Android需实现onRequestClose,否则可能崩溃。
  • iOS方向限制由info.plist中的UISupportedInterfaceOrientations决定,supportedOrientations仅影响模态视图方向。
  • 透明背景需配合半透明层(如rgba(0,0,0,0.45))实现视觉优化。

实际案例演示:

import React, { useState } from "react";
import {
  Alert,
  Modal,
  StyleSheet,
  Text,
  TouchableHighlight,
  View
} from "react-native";

const App = () => {
  const [modalVisible, setModalVisible] = useState(false);
  return (
    <View style={styles.centeredView}>
      <Modal
        animationType="slide"
        transparent={true}
        visible={modalVisible}
        onRequestClose={() => {
          Alert.alert("Modal has been closed.");
          setModalVisible(!modalVisible);
        }}
      >
        <View style={styles.centeredView}>
          <View style={styles.modalView}>
            <Text style={styles.modalText}>Hello OpenHarmony!</Text>

            <TouchableHighlight
              style={styles.closeButton}
              underlayColor="#1E88E5"
              onPress={() => {
                setModalVisible(!modalVisible);
              }}
            >
              <Text style={styles.textStyle}>Hide Modal</Text>
            </TouchableHighlight>
          </View>
        </View>
      </Modal>

      <TouchableHighlight
        style={styles.openButton}
        underlayColor="#BA68C8"
        onPress={() => {
          setModalVisible(true);
        }}
      >
        <Text style={styles.textStyle}>Show Modal</Text>
      </TouchableHighlight>
    </View>
  );
};

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5F5F5"
  },
  modalView: {
    margin: 20,
    backgroundColor: "white",
    borderRadius: 16,
    padding: 35,
    alignItems: "center",
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 4
    },
    shadowOpacity: 0.3,
    shadowRadius: 6,
    elevation: 8
  },
  openButton: {
    backgroundColor: "#9C27B0",
    borderRadius: 16,
    padding: 12,
    elevation: 3
  },
  closeButton: {
    backgroundColor: "#2196F3",
    borderRadius: 16,
    padding: 12,
    elevation: 3,
    marginTop: 15
  },
  textStyle: {
    color: "white",
    fontWeight: "bold",
    textAlign: "center",
    fontSize: 16
  },
  modalText: {
    marginBottom: 20,
    textAlign: "center",
    fontSize: 18,
    color: "#333"
  }
});

export default App;

这段React Native代码展示了一个模态框(Modal)组件的完整实现,涉及React Hooks状态管理、组件通信和平台特定行为处理等多个重要概念。

Modal组件的显示控制通过useSta
te Hook实现,modalVisible状态变量作为布尔标志控制模态框的可见性。当用户点击"Show Modal"按钮时,setModalVisible(true)触发状态更新,进而重新渲染组件并显示模态框。这种单向数据流模式是React的核心设计哲学。

动画系统的工作原理基于平台原生能力。当animationType设置为"slide"时,在鸿蒙上会使用UIView动画实现滑动效果,在Android上则使用FragmentTransaction的转场动画。transparent属性设置为true时,模态框背景会变成半透明,这通过设置UIView的alpha属性(iOS)或Window的透明度(Android)实现。

在这里插入图片描述

onRequestClose是Android平台的特定回调,当用户按下设备的返回按钮时触发,这体现了React Native对平台原生行为的适配。TouchableHighlight组件提供触摸反馈,其底层使用原生触摸事件系统,在鸿蒙上通过UITouch事件传递,在Android上通过MotionEvent处理。

样式系统通过StyleSheet.create创建,这些样式会被编译为平台特定的样式对象。shadowColor等阴影属性在鸿蒙上直接映射为CALayer的阴影属性,而在Android上通过elevation属性实现类似的视觉效果,这展示了React Native的跨平台适配能力。

事件处理机制中,onPress回调通过React Native的事件系统与原生触摸事件进行桥接。当用户触摸时,事件从原生层传递到JavaScript层,触发相应的状态更新和界面重渲染。

这段React Native代码展示了一个模态框组件的完整实现,其核心原理涉及React Native的组件系统、状态管理和平台特性适配等多个层面。

Modal组件的工作原理基于原生平台的模态视图实现。在iOS上,它使用UIViewController的presentViewController方法,在Android上则通过DialogFragment实现。当visible属性设置为true时,React Native会调用原生代码创建并显示一个模态视图,这个视图独立于主应用窗口,具有自己的视图层级和事件处理机制。

animationType="slide"的动画效果在不同平台上有不同的实现方式。iOS使用UIView的transitionWithView方法实现滑动动画,Android则使用FragmentTransaction的setCustomAnimations方法。transparent属性控制模态框背景的透明度,当设置为true时,底层内容会保持可见,这通过设置模态视图的背景色为透明实现。

状态管理使用React的useState Hook,modalVisible状态变量控制模态框的显示与隐藏。当状态改变时,React Native会触发重新渲染,并通过桥接层将新的属性传递给原生组件。

TouchableHighlight组件提供触摸反馈效果。当用户按下时,它会改变子视图的不透明度,在iOS上通过设置UIView的alpha属性,在Android上通过View的setAlpha方法实现。这种反馈机制增强了用户体验,让用户能够直观地感知到交互响应。

onRequestClose回调是Android平台的特定需求,当用户按下设备的返回按钮时触发。这体现了React Native对平台特性的尊重和适配,确保应用在不同平台上都能提供符合用户期望的交互体验。


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述
最后运行效果图如下显示:

请添加图片描述

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐