欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React?Native?Modal?的封裝與使用實例詳解

 更新時間:2022年09月23日 14:56:19   作者:wi100sh  
這篇文章主要介紹了React?Native?Modal?的封裝與使用,本文通過實例代碼圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

背景

在使用 React Native(以下簡稱 RN ,使用版本為 0.59.5) 開發(fā) App 的過程中,有許許多多使用到彈窗控件的場景,雖然 RN 自帶了一個 Modal 控件,但是在使用過程中它有一些不太好的體驗和問題。

  • Android 端的 Modal 控件無法全屏,也就是內(nèi)容無法從狀態(tài)欄處開始布局。
  • ios 端的 Modal 控件的層級太高,是基于 window 的,如果在 Modal 中打開一個新的 ViewController 界面的時候,將會被 Modal 控件給覆蓋住,同時 ios 的 Modal 控件只能彈出一個。

針對上面所發(fā)現(xiàn)的問題,我們需要對 RN 的 Modal 控件整體做一個修改和封裝,以便于在使用中可以應對各種不同樣的業(yè)務場景。

Android FullScreenModal 的封裝使用

針對第一個問題,查看了 RN Modal 組件在 Android 端的實現(xiàn),發(fā)現(xiàn)它是對 Android Dialog 組件的一個封裝調用,那么假如我能實現(xiàn)一個全屏展示的 Dialog,那么是不是在 RN 上也就可以實現(xiàn)全屏彈窗了。

Android 原生實現(xiàn)全屏 Dialog

FullScreenDialog 主要實現(xiàn)代碼如下

public class FullScreenDialog extends Dialog {

    private boolean isDarkMode;
    private View rootView;

    public void setDarkMode(boolean isDarkMode) {
        this.isDarkMode = isDarkMode;
    }

    public FullScreenDialog(@NonNull Context context, @StyleRes int themeResId) {
        super(context, themeResId);
    }

    @Override
    public void setContentView(@NonNull View view) {
        super.setContentView(view);
        this.rootView = view;
    }

    @Override
    public void show() {
        super.show();
        StatusBarUtil.setTransparent(getWindow());
        if (isDarkMode) {
            StatusBarUtil.setDarkMode(getWindow());
        } else {
            StatusBarUtil.setLightMode(getWindow());
        }
        AndroidBug5497Workaround.assistView(rootView, getWindow());
    }
}

在這里主要起作用的是 StatusBarUtil.setTransparent(getWindow()); 方法,它的主要作用是將狀態(tài)欄背景透明,并且讓布局內(nèi)容可以從 Android 狀態(tài)欄開始。

/**
  * 使狀態(tài)欄透明,并且是從狀態(tài)欄處開始布局
  */
 @TargetApi(Build.VERSION_CODES.KITKAT)
 private static void transparentStatusBar(Window window) {
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
         View decorView = window.getDecorView();
         int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
         decorView.setSystemUiVisibility(option);
         window.setStatusBarColor(Color.TRANSPARENT);
     } else {
         window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
     }
 }

這里需要注意的是,該方法只有在 Android 4.4 以上才會有效果,不過如今已經(jīng)是 9012 年了,主流 Android 用戶使用的版本應該沒有低于 Android 4.4 了吧。

封裝給 RN 進行相關的調用

Android 原生部分實現(xiàn)

有了 FullScreenDialog ,下一步就是封裝組件給 RN 進行調用了,這里主要的步驟就是參考 RN Modal 的 Android 端實現(xiàn),然后替換其中的 Dialog 為 FullScreenDialog,最后封裝給 RN 進行調用。

