react-native-safe-area-context 用法

react-native-safe-area-context 主要用于處理異形屏的適配 ,React Navigation 的適配就是使用該組件進(jìn)行處理的。 React Navigation V5 版是通過(guò) safeAreaInsets 屬性進(jìn)行設(shè)置的,新版將該功能提取出來(lái),通過(guò) 組件、Hook 方式處理,這樣做的好處是:無(wú)需自行監(jiān)聽(tīng)屏幕旋轉(zhuǎn),會(huì)自動(dòng)更新同步渲染界面,處理起來(lái)也更加靈活。

安裝

yarn add react-native-safe-area-context
npx pod-install

使用

SafeAreaProvider

這是一個(gè)提供者,本身不會(huì)對(duì)布局產(chǎn)生任何影響,但只有在該組件包裹下的子組件才能使用 react-native-safe-area-context 提供的功能,通常,可以直接包裹在根組件上。React Navigation 本身已經(jīng)使用該組件作了包裹,所以在配合 React Navigation 使用時(shí),無(wú)需再進(jìn)行包裹了,直接使用即可。獨(dú)立使用時(shí),可使用類似如下的代碼:

import { SafeAreaProvider } from 'react-native-safe-area-context';

function App() {
  // 通??梢栽?APP 最外層使用,也可以在深層使用,但只有子組件才能API
  // 注意:不要把該組件放到有動(dòng)畫或滾動(dòng)的組件下級(jí),比如 Animated 或 ScrollView
  // 支持 View 的所有屬性,并支持額外的一個(gè) initialMetrics 屬性
  return <SafeAreaProvider initialMetrics={null}>...</SafeAreaProvider>;
}

initialWindowMetrics

上面 SafeAreaProviderinitialMetrics 屬性需要提供一個(gè) Object 值,提供相關(guān)的尺寸位置信息,默認(rèn)為自動(dòng)獲取,無(wú)需提供。默認(rèn)提供的信息可以通過(guò)該 Hook 獲取

import { initialWindowMetrics } from 'react-native-safe-area-context';

function HookComponent() {
  // 數(shù)據(jù)格式
  // {
  //    frame: { x: number, y: number, width: number, height: number },
  //    insets: { top: number, left: number, right: number, bottom: number },
  // }
  const insets = initialWindowMetrics();
  
  ...
}

useSafeAreaFrame / SafeAreaFrameContext

獲取離當(dāng)前組件最近的 SafeAreaProvider 尺寸信息

import { 
   useSafeAreaFrame,
   SafeAreaFrameContext
} from 'react-native-safe-area-context';

// 函數(shù)式組件
function HookComponent() {
  // 獲取 SafeAreaProvider 的寬高、偏移 x,y
  const {x, y, width, height} = useSafeAreaFrame();
  
  // ...
}

// class 組件
class ClassComponent extends React.Component {
  render() {
    return (
      <SafeAreaFrameContext.Consumer>
        {(frame) => <View ... />}
      </SafeAreaFrameContext.Consumer>
    );
  }
}

useSafeAreaInsets / SafeAreaInsetsContext

獲取當(dāng)前屏幕異形部分的尺寸

import { 
  useSafeAreaInsets,
  SafeAreaInsetsContext
} from 'react-native-safe-area-context';

// 函數(shù)式組件
function HookComponent() {
  // 該 Hook 返回屏幕四個(gè)方向上異形的尺寸
  // 若屏幕旋轉(zhuǎn),該值也會(huì)自動(dòng)更新,促使組件同步更新
  const {left, right, top, bottom} = useSafeAreaInsets();

  return <View style={{ paddingBottom: Math.max(bottom, 16) }} />;
}

// class 組件
class ClassComponent extends React.Component {
  render() {
    return (
      <SafeAreaInsetsContext.Consumer>
        {(insets) => <View style={{ paddingTop: insets.top }} />}
      </SafeAreaInsetsContext.Consumer>
    );
  }
}

withSafeAreaInsets

上面兩組分別是使用 Hook / Context 方式獲取相關(guān)尺寸數(shù)值應(yīng)用到 Function、Class 組件,對(duì)于 AreaInsets 還可使用 withSafeAreaInsets 應(yīng)用到高階組件。

class MyConmpoent extends React.Component {
  render() {
    const {insets} = this.props;
    return <View style={{ paddingTop: insets.top }} />
  }
}

export default withSafeAreaInsets(MyConmpoent);

SafeAreaView

以上都是比較靈活的方式,自行獲取數(shù)值進(jìn)行處理。還有另外一種較為方便的方式,在 SafeAreaProvider 任何層級(jí)內(nèi)都可以使用 SafeAreaView,該組件與 View 相同,默認(rèn)添加了 padding 屬性,在 View 四周添加了空白用以避開(kāi)屏幕異形的部分,該組件會(huì)在屏幕旋轉(zhuǎn)、或數(shù)值發(fā)生變動(dòng)時(shí)自動(dòng)更新。

import { SafeAreaView } from 'react-native-safe-area-context';

function SomeComponent() {
  // 支持 edges / mode 兩個(gè)屬性
  // edges: 設(shè)置要添加空白的方向,數(shù)組形式
  // mode:添加空白的方式,支持 padding(默認(rèn)) / margin
  return (
    <SafeAreaView 
        style={{ flex: 1, backgroundColor: 'red' }} 
        edges={['top', 'bottom', 'right', 'left']}
        mode="padding"
    >
      <View style={{ flex: 1, backgroundColor: 'blue' }} />
    </SafeAreaView>
  );
}

圖解

react-native-safe-area-context 返回屏幕異形尺寸,針對(duì)的是“非矩形”的部分,而不是“劉?!?、“針孔”。如下圖,倒腳部分都算作異形,在豎屏?xí)r通常沒(méi)啥問(wèn)題,但在橫屏?xí)r可能不符合設(shè)計(jì)預(yù)期,需注意。

頁(yè)面演示

React Navigation 舉例, 該組件已內(nèi)置 react-native-safe-area-context,并在 Header、BottomTab組件中處理了 top / bottom 方向的異形屏。在使用 React Navigation 時(shí),如果是一般情況,在頁(yè)面組件中無(wú)需刻意處理,如下圖

豎屏演示

但碰到以下兩種情況時(shí),仍需手動(dòng)處理

  • 頁(yè)面組件未使用 HeaderBottomTab,這就與上面的普通組件沒(méi)什么區(qū)別了,很好理解
  • 頁(yè)面支持橫屏,在橫屏?xí)r,如未做任何處理,效果如下圖
未對(duì)橫屏進(jìn)行處理

如果將頁(yè)面組件包裹在 SafeAreaView 組件內(nèi),top / bottom 方向異形尺寸為 0,left / right 方向會(huì)自動(dòng)應(yīng)用 padding,效果如下圖,但很有可能,下圖也不一定符合設(shè)計(jì)預(yù)期,比如 left 方向,圓角異形導(dǎo)致了 padding,但同時(shí)也浪費(fèi)了不少可視區(qū)域,可通過(guò) SafeAreaViewedges 屬性進(jìn)行設(shè)置。

頁(yè)面組件使用 SafeAreaView
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容