Rork でアプリを作って実機で動かしたとき、「あれ、横にしても画面が回らない」あるいは逆に「ログイン画面だけ縦固定にしたいのに勝手に回ってしまう」といった経験はないでしょうか。私も最初の頃、ゲーム系アプリを作ったときに「ゲーム画面だけ横向きに固定したい」という要件でかなり悩みました。
Rork の AI は基本的に縦向き固定でアプリを生成することが多く、後から回転対応や画面ごとの制御を入れようとすると思わぬ落とし穴に出会います。ここではRork で生成したアプリのオリエンテーション設定でつまずきやすい箇所を、iOS と Android 両方の視点から整理します。
まず確認すべき: app.json の orientation 設定
Rork で生成した直後のプロジェクトを開くと、app.json(または app.config.js)に以下のような記述があります。
{
"expo": {
"orientation": "portrait",
"ios": { /* ... */ },
"android": { /* ... */ }
}
}この orientation フィールドが、アプリ全体の基本方針を決めています。設定できる値は次の3つです。
"portrait"— 縦向き固定(デフォルト)"landscape"— 横向き固定"default"— ユーザーの端末回転に追従(両対応)
「画面が回らない」と感じているときは、まずここが "portrait" のままになっていることがほとんどです。両対応にしたい場合は、シンプルに "default" に変更してください。
{
"expo": {
"orientation": "default"
}
}ただし、これだけで話が終わらないのがオリエンテーションの厄介なところです。
見落としやすい落とし穴: iOS ネイティブ側の設定
app.json を "default" にしても、iOS で横回転しないケースがあります。これは iOS 側の Info.plist 相当の設定である supportedInterfaceOrientations が、Expo のビルド時に再生成されるためです。
Expo 管理下であれば app.json の変更が自動で反映されますが、一度 eas build を実行してから変更した場合、古いビルドキャッシュが残っていると反映されないことがあります。
# キャッシュをクリアして再ビルド
eas build --platform ios --clear-cacheさらに、iPad 版のみ全回転対応にしたい場合は ios セクションに明示的に書く必要があります。
{
"expo": {
"orientation": "portrait",
"ios": {
"requireFullScreen": false,
"infoPlist": {
"UISupportedInterfaceOrientations~ipad": [
"UIInterfaceOrientationPortrait",
"UIInterfaceOrientationPortraitUpsideDown",
"UIInterfaceOrientationLandscapeLeft",
"UIInterfaceOrientationLandscapeRight"
]
}
}
}
}requireFullScreen: false は、iPad の Slide Over・Split View に対応するために必要です。App Store 審査で「iPad のマルチタスクに対応してください」と指摘されることがあるので、iPad でも横対応する場合は忘れずに入れておきましょう。
画面ごとに方向を切り替えたいとき
「アプリ全体は縦固定、でもビデオ再生画面だけは横にしたい」という要件は、ゲーム系・動画系のアプリでよくあります。これには expo-screen-orientation を使います。
まずパッケージを追加します。Rork のパッケージ管理画面から追加するか、ローカルで開発する場合は以下を実行します。
npx expo install expo-screen-orientationビデオプレイヤー画面などで、入った瞬間に横向きに固定し、離れるときに縦に戻す実装は次のようになります。
import * as ScreenOrientation from 'expo-screen-orientation';
import { useEffect } from 'react';
export default function VideoPlayerScreen() {
useEffect(() => {
// 画面に入ったら横向きに固定
ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.LANDSCAPE
);
// 画面から離れるときに縦向きに戻す
return () => {
ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.PORTRAIT_UP
);
};
}, []);
return (/* ビデオプレイヤーの中身 */);
}ポイントは、useEffect のクリーンアップ関数で必ず元の向きに戻すことです。ここを忘れると、前の画面に戻ったときも横向きのまま残ってしまい、ユーザーを混乱させます。
もう1つ注意したいのが、app.json の orientation が "portrait" のままだと、lockAsync(LANDSCAPE) を呼んでも iOS では効かないという挙動です。これは iOS が「アプリレベルで許可されていない向き」を拒否するためです。画面ごとに切り替える設計をするなら、app.json 側は "default" にしておく必要があります。
Android で挙動が違うときの確認ポイント
iOS では期待通り動いているのに、Android では回転しないというケースもあります。これは Android 側の android:screenOrientation が sensor や fullSensor ではなく portrait で固定されている場合に起こります。
Expo の管理下では app.json の設定から自動生成されるはずですが、古いビルドや手動で書き換えたケースでは要確認です。
また、Android 11 以降では「設定 → ディスプレイ → 画面の自動回転」がオフになっていると、アプリが "default" でも回転しないことがあります。テスト時は端末側の設定も併せてチェックしましょう。
// Android の端末設定が原因でないかを切り分けるコード
import * as ScreenOrientation from 'expo-screen-orientation';
async function checkOrientationSupport() {
const supported = await ScreenOrientation.supportsOrientationLockAsync(
ScreenOrientation.OrientationLock.LANDSCAPE
);
console.log('Landscape supported:', supported);
// → false の場合、端末のシステム設定が原因の可能性が高い
}supportsOrientationLockAsync は、その向きがそもそも利用可能かを返してくれます。ログで false と出たら、端末設定を疑ってください。
レイアウトが崩れる問題への対処
無事に回転するようになっても、横向きでレイアウトが崩れるという次の壁が待っています。Rork の AI が生成するレイアウトは縦向き前提になっていることが多く、横にすると要素が画面外にはみ出すことがあります。
この場合は、useWindowDimensions フックで動的に幅と高さを取得して、条件分岐でスタイルを切り替えるのが扱いやすい方法です。
import { useWindowDimensions, View, StyleSheet } from 'react-native';
export default function ResponsiveScreen() {
const { width, height } = useWindowDimensions();
const isLandscape = width > height;
return (
<View style={[
styles.container,
isLandscape ? styles.landscape : styles.portrait,
]}>
{/* 中身 */}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 },
portrait: { flexDirection: 'column' },
landscape: { flexDirection: 'row', paddingHorizontal: 32 },
});Dimensions.get('window') ではなく useWindowDimensions を使うのがポイントです。前者は初期値を返すだけで、回転時に更新されません。
もう一つの Tips として、ネストした View に aspectRatio を多用するのは避けたほうが安全です。回転アニメーションの途中フレームでクリッピングが発生しやすく、表示が一瞬崩れます。画像や動画などアスペクト比を維持したい要素には、Image の resizeMode: 'contain' を使い、コンテナ側はフレキシブルに保つのが無難です。
React Native のレイアウト設計をもっと体系的に
リリース前の最終チェック
オリエンテーション関連の不具合は、定常状態より画面遷移の瞬間に発生しがちです。モーダルを開いた状態で回転した、回転してから戻った、バックグラウンドに送って向きを変えて戻った——こうしたエッジケースが、App Store や Google Play の審査で指摘される原因の大半を占めます。
リリース前には、実機で次の項目を必ず通してください。
- 全画面(モーダル・オーバーレイ含む)で回転して動作確認してください
- 回転 → 画面遷移 → 戻る、でオリエンテーションが正しく復元されるか
- 回転 → バックグラウンド → 向きを変える → フォアグラウンド、で UI が正しい向きで復帰するか
- iPad なら Split View の狭い/広いペインそれぞれでテストしてください
- Android では端末の「自動回転オフ」状態でも破綻しないか
シミュレータは手軽ですが、センサーや OS レベルの回転ロックが関わる挙動は拾えません。10分ほど実機でテストするだけで、ほぼすべての問題を事前に捕まえられます。
それでも解決しないときのチェックリスト
ここまでの対処で直らない場合、以下を順に確認してみてください。
- Rork の Preview(Companion アプリ)ではなく、必ず
eas buildで作った実機ビルドで検証する(Preview は方向ロックの挙動が異なることがあります) app.jsonを変更した後は--clear-cacheを付けて再ビルドしてくださいexpo-screen-orientationを使っている場合、app.jsonのorientationが"default"になっているか確認してください- iPad の場合は
ios.requireFullScreen: falseが入っているか確認してください - Android 実機の「自動回転」設定がオンになっているか確認してください
関連する画面遷移周りのエラーでお困りの方は、Rork の Expo Router でナビゲーションエラーが出るときの対処法 も併せて参考にしてください。デバイス固有の挙動差で悩んでいる方には、Rork の Max プランでシミュレータと実機でクラッシュが違うときの切り分け が役に立つはずです。
画面回転の問題は一見シンプルに見えて、iOS と Android でそれぞれ別の罠があります。まずは app.json → 画面単位の制御 → レイアウトの分岐、という順で切り分けるのが最短ルートです。今日のところは、作っているアプリで「どこまで回転対応するか」の方針だけ決めてみませんか。全画面対応か、特定画面のみか、それともすべて縦固定か。方針が決まれば、実装は上で紹介した手順でたどり着けます。