public class FullScreenModalManager extends ViewGroupManager<FullScreenModalView> {
    @Override
    public String getName() {
        return "RCTFullScreenModalHostView";
    }
    public enum Events {
        ON_SHOW("onFullScreenShow"),
        ON_REQUEST_CLOSE("onFullScreenRequstClose");
        private final String mName;
        Events(final String name) {
            mName = name;
        }
        @Override
        public String toString() {
            return mName;
        }
    }
    @Override
    @Nullable
    public Map getExportedCustomDirectEventTypeConstants() {
        MapBuilder.Builder builder = MapBuilder.builder();
        for (Events event : Events.values()) {
            builder.put(event.toString(), MapBuilder.of("registrationName", event.toString()));
        }
        return builder.build();
    }
    @Override
    protected FullScreenModalView createViewInstance(ThemedReactContext reactContext) {
        final FullScreenModalView view = new FullScreenModalView(reactContext);
        final RCTEventEmitter mEventEmitter = reactContext.getJSModule(RCTEventEmitter.class);
        view.setOnRequestCloseListener(new FullScreenModalView.OnRequestCloseListener() {
            @Override
            public void onRequestClose(DialogInterface dialog) {
                mEventEmitter.receiveEvent(view.getId(), Events.ON_REQUEST_CLOSE.toString(), null);
            }
        });
        view.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                mEventEmitter.receiveEvent(view.getId(), Events.ON_SHOW.toString(), null);
            }
        });
        return view;
    }
    @Override
    public LayoutShadowNode createShadowNodeInstance() {
        return new FullScreenModalHostShadowNode();
    }
    @Override
    public Class<? extends LayoutShadowNode> getShadowNodeClass() {
        return FullScreenModalHostShadowNode.class;
    }
    @Override
    public void onDropViewInstance(FullScreenModalView view) {
        super.onDropViewInstance(view);
        view.onDropInstance();
    }
    @ReactProp(name = "autoKeyboard")
    public void setAutoKeyboard(FullScreenModalView view, boolean autoKeyboard) {
        view.setAutoKeyboard(autoKeyboard);
    }
    @ReactProp(name = "isDarkMode")
    public void setDarkMode(FullScreenModalView view, boolean isDarkMode) {
        view.setDarkMode(isDarkMode);
    }
    @ReactProp(name = "animationType")
    public void setAnimationType(FullScreenModalView view, String animationType) {
        view.setAnimationType(animationType);
    }
    @ReactProp(name = "transparent")
    public void setTransparent(FullScreenModalView view, boolean transparent) {
        view.setTransparent(transparent);
    }
    @ReactProp(name = "hardwareAccelerated")
    public void setHardwareAccelerated(FullScreenModalView view, boolean hardwareAccelerated) {
        view.setHardwareAccelerated(hardwareAccelerated);
    }
    @Override
    protected void onAfterUpdateTransaction(FullScreenModalView view) {
        super.onAfterUpdateTransaction(view);
        view.showOrUpdate();
    }
}

在這里有幾點需要注意的

  • 由于 RN Modal 已經(jīng)存在了 onShow 和 onRequestClose 回調,這里不能再使用這兩個命名,所以這里改成了 onFullScreenShow 和 onFullScreenRequstClose,但是在 js 端還是重新命名成 onShow 和 onRequestClose ,所以在使用過程中還是沒有任何變化
  • 增加了 isDarkMode 屬性,對應上面的狀態(tài)欄字體的顏色
  • 增加了 autoKeyboard 屬性,根據(jù)該屬性判斷是否需要自動彈起軟件盤

其他的一些屬性和用法也就跟 RN Modal 的一樣了。

JS 部分實現(xiàn)

在 JS 部分,我們只需要 Android 的實現(xiàn)就好了,ios 還是沿用原來的 Modal 控件。這里參照 RN Modal 的 JS 端實現(xiàn)如下

import React, {Component} from "react";
import {requireNativeComponent, View}  from "react-native";
const FullScreenModal = requireNativeComponent('RCTFullScreenModalHostView', FullScreenModalView)
export default class FullScreenModalView extends Component {
    _shouldSetResponder = () => {
        return true;
    }
    render() {
        if (this.props.visible === false) {
            return null;
        }
        const containerStyles = {
            backgroundColor: this.props.transparent ? 'transparent' : 'white',
        };
        return (
            <FullScreenModal
                style={{position: 'absolute'}}  {...this.props}
                onStartShouldSetResponder={this._shouldSetResponder}
                onFullScreenShow={() => this.props.onShow && this.props.onShow()}
                onFullScreenRequstClose={() => this.props.onRequestClose && this.props.onRequestClose()}>
                <View style={[{position: 'absolute', left: 0, top: 0}, containerStyles]}>
                    {this.props.children}
                </View>
            </FullScreenModal>
        )
    }
}

