import { useWindowDimensions, PixelRatio, Dimensions } from "react-native"; // iPhone 14 Pro を基準デザインサイズとする const BASE_WIDTH = 393; const BASE_HEIGHT = 852; /** * ウィンドウサイズとディスプレイ密度に応じたスケーリングを提供するhook。 * * Samsung DeXなどの低密度外部モニターでは、同じdp値でも物理ピクセルが少なく * テキストが物理的に小さくなる。さらにモニターは視聴距離が遠いため、 * フォント/アイコンを密度比に応じて**拡大**する必要がある。 */ export function useResponsive() { const { width, height } = useWindowDimensions(); const pixelRatio = PixelRatio.get(); const heightRatio = Math.min(1, height / BASE_HEIGHT); // PixelRatio < 2.0 は低密度ディスプレイ(DeX等の外部モニター) // DeX実測値: PR=0.756, Win=1133x690 const isLowDensity = pixelRatio < 2.0; // フォント拡大はutils/scaleTextForDensity.tsでText.renderをモンキーパッチして // 全テキストに一括適用するため、ここでは恒等関数とする(二重適用防止) return { /** フォントサイズ用:拡大はscaleTextForDensityで一括処理 */ fontScale: (size: number) => size, /** 垂直方向の寸法用(ヘッダー高さ、スペーシング、余白等) */ verticalScale: (size: number) => Math.round(size * heightRatio), /** * アイコン・コンテナ寸法用:拡大しない * width/height/borderRadius等にも使われるため、拡大するとレイアウト崩壊する */ moderateScale: (size: number, _factor = 0.5) => size, isLowDensity, heightRatio, windowWidth: width, windowHeight: height, }; }