React Navigationを使用していて、要素のサイズを取得する際にどこにその値が格納されているのかよくわからなかったので、備忘録としてまとめました。
特にモーダルを使用しているアニメーションにより高さが変わるので、なかなか厄介でした。
以下の画像とコードをベースとして①から順番に取得方法を記述していきます。
今回はiOSでしか作成していないので、Androidについては未確認です。
参考画像
サンプルコード
import React from 'react'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { StatusBar, StyleSheet } from 'react-native'
import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import ModalNavigation from './src/ModalNavigation'
import 'react-native-gesture-handler'
const MainStack = createNativeStackNavigator<MainStackParamList>()
function IndexScreen () {
return <View><Text>Index</Text></View>
}
function ModalScreen () {
return <View><Text>Modal</Text></View>
}
function ModalNavigation () {
return (
<MainStack.Navigator initialRouteName="Index">
<MainStack.Group>
<MainStack.Screen name="Index" component={IndexScreen} />
</MainStack.Group>
<MainStack.Group screenOptions={{ presentation: 'modal' }}>
<MainStack.Screen name="Modal" component={ModalScreen} />
</MainStack.Group>
</MainStack.Navigator>
)
}
export default function App () {
return (
<SafeAreaProvider style={styles.container}>
<NavigationContainer>
<ModalNavigation />
</NavigationContainer>
<StatusBar barStyle='dark-content' />
</SafeAreaProvider>
)
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff'
}
})
StatusBarの高さの取得方法
まずは①の取得方法です。 確認したところ、3つありました。
NativeModulesを使用する
Androidは未確認の方法です。
import { NativeModules } from 'react-native'
const { StatusBarManager } = NativeModules
console.log(StatusBarManager.HEIGHT)
useSafeAreaInsetsを使用する
今回はSafeAreaProvider
を使用しているので、それを使って取得します。
import { useSafeAreaInsets } from 'react-native-safe-area-context'
const insets = useSafeAreaInsets()
console.log(insets.top)
StatusBarを使った取得
これはAndroidのみです。
import { StatusBar } from 'react-native'
console.log(StatusBar.currentHeight)
iOSの高さが取得できているので、一番上がおそらく安定してると思います。
StatusBarのボトムから一番表に出ているコンポーネントのヘッダーまでの位置の取得方法
まずはこれは②の取得方法ですが、明確に数字を取れるようなものはありませんでした。
一番上の線と二番目の線の距離を測ると10px
だったので固定でおいています。
react-navigationのgetDefaultHeaderHeightを見るとデバイス毎に決め打ちされてるので、一旦これでいいかなと思っています。
import { useHeaderHeight } from '@react-navigation/elements'
const headerHeight = useHeaderHeight()
console.log(StatusBar.currentHeight + 10)
モーダルが出るときに、スクリーンが背景に隠れる動きをしているので、もしかすると固定ではなくスケールを使ってるかもしれませんが、そこまで調べるのは面倒でした。