使用 RootSiblings 封裝 Modal

針對第二個問題,一種方法是通過 ios 原生去封裝實現(xiàn)一個 Modal 控件,但是在 RN 的開發(fā)過程中,發(fā)現(xiàn)了一個第三方庫 react-native-root-siblings , 它重寫了系統(tǒng)的 AppRegistry.registerComponent 方法,當我們通過這個方法注冊根組件的時候,替換根組件為我們自己的實現(xiàn)的包裝類。包裝類中監(jiān)聽了目標通知 siblings.update,接收到通知就將通知傳入的組件視圖添加到包裝類頂層,然后進行刷新顯示。通過 RootSiblings 也可以實現(xiàn)一個 Modal 組件,而且它的層級是在當前界面的最上層的。

實現(xiàn)界面 Render 相關

由于 RootSiblings 的實現(xiàn)是通過將組件添加到它注冊到根節(jié)點中的,并不直接通過 Component 的 Render 進行布局,而 RN Modal 的顯示隱藏是通過 visible 屬性進行控制,所以在 componentWillReceiveProps(nextProps) 中根據(jù) visible 進行相關的控制,部分實現(xiàn)代碼如下

render() {
  if (this.props.visible) {
    this.RootSiblings && this.RootSiblings.update(this.renderRootSiblings());
  }
  return null;
}
componentWillReceiveProps(nextProps) {
    const { onShow, animationType, onDismiss } = this.props;
    const { visible } = nextProps;
    if (!this.RootSiblings && visible === true) { // 表示從沒有到要顯示了
      this.RootSiblings = new RootSiblings(this.renderRootSiblings(), () => {
        if (animationType === 'fade') {
          this._animationFadeIn(onShow);
        } else if (animationType === 'slide') {
          this._animationSlideIn(onShow);
        } else {
          this._animationNoneIn(onShow);
        }
      });
    } else if (this.RootSiblings && visible === false) { // 表示顯示之后要隱藏了
      if (animationType === 'fade') {
        this._animationFadeOut(onDismiss);
      } else if (animationType === 'slide') {
        this._animationSlideOut(onDismiss);
      } else {
        this._animationNoneOut(onDismiss);
      }
   }
}

實現(xiàn) Modal 展示動畫相關

RN Modal 實現(xiàn)了三種動畫模式,所以這里在通過 RootSiblings 實現(xiàn) Modal 組件的時候也實現(xiàn)了這三種動畫模式,這里借助的是 RN 提供的 Animated 和 Easing 進行相關的實現(xiàn)

  • ‘none’ 這種不必多說,直接進行展示,沒有動畫效果
  • ‘fade’ 淡入淺出動畫,也就是透明度的一個變化,這里使用了 Easing.in 插值器使得效果更加平滑
  • ‘slide’ 幻燈片的滑入畫出動畫,這是是組件 Y 方向位置的一個變化,這里使用了 Easing.in 插值器使得效果更加平滑

完整的一個 使用 RootSiblings 封裝 Modal 實現(xiàn)代碼如下

import React, { Component } from 'react';
import {
  Animated, Easing, Dimensions, StyleSheet,
} from 'react-native';
import RootSiblings from 'react-native-root-siblings';
const { height } = Dimensions.get('window');
const animationShortTime = 250; // 動畫時長為250ms
export default class ModalView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      animationSlide: new Animated.Value(0),
      animationFade: new Animated.Value(0),
    };
  }
  render() {
    if (this.props.visible) {
      this.RootSiblings && this.RootSiblings.update(this.renderRootSiblings());
    }
    return null;
  }
  componentWillReceiveProps(nextProps) {
    const { onShow, animationType, onDismiss } = this.props;
    const { visible } = nextProps;
    if (!this.RootSiblings && visible === true) { // 表示從沒有到要顯示了
      this.RootSiblings = new RootSiblings(this.renderRootSiblings(), () => {
        if (animationType === 'fade') {
          this._animationFadeIn(onShow);
        } else if (animationType === 'slide') {
          this._animationSlideIn(onShow);
        } else {
          this._animationNoneIn(onShow);
        }
      });
    } else if (this.RootSiblings && visible === false) { // 表示顯示之后要隱藏了
      if (animationType === 'fade') {
        this._animationFadeOut(onDismiss);
      } else if (animationType === 'slide') {
        this._animationSlideOut(onDismiss);
      } else {
        this._animationNoneOut(onDismiss);
      }
    }
  }
  renderRootSiblings = () => {
    return (
      <Animated.View style={[styles.root,
        { opacity: this.state.animationFade },
        {
          transform: [{
            translateY: this.state.animationSlide.interpolate({
              inputRange: [0, 1],
              outputRange: [height, 0],
            }),
          }],
        }]}>
        {this.props.children}
      </Animated.View>
    );
  }
  _animationNoneIn = (callback) => {
    this.state.animationSlide.setValue(1);
    this.state.animationFade.setValue(1);
    callback && callback();
  }
  _animationNoneOut = (callback) => {
    this._animationCallback(callback);
  }
  _animationSlideIn = (callback) => {
    this.state.animationSlide.setValue(0);
    this.state.animationFade.setValue(1);
    Animated.timing(this.state.animationSlide, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 1,
    }).start(() => callback && callback());
  }
  _animationSlideOut = (callback) => {
    this.state.animationSlide.setValue(1);
    this.state.animationFade.setValue(1);
    Animated.timing(this.state.animationSlide, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 0,
    }).start(() => this._animationCallback(callback));
  }
  _animationFadeIn = (callback) => {
    this.state.animationSlide.setValue(1);
    this.state.animationFade.setValue(0);
    Animated.timing(this.state.animationFade, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 1,
    }).start(() => callback && callback());
  }
  _animationFadeOut = (callback) => {
    this.state.animationSlide.setValue(1);
    this.state.animationFade.setValue(1);
    Animated.timing(this.state.animationFade, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 0,
    }).start(() => this._animationCallback(callback));
  }
  _animationCallback = (callback) => {
    this.RootSiblings && this.RootSiblings.destroy(() => {
      callback && callback();
      this.RootSiblings = undefined;
    });
  }
}
const styles = StyleSheet.create({
  root: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
  },
});

使用 View 封裝 Modal

上面兩種 Modal 的封裝已經(jīng)能夠滿足絕大部分業(yè)務場景的需求,但是如果在 Modal 中需要打開新的界面(不創(chuàng)建新的 ViewController 和 Acticity ),并且 Modal 不進行隱藏的話,比如使用 react-navigation 跳轉頁面,那么上面實現(xiàn)的 Modal 層級會太高了。所以這里通過 View 去實現(xiàn)類似的一個 Modal 控件。它的實現(xiàn)代碼類似于上面的 RootSiblings 的實現(xiàn)。在 Render 中進行展示就好了,動畫也可以使用上面的實現(xiàn)

 render() {
    return this._renderView()
 }
 
_renderView = () => {
    if (this.state.visible) {
      return (
        <Animated.View style={[styles.root,
          {opacity: this.state.animationFade},
          {
            transform: [{
              translateY: this.state.animationSlide.interpolate({
                inputRange: [0, 1],
                outputRange: [height, 0]
              }),
            }]
          }]}>
          {this.props.children}
        </Animated.View>
      );
    } else {
      return null
    }
}

整體 Modal 控件的封裝

相對于 RN Modal ,上面新增了三種 Modal 的實現(xiàn),為了整合整體的使用,所以需要對它們進行一個整體的封裝使用,通過制定 modalType 的方式,來指定我們需要它內(nèi)部的實現(xiàn),先上代碼

/**
 * @Author: linhe
 * @Date: 2019-05-12 10:11
 *
 * 因為ios端同時只能存在一個Modal,并且Modal多次顯示隱藏會有很奇怪的bug
 *
 * 為了兼容ios的使用,這里需要封裝一個ModalView
 *
 * Android 依舊使用 React Native Modal 來進行實現(xiàn)
 * ios 的話采用 RootSiblings 配合進行使用
 *
 * 這個是因為有的modal里面還需要跳轉到其他界面
 * 這個時候主要要將該View放到最外邊的層級才可以
 *
 * modalType:1 //表示使用Modal進行實現(xiàn)
 *           2 //表示使用RootSiblings進行實現(xiàn)
 *           3 //表示使用View進行實現(xiàn)
 * 注意:默認情況下 Android 使用的是1,ios使用的是2
 *
 * 同時采用與 React Native Modal 相同的API
 */
'use strict';
import React, {Component} from "react";
import {Animated, BackHandler, Platform, Easing, StyleSheet, Dimensions, Modal} from "react-native";
import PropTypes from 'prop-types'
import RootSiblings from 'react-native-root-siblings';
import FullScreenModal from './FullScreenModal/FullScreenModal'
const {height} = Dimensions.get('window')
const animationShortTime = 250 //動畫時長為250ms
const DEVICE_BACK_EVENT = 'hardwareBackPress';
export default class ModalView extends Component {
  static propTypes = {
    isDarkMode: PropTypes.bool, // false 表示白底黑字,true 表示黑底白字
    autoKeyboard: PropTypes.bool, // 未知原因的坑,modal中的edittext自動彈起鍵盤要設置這個參數(shù)為true
    useReactModal: PropTypes.bool, // 是否使用 RN Modal 進行實現(xiàn)
    modalType: PropTypes.number // modalType 類型,默認 android 為 1,ios 為 2
  };
  static defaultProps = {
    isDarkMode: false,
    autoKeyboard: false,
    useReactModal: false,
    modalType: (Platform.OS === 'android' ? 1 : 2) // 默認 android 為1,ios 為2
  };
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      animationSlide: new Animated.Value(0),
      animationFade: new Animated.Value(0)
    };
  }
  render() {
    const {modalType} = this.props
    if (modalType === 1) { //modal實現(xiàn)
      return this._renderModal()
    } else if (modalType === 2) { //RootSiblings實現(xiàn)
      this.RootSiblings && this.RootSiblings.update(this._renderRootSiblings())
      return null
    } else { //View的實現(xiàn)
      return this._renderView()
    }
  }
  _renderModal = () => {
    const ModalView = this.props.useReactModal ? Modal : FullScreenModal
    return (
      <ModalView
        transparent={true}
        {...this.props}
        visible={this.state.visible}
        onRequestClose={() => {
          if (this.props.onRequestClose) {
            this.props.onRequestClose()
          } else {
            this.disMiss()
          }
        }}>
        {this.props.children}
      </ModalView>
    )
  }
  _renderRootSiblings = () => {
    return (
      <Animated.View style={[styles.root,
        {opacity: this.state.animationFade},
        {
          transform: [{
            translateY: this.state.animationSlide.interpolate({
              inputRange: [0, 1],
              outputRange: [height, 0]
            }),
          }]
        }]}>
        {this.props.children}
      </Animated.View>
    );
  }
  _renderView = () => {
    if (this.state.visible) {
      return (
        <Animated.View style={[styles.root,
          {opacity: this.state.animationFade},
          {
            transform: [{
              translateY: this.state.animationSlide.interpolate({
                inputRange: [0, 1],
                outputRange: [height, 0]
              }),
            }]
          }]}>
          {this.props.children}
        </Animated.View>
      );
    } else {
      return null
    }
  }
  show = (callback) => {
    if (this.isShow()) {
      return
    }
    const {modalType, animationType} = this.props
    if (modalType === 1) { //modal
      this.setState({visible: true}, () => callback && callback())
    } else if (modalType === 2) { //RootSiblings
      this.RootSiblings = new RootSiblings(this._renderRootSiblings(), () => {
        if (animationType === 'fade') {
          this._animationFadeIn(callback)
        } else if (animationType === 'slide') {
          this._animationSlideIn(callback)
        } else {
          this._animationNoneIn(callback)
        }
      });
      // 這里需要監(jiān)聽 back 鍵
      this._addHandleBack()
    } else { //view
      if (animationType === 'fade') {
        this.setState({visible: true}, () => this._animationFadeIn(callback))
      } else if (animationType === 'slide') {
        this.setState({visible: true}, () => this._animationSlideIn(callback))
      } else {
        this.setState({visible: true}, () => this._animationNoneIn(callback))
      }
      // 這里需要監(jiān)聽 back 鍵
      this._addHandleBack()
    }
  }
  disMiss = (callback) => {
    if (!this.isShow()) {
      return
    }
    const {modalType, animationType} = this.props
    if (modalType === 1) { //modal
      this.setState({visible: false}, () => callback && callback())
    } else { //RootSiblings和View
      if (animationType === 'fade') {
        this._animationFadeOut(callback)
      } else if (animationType === 'slide') {
        this._animationSlideOut(callback)
      } else {
        this._animationNoneOut(callback)
      }
      // 移除 back 鍵的監(jiān)聽
      this._removeHandleBack()
    }
  }
  isShow = () => {
    const {modalType} = this.props
    if (modalType === 1 || modalType === 3) { //modal和view
      return this.state.visible
    } else { //RootSiblings
      return !!this.RootSiblings
    }
  }
  _addHandleBack = () => {
    if (Platform.OS === 'ios') {
      return
    }
    // 監(jiān)聽back鍵
    this.handleBack = BackHandler.addEventListener(DEVICE_BACK_EVENT, () => {
      const {onRequestClose} = this.props
      if (onRequestClose) {
        onRequestClose()
      } else {
        this.disMiss()
      }
      return true
    });
  }
  _removeHandleBack = () => {
    if (Platform.OS === 'ios') {
      return
    }
    this.handleBack && this.handleBack.remove()
  }
  _animationNoneIn = (callback) => {
    this.state.animationSlide.setValue(1)
    this.state.animationFade.setValue(1)
    callback && callback()
  }
  _animationNoneOut = (callback) => {
    this._animationCallback(callback);
  }
  _animationSlideIn = (callback) => {
    this.state.animationSlide.setValue(0)
    this.state.animationFade.setValue(1)
    Animated.timing(this.state.animationSlide, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 1,
    }).start(() => callback && callback());
  }
  _animationSlideOut = (callback) => {
    this.state.animationSlide.setValue(1)
    this.state.animationFade.setValue(1)
    Animated.timing(this.state.animationSlide, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 0,
    }).start(() => this._animationCallback(callback));
  }
  _animationFadeIn = (callback) => {
    this.state.animationSlide.setValue(1)
    this.state.animationFade.setValue(0)
    Animated.timing(this.state.animationFade, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 1,
    }).start(() => callback && callback());
  }
  _animationFadeOut = (callback) => {
    this.state.animationSlide.setValue(1)
    this.state.animationFade.setValue(1)
    Animated.timing(this.state.animationFade, {
      easing: Easing.in(),
      duration: animationShortTime,
      toValue: 0,
    }).start(() => this._animationCallback(callback));
  }
  _animationCallback = (callback) => {
    if (this.props.modalType === 2) {//RootSiblings
      this.RootSiblings && this.RootSiblings.destroy(() => {
        callback && callback()
        this.RootSiblings = undefined
      })
    } else { //view
      this.setState({visible: false}, () => callback && callback())
    }
  }
}
const styles = StyleSheet.create({
  root: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
  }
});

這里主要通過 useReactModal 和 modalType 兩個屬性來控制我們所需要的實現(xiàn)

  • modalType 表示 modal 內(nèi)部實現(xiàn)方式,1 表示使用層級較高的實現(xiàn),2 表示使用 RootSiblings 進行實現(xiàn),3 表示使用 View 進行實現(xiàn),當不進行指定的時候,默認 Android 為 1,ios 為 2
  • useReactModal 主要針對 Android 端并且 modalType 為 1 的時候使用,true 表示使用 RN Modal,false 表示使用 FullScreenModal ,默認為 false
  • 對外提供 show,disMiss,isShow 方法分別表示顯示彈窗,隱藏彈窗和判斷當前彈窗的狀態(tài),同時在 show 和 disMiss 方法調用的時候還添加了 callback 回調

其他

Android Back 鍵的注意

當 Modal 組件使用 RootSiblings 或者 View 實現(xiàn)的時候,它并沒有處理一個 Android 的返回鍵,所以對于這兩種實現(xiàn)的時候,要額外處理一個 Back 鍵的操作,這里借助了 RN BackHandler 這個了,如果 modalType 不為 1 的話,需要通過 BackHandler 去實現(xiàn)一個返回鍵的監(jiān)聽,然后通過 onRequestClose 屬性進行返回

const DEVICE_BACK_EVENT = 'hardwareBackPress';
_addHandleBack = () => {
    if (Platform.OS === 'ios') {
      return
    }
    // 監(jiān)聽back鍵
    this.handleBack = BackHandler.addEventListener(DEVICE_BACK_EVENT, () => {
      const {onRequestClose} = this.props
      if (onRequestClose) {
        onRequestClose()
      } else {
        this.disMiss()
      }
      return true
    });
}
_removeHandleBack = () => {
    if (Platform.OS === 'ios') {
      return
    }
    this.handleBack && this.handleBack.remove()
}

View 封裝 Modal 時候的注意

如果是 View 實現(xiàn)的 Modal 控件,那必須要注意它的一個層級,必須滿足它所處于整個界面布局的最外層,否則它可能會被其他組件所擋住,同時它的最大的顯示范圍取決于它的父 View 的顯示范圍。

最后

當然在最后還是要附上實現(xiàn)效果圖

再一次附上 Demo 地址:https://github.com/hzl123456/ModalViewDemo

到此這篇關于React Native Modal 的封裝與使用 的文章就介紹到這了,更多相關React Native Modal 使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript中的useRef 和 useState介紹

    JavaScript中的useRef 和 useState介紹

    這篇文章主要給大家分享的是 JavaScript中的useRef 和 useState介紹,下列文章,我們將學習 useRef 和 useState hook是什么,它們的區(qū)別以及何時使用哪個。 這篇文章中的代碼示例將僅涉及功能組件,但是大多數(shù)差異和用途涵蓋了類和功能組件,需要的朋友可以參考一下
    2021-11-11
  • React Native之prop-types進行屬性確認詳解

    React Native之prop-types進行屬性確認詳解

    本篇文章主要介紹了React Native之prop-types進行屬性確認詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • React render核心階段深入探究穿插scheduler與reconciler

    React render核心階段深入探究穿插scheduler與reconciler

    這篇文章主要介紹了React render核心階段穿插scheduler與reconciler,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-11-11
  • React Form組件的實現(xiàn)封裝雜談

    React Form組件的實現(xiàn)封裝雜談

    這篇文章主要介紹了React Form組件的實現(xiàn)封裝雜談,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • react 原生實現(xiàn)頭像滾動播放的示例

    react 原生實現(xiàn)頭像滾動播放的示例

    這篇文章主要介紹了react 原生實現(xiàn)頭像滾動播放的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • react使用antd的上傳組件實現(xiàn)文件表單一起提交功能(完整代碼)

    react使用antd的上傳組件實現(xiàn)文件表單一起提交功能(完整代碼)

    最近在做一個后臺管理項目,涉及到react相關知識,項目需求需要在表單中帶附件提交,怎么實現(xiàn)這個功能呢?下面小編給大家?guī)砹藃eact使用antd的上傳組件實現(xiàn)文件表單一起提交功能,一起看看吧
    2021-06-06
  • React三大屬性之Refs的使用詳解

    React三大屬性之Refs的使用詳解

    這篇文章主要介紹了React三大屬性之Refs的使用詳解,幫助大家更好的理解和學習使用React,感興趣的朋友可以了解下
    2021-04-04
  • React如何利用Antd的Form組件實現(xiàn)表單功能詳解

    React如何利用Antd的Form組件實現(xiàn)表單功能詳解

    這篇文章主要給大家介紹了關于React如何利用Antd的Form組件實現(xiàn)表單功能的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • React?Flux與Redux設計及使用原理

    React?Flux與Redux設計及使用原理

    這篇文章主要介紹了React?Flux與Redux設計及使用,Redux最主要是用作應用狀態(tài)的管理。簡言之,Redux用一個單獨的常量狀態(tài)樹(state對象)保存這一整個應用的狀態(tài),這個對象不能直接被改變
    2023-03-03
  • 在?React?中使用?i18next的示例

    在?React?中使用?i18next的示例

    這篇文章主要介紹了在?React?中使用?i18next,本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01

最新評論