Files
jrshikoku/utils/dexDimensionOverride.ts
harukin-expo-dev-env 393bcc4df3 DeX: Dimensions.getモンキーパッチ + transform scaleで低密度ディスプレイ対応
- Dimensions.get('window')を1/1.3に縮小パッチ
- useWindowDimensions()も自動的に小さい値を返す
- DensityScaleWrapperで1.3倍transform scaleで拡大
- コンポーネントは872x531dpとしてレイアウト→実画面1133x690に拡大
2026-03-29 23:31:26 +00:00

68 lines
2.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Samsung DeX 等の低密度ディスプレイで、Dimensions を仮想的に縮小する。
* コンポーネントが小さい画面だと思ってレイアウトし、
* App.tsx の DensityScaleWrapper が transform scale で実画面に拡大する。
*
* 必ず App.tsx の最初にインポートすること。
*/
import { Dimensions, PixelRatio } from "react-native";
import { useState, useEffect } from "react";
const pr = PixelRatio.get();
export const IS_LOW_DENSITY = pr < 1.5;
export const DEX_SCALE = IS_LOW_DENSITY ? Math.min(1.3, 1.5 / pr) : 1;
// オリジナル関数の参照を保存
const originalGet = Dimensions.get.bind(Dimensions);
const originalAddEventListener =
Dimensions.addEventListener.bind(Dimensions);
if (IS_LOW_DENSITY) {
// Dimensions.get('window') をスケーリング
(Dimensions as any).get = (type: "window" | "screen") => {
const real = originalGet(type);
if (type === "window") {
return {
...real,
width: real.width / DEX_SCALE,
height: real.height / DEX_SCALE,
};
}
return real;
};
// change イベントもスケーリング
(Dimensions as any).addEventListener = (type: string, handler: any) => {
const wrappedHandler = (event: any) => {
if (event?.window) {
handler({
...event,
window: {
...event.window,
width: event.window.width / DEX_SCALE,
height: event.window.height / DEX_SCALE,
},
});
} else {
handler(event);
}
};
return originalAddEventListener(type, wrappedHandler);
};
}
/** パッチ前の実画面サイズを取得するhookDensityScaleWrapper用 */
export function useRealWindowDimensions() {
const [dims, setDims] = useState(() => {
const d = originalGet("window");
return { width: d.width, height: d.height };
});
useEffect(() => {
const sub = originalAddEventListener("change", ({ window }: any) => {
setDims({ width: window.width, height: window.height });
});
return () => sub?.remove();
}, []);
return dims;
}