RORK LABJP
FREETRY — Rork announced on X that Rork Max is free to try for a limited time, a chance to touch the $200/month tier without paying up frontONESHOT — Rork Max claims to one-shot almost any app for iPhone, Watch, iPad, TV, and Vision Pro, including builds that lean on AR and 3DXCODE — Positioned as a website that replaces Xcode: one click to install on device, two clicks to publish to the App Store, powered by Swift, Claude Code, and OpusPAPERLINE — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentSKILLS — Rork's app-store-connect-cli-skills repo was updated on July 9, a sign the submission tooling keeps getting attentionMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026, up from under 25% in 2020FREETRY — Rork announced on X that Rork Max is free to try for a limited time, a chance to touch the $200/month tier without paying up frontONESHOT — Rork Max claims to one-shot almost any app for iPhone, Watch, iPad, TV, and Vision Pro, including builds that lean on AR and 3DXCODE — Positioned as a website that replaces Xcode: one click to install on device, two clicks to publish to the App Store, powered by Swift, Claude Code, and OpusPAPERLINE — Rork acquired the app builder Paperline and says it will stay acquisitive to bring in engineering talentSKILLS — Rork's app-store-connect-cli-skills repo was updated on July 9, a sign the submission tooling keeps getting attentionMARKET — Gartner expects 75% of new applications to be built with low-code or no-code tools by the end of 2026, up from under 25% in 2020
Articles/Dev Tools
Dev Tools/2026-04-21Intermediate

Fixing Screen Orientation and Rotation Issues in Rork-Built Apps

When Rork-generated apps won't rotate, refuse to lock to portrait on certain screens, or break layouts on iPad landscape — here are the fixes for both iOS and Android.

Troubleshooting38OrientationRotationExpo149React Native209

You build an app with Rork, load it on your phone, turn the device sideways — and nothing happens. Or the opposite: you want the login screen to stay in portrait but it keeps flipping whenever the user tilts the phone. If this sounds familiar, you're not alone. I ran into this exact problem when building my first game-style app in Rork and wanted the gameplay screen locked to landscape while everything else stayed portrait.

By default, Rork's AI generates apps in portrait-only mode, and retrofitting rotation support — especially per-screen control — exposes some unexpected gotchas on both iOS and Android. This guide walks through the real traps in order, so you can stop guessing and ship.

Start Here: The orientation Field in app.json

Open the project Rork generated and look at app.json (or app.config.js). You'll see something like this:

{
  "expo": {
    "orientation": "portrait",
    "ios": { /* ... */ },
    "android": { /* ... */ }
  }
}

The orientation field sets the app-wide default. It accepts three values:

  • "portrait" — locked to portrait (the default Rork generates)
  • "landscape" — locked to landscape
  • "default" — follows the device, both orientations supported

If nothing rotates at all, this is almost always where the issue is. Change it to "default" and rebuild.

{
  "expo": {
    "orientation": "default"
  }
}

Simple so far — but orientation never stays this clean for long. The setting interacts with native manifests, device-level preferences, and per-screen overrides, which is where most debugging hours disappear.

The iOS Gotcha: Build Cache and iPad Requirements

Even with "default" set, you might still see iOS refuse to rotate. The culprit is usually a stale build cache. Under the hood, Expo regenerates the iOS Info.plist entries (specifically UISupportedInterfaceOrientations) from app.json at build time, but a cached build from before your change can hide the new values. I've shipped a build twice in a row thinking my change didn't take, only to realize I was testing the previous binary.

# Clear the cache and rebuild
eas build --platform ios --clear-cache

If you want only iPad to support all orientations while keeping iPhone in portrait, you have to say so explicitly in the ios section:

{
  "expo": {
    "orientation": "portrait",
    "ios": {
      "requireFullScreen": false,
      "infoPlist": {
        "UISupportedInterfaceOrientations~ipad": [
          "UIInterfaceOrientationPortrait",
          "UIInterfaceOrientationPortraitUpsideDown",
          "UIInterfaceOrientationLandscapeLeft",
          "UIInterfaceOrientationLandscapeRight"
        ]
      }
    }
  }
}

