yaofly2012 / note

Personal blog

Home Page:https://github.com/yaofly2012/note/issues

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RN-SafeAreaView

yaofly2012 opened this issue · comments

commented

SafeAreaView组件

功能

设备安全区域内容展示页面内容:

原理

本质是个View组件,但会自动添加padding
SafeAreaView不是无脑的添加padding,而是在适当的时候添加padding

  1. 上边缘触摸了设备顶部,即坐标Y === 0;
  2. 左边缘触摸了设备左部,即坐标X === 0;
  3. 下边缘超过设备底部,即坐标Y + View高度 >= 设备高度;
  4. 右边缘超过设备右部,即坐标X + View宽度 >= 设备宽度;

SafeAreaView四边处于以上4中情况时,则会给边缘添加合适的padding

具体实现可以参考react-native-safe-area-view_getSafeAreaStyle方法的实现。

// 检查`SafeAreaView`边缘是否触碰到设备边缘
 _updateMeasurements = () => {
    if (!this._isMounted) return;
    if (!this._view.current) return;

    const { width: WIDTH, height: HEIGHT } = getResolvedDimensions();

    // calling getNode on the ref is no longer necessary in the future
    const view = this._view.current.measureInWindow
      ? this._view.current
      : this._view.current.getNode();
    view.measureInWindow((realX, realY, winWidth, winHeight) => {
      if (!this._view.current) {
        return;
      }

      if (realY >= HEIGHT) {
        realY = realY % HEIGHT;
      } else if (realY < 0) {
        realY = (realY % HEIGHT) + HEIGHT;
      }

      if (realX >= WIDTH) {
        realX = realX % WIDTH;
      } else if (realX < 0) {
        realX = (realX % WIDTH) + WIDTH;
      }

      let nextState = {
        touchesTop: realY === 0,
        touchesBottom: realY + winHeight >= HEIGHT,
        touchesLeft: realX === 0,
        touchesRight: realX + winWidth >= WIDTH,
        viewWidth: winWidth,
        viewHeight: winHeight,
      };

      if (!shallowEquals(nextState, this.state)) {
        this.setState(nextState);
      }
    });
  };

使用

包裹整个页面组件

如果只是简单的把页面内容展示安全区域内,可以用SafeAreaView+flex: 1包裹页面组件即可。正如RN官方的[DEMO]:(https://reactnative.dev/docs/safeareaview#example):

import React from 'react';
import {StyleSheet, Text, SafeAreaView} from 'react-native';

const App = () => {
  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.text}>Page content</Text>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  text: {
    fontSize: 25,
    fontWeight: '500',
  },
});

export default App;

头部组件

为了实现更好的沉浸式头部组件(Header, Tab等)可以在这些组件内部使用SafeAreaView

底部组件

跟头部组件类似,还有些页面底部的组件中可以直接使用SafeAreaView

Issues/Concern

  1. 不能给SafeAreaView显示的指定padding相关属性。
  2. ScrollView内部使用SafeAreaView时会发生页面抖动。解决方案:contentInsetAdjustmentBehavior="automatic"

参考

  1. ReactNative SafeAreaView
  2. iOS Safe Area
  3. SafeAreaView doesn't respect padding property in style #22211
  4. Having a SafeAreaView inside ScrollView breaks scrolling #19658
  5. react-native-safe-area-context