- Dimensions.get('window')を1/1.3に縮小パッチ
- useWindowDimensions()も自動的に小さい値を返す
- DensityScaleWrapperで1.3倍transform scaleで拡大
- コンポーネントは872x531dpとしてレイアウト→実画面1133x690に拡大
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
/**
|
||
* 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);
|
||
};
|
||
}
|
||
|
||
/** パッチ前の実画面サイズを取得するhook(DensityScaleWrapper用) */
|
||
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;
|
||
}
|