The requireFullScreen: false line is what makes your app play nicely with Slide Over and Split View on iPad. Apple's reviewers often flag apps that don't support iPad multitasking — worth setting proactively if you ship to both device classes, because getting rejected at review is far more painful than adding one line now. In addition, Apple's Human Interface Guidelines strongly encourage iPad apps to support all four orientations, and reviewers have started rejecting apps that appear locked to portrait on larger screen sizes, even without explicit multitasking complaints.

If you want to test the generated Info.plist before submitting, run eas build --platform ios --profile development locally, then extract the .ipa, rename it to .zip, and inspect the Info.plist inside the Payload/*.app/ directory. It's an extra step, but it beats finding out at the review stage.

Switching Orientation Per Screen

"Most of the app is portrait, but the video player should be landscape." This is a common requirement in media and game apps, and the tool for the job is expo-screen-orientation.

Install it via Rork's package panel, or locally:

npx expo install expo-screen-orientation

Then, in the screen that needs a different orientation, lock on entry and restore on exit:

import * as ScreenOrientation from 'expo-screen-orientation';
import { useEffect } from 'react';
 
export default function VideoPlayerScreen() {
  useEffect(() => {
    // Lock to landscape when this screen mounts
    ScreenOrientation.lockAsync(
      ScreenOrientation.OrientationLock.LANDSCAPE
    );
 
    // Restore portrait on unmount
    return () => {
      ScreenOrientation.lockAsync(
        ScreenOrientation.OrientationLock.PORTRAIT_UP
      );
    };
  }, []);
 
  return (/* your video player JSX */);
}

The cleanup function is essential. Skip it and the previous screen ends up stuck in landscape too — a confusing UX bug that's easy to miss in development, because developers usually test by navigating forward, not backward.

There's one more subtlety worth calling out: if app.json still says "orientation": "portrait", iOS will silently refuse the lockAsync(LANDSCAPE) call. iOS only honors orientations the app has declared support for at the manifest level. For per-screen control to work, the app-wide setting must be "default", and you enforce the portrait-lock on other screens individually with OrientationLock.PORTRAIT_UP.

For navigation libraries like React Navigation or Expo Router, a cleaner pattern is to wrap the orientation call in a useFocusEffect, so the lock fires whenever the screen is focused — not just on mount. This matters if users can return to the screen via back navigation without re-mounting it.

Android-Specific Checks

Sometimes iOS rotates just fine, but Android stays stubbornly in portrait. The usual cause is that android:screenOrientation in the generated manifest still reads portrait instead of sensor or fullSensor.

When you're under Expo's managed workflow, app.json drives this and should regenerate correctly. But if you've ever done a local build or hand-edited the manifest, it's worth double-checking. One way to confirm is to unzip the APK and inspect AndroidManifest.xml directly — if it still says portrait, the rebuild didn't pick up your change.

Another frequent cause on Android 11 and newer: the user has "auto-rotate" turned off in system settings. Your app will honor "default" but still behave as if it's locked to portrait, because the OS blocks rotation globally. This catches people often during beta testing, where a tester reports "rotation is broken" but the device is the problem.

// Quick check: is the orientation even supported on this device right now?
import * as ScreenOrientation from 'expo-screen-orientation';
 
async function checkOrientationSupport() {
  const supported = await ScreenOrientation.supportsOrientationLockAsync(
    ScreenOrientation.OrientationLock.LANDSCAPE
  );
  console.log('Landscape supported:', supported);
  // → false usually means a system-level setting is blocking rotation
}

When supportsOrientationLockAsync returns false, stop debugging your code and check the device settings first. I've lost an hour to this one myself — writing extra try/catch handlers and logging statements before realizing the phone's rotation lock was on.

When Rotation Works, But the Layout Breaks

Congratulations — your app rotates. Now you're facing the next wall: the layout was designed for portrait, and in landscape everything overflows or crams awkwardly into a corner.

Rork's AI usually generates layouts assuming a tall aspect ratio. The cleanest fix is the useWindowDimensions hook — it reports the current dimensions and updates on rotation, unlike Dimensions.get('window') which returns a stale initial value.

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,
    ]}>
      {/* your content */}
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: { flex: 1, padding: 16 },
  portrait: { flexDirection: 'column' },
  landscape: { flexDirection: 'row', paddingHorizontal: 32 },
});

Remember: useWindowDimensions, not Dimensions.get. The latter only gives you the value at mount time and won't update when the device rotates. One more tip: when your layout has multiple nested views, resist the urge to add aspectRatio constraints everywhere. aspectRatio locks the dimension relationship and tends to cause clipping when the orientation changes mid-animation. Prefer percentage-based width / height with flex weights — they adapt more gracefully to mid-transition frames.

If your app has images or video that must maintain their own aspect ratio during rotation, use resizeMode: 'contain' on the Image component rather than forcing the container to match. The image adapts, the container stays flexible.

For screens with a lot of conditional layout, I find it cleaner to derive an orientation variable at the top of the component and pass it into stylesheet selectors, rather than sprinkling isLandscape ternaries throughout the JSX. It keeps the template readable when the layout has many branches.

A Sanity Check Before Shipping

Orientation bugs have a nasty habit of appearing only in specific transitions — you rotate while a modal is open, or you rotate then navigate, or you background the app in landscape and foreground it. In my experience, most orientation-related review rejections come from these transition edge cases rather than the steady state.

Before release, I work through this short list on a real device (not just the simulator):

  • Rotate while on every screen, including modals and overlays
  • Rotate, then navigate forward and back — does the orientation lock restore correctly?
  • Rotate, send the app to the background, rotate the device back, and foreground — does the UI come up in the correct orientation?
  • On iPad, test Split View with the app occupying both the narrower and wider pane
  • On Android, test with auto-rotate off in system settings (the app should still behave sensibly, even if it can't rotate)

The simulator is convenient for quick checks but misses behaviors tied to real sensors and OS-level rotation locks. A 10-minute pass on a physical device catches almost everything.

Still Stuck? A Quick Checklist

If rotation still isn't behaving after the changes above, work through these in order:

  • Test on an eas build output, not on the Rork Preview / Companion app — Preview handles orientation locks differently than a production build, so Preview passing doesn't guarantee the release build will
  • After any app.json change, rebuild with --clear-cache to bust the build cache
  • When using expo-screen-orientation, confirm app.json has "orientation": "default" — per-screen locks are no-ops on iOS if the app-level setting forbids the orientation
  • For iPad, confirm ios.requireFullScreen: false is set to enable multitasking
  • On Android, check that the device's system "auto-rotate" is enabled before blaming your code

If you're also seeing navigation-side issues, Fixing Expo Router Screen Navigation Errors in Rork may help. And if device-specific crashes are part of the same debugging session, Simulator vs. Real-Device Crash Triage in Rork Max covers the broader cross-device workflow.

Screen orientation looks like a one-line config change, but the real gotchas hide in per-screen control, iPad-specific flags, and device-level settings. The cleanest mental model is: start with the app-wide setting in app.json, layer per-screen control on top when needed, then adapt the layout with useWindowDimensions. Before your next session, decide one thing — what rotation policy does your app actually need? Full rotation, portrait-only except one screen, or tablet-only landscape? Once that's settled, the implementation above takes you the rest of the way.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-07-08
Your SVG Icon Shows in Expo Go but Vanishes in a Build — Making SVGs Render Reliably in Rork Apps
When a .svg import renders nothing, throws a resolve error, or ignores your theme colors in Rork and Expo apps, here is how to fix it with metro.config.js, react-native-svg-transformer, and currentColor — with working code.
Dev Tools2026-05-25
Fixing Layout Bleed on Android 15 (API 35) in Rork Apps
Once you bump targetSdkVersion to 35, Android 15 enforces edge-to-edge display, and Rork-generated tab bars and headers start sliding under the system bars. Here are the patterns I use with react-native-edge-to-edge and useSafeAreaInsets to fix it properly.
Dev Tools2026-05-03
5 Things to Check First When Rork Shows 'Unable to Resolve Module'
Walk through the five most common causes of the 'Unable to resolve module' error in Rork, React Native, and Expo projects, with the exact commands and the order in which to check them.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →