- utils/scaleTextForDensity.ts: PR<2.0のとき全TextのfontSizeを2.0/PR倍(max2.5x) - App.tsx: 起動時にscaleTextForDensityをインポート - responsive.ts: fontScaleをidentityに戻す(二重スケーリング防止) - 178箇所のハードコードfontSizeも個別修正不要で一括対応
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
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,
|
||
};
|
||
}
|