●APPLE-AI — Apple opens Foundation Models free to developers under 2M first-time downloads, slashing the cost of adding AI to indie apps●SWIFT-API — Foundation Models server-side integration lets you call Claude and Gemini through the same Swift API, now with image input●KOTLIN-MIGRATION — Android Studio's migration agent converts React Native apps into native Kotlin automatically — a future path for Rork-built apps●RORK-MAX — Rork Max generates native Swift code ($200/mo), covering iPhone, iPad, Watch, TV, Vision Pro, and iMessage●SIMULATOR — A browser-based streaming iOS simulator lets you test on a real Apple environment without Xcode or Mac hardware●SWIFTUI — SwiftUI evolves at WWDC 2026 with reorderable containers, swipe actions for any container, and layouts up to 2x faster●APPLE-AI — Apple opens Foundation Models free to developers under 2M first-time downloads, slashing the cost of adding AI to indie apps●SWIFT-API — Foundation Models server-side integration lets you call Claude and Gemini through the same Swift API, now with image input●KOTLIN-MIGRATION — Android Studio's migration agent converts React Native apps into native Kotlin automatically — a future path for Rork-built apps●RORK-MAX — Rork Max generates native Swift code ($200/mo), covering iPhone, iPad, Watch, TV, Vision Pro, and iMessage●SIMULATOR — A browser-based streaming iOS simulator lets you test on a real Apple environment without Xcode or Mac hardware●SWIFTUI — SwiftUI evolves at WWDC 2026 with reorderable containers, swipe actions for any container, and layouts up to 2x faster
Android 17 Will Ignore Your Portrait Lock — Getting Rork-Built Expo Apps Ready for Large Screens Ahead of Time
Android 17 stops honoring orientation locks and resizability restrictions on large-screen devices. Here is how I assessed the impact on my Rork-built Expo apps, reworked the layouts, and verified everything with nothing but an emulator.
Last week I opened one of my own apps inside a resizable emulator running the Android 17 beta, and what I saw made me pause. A screen I had designed strictly for portrait was stretched across a wide landscape window. The letterboxing — those familiar black bars that used to protect a locked layout — was simply gone.
If you run Android apps as an indie developer, chances are you have relied on the same assumption I did: lock the app to portrait and the layout can never break. Starting with Android 17, expected this summer, that assumption stops holding on large-screen devices.
In this article I walk through what I actually did across six of my production apps built with Rork on the Expo (React Native) stack: judging whether an app is affected, unwinding the orientation lock safely, restructuring layouts around size classes, and verifying the whole thing without buying a single foldable.
What Is Changing — the Slow Death of Orientation Restrictions
Let me summarize the change first. Beginning with Android 16, Google started ignoring the following app-declared restrictions on devices whose shorter side is 600dp or more — tablets, unfolded foldables, and desktop windows:
Portrait or landscape locks declared via screenOrientation
Resize refusal declared via resizableActivity="false"
Declared aspect-ratio minimums and maximums
Android 16 still allowed a temporary opt-out through a compatibility property. Android 17 removes that escape hatch, which is why this release is the real deadline. The question is no longer whether to adapt, only when.
Phones (shorter side under 600dp) keep honoring your locks as before. The scope is strictly large screens — but a foldable is a phone when closed and a tablet when opened, so "we never shipped a tablet version" no longer keeps you out of scope.
A 10-Minute Impact Assessment
Before touching any code, estimate how exposed your app is. I checked three things, in this order:
Look at orientation in app.json. Rork-generated Expo projects default to "orientation": "portrait". If yours says portrait or landscape, you are in scope for the ignored-restrictions behavior
Hunt down fixed-size layout code. Any module that evaluates Dimensions.get("window") once at import time will keep returning stale dimensions after a resize. Run grep -rn "Dimensions.get" src/ and review every hit
Check the device breakdown in Google Play Console. Under statistics by device type, see what share tablets and foldables hold. Across my apps it was 4–7% — small, but these users see larger ad surfaces, and in my AdMob reports their eCPM trends higher than on phones, which makes them an expensive segment to abandon
If both items 1 and 2 apply, doing nothing means real users will see the stretched, broken version of your UI. Conversely, if you already ship with orientation: "default" and dimension-driven layouts, this article mostly reduces to the verification routine at the end.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦A 10-minute check to determine whether your portrait-locked app will be force-resized on Android 17
✦A size-class design and useWindowDimensions-based implementation that survives unlocking orientation
✦An emulator-only verification routine for foldables and tablets, plus the 4 fixes it surfaced in my own apps
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Removing the global lock raises an immediate question: what about camera screens or video players that genuinely want a fixed orientation? Lock those per screen with expo-screen-orientation — and skip the lock on large screens, where it would be ignored anyway:
// useConditionalPortraitLock.ts — lock portrait on phones onlyimport { useEffect } from "react";import { useWindowDimensions } from "react-native";import * as ScreenOrientation from "expo-screen-orientation";export function useConditionalPortraitLock() { const { width, height } = useWindowDimensions(); // Treat shorter side >= 600dp as large screen: locking there is futile const isLargeScreen = Math.min(width, height) >= 600; useEffect(() => { if (isLargeScreen) { ScreenOrientation.unlockAsync(); return; } ScreenOrientation.lockAsync( ScreenOrientation.OrientationLock.PORTRAIT_UP ); return () => { ScreenOrientation.unlockAsync(); }; }, [isLargeScreen]);}
Writing "do not lock on large screens" explicitly may look redundant, since the OS ignores the lock anyway. I prefer it this way: code that encodes the platform's intent keeps working even if enforcement details shift, while code that depends on an ignored setting is a latent bug.
Rebuilding Layouts Around Size Classes
With orientation unlocked, layout comes next. Scattering if (isTablet) checks across screens is how maintenance dies. I centralized the decision into a single size-class hook, so screens only ever read a class name:
// useSizeClass.ts — define size classes in exactly one placeimport { useWindowDimensions } from "react-native";export type SizeClass = "compact" | "medium" | "expanded";export function useSizeClass(): SizeClass { const { width } = useWindowDimensions(); if (width < 600) return "compact"; // phone portrait if (width < 840) return "medium"; // unfolded foldable, small tablet portrait return "expanded"; // tablet landscape, desktop window}
The 600 / 840 thresholds match the Material Design window size classes. Borrowing a published standard instead of inventing your own makes it far easier to stay aligned with designers and with other libraries.
A list screen then becomes a small mapping problem:
One trap worth calling out: FlatList throws if you change numColumns on the fly, so you must pass the column count through key to force a remount. Fold/unfold transitions can trigger this remount repeatedly, so on screens where scroll position matters I also restore it via initialScrollIndex across the transition.
Verification Without Owning a Foldable
Not buying a foldable just to test is, frankly, the indie developer's honest preference. The following routine got me essentially all the way there:
Create a Resizable device. In Android Studio's Device Manager, the "Resizable" profile lets you switch between phone, foldable, and tablet shapes from the running emulator's toolbar
Replay fold and unfold. The same emulator's fold/unfold button exercises the dimension-change events and re-layout while the app stays alive
Drag-resize in a desktop window. Continuously resize the window across the 600dp and 840dp boundaries and confirm the layout crosses thresholds in both directions without breaking
Rotate through every screen. Once the lock is gone, landscape variants of screens you never designed for become reachable. Walk all of them once
This routine surfaced exactly four issues in my apps: a splash image stretched in landscape (fixed with contain sizing), modals growing absurdly tall on wide screens (capped at 560dp max width), keyboard covering inputs (revisited softwareKeyboardLayoutMode), and the FlatList column error above. Each fix took well under half a day — but every one of them would have shipped broken without this pass.
My Suggestion — Do One Full Pass Before the Deadline Does It for You
Android 17 is expected to roll out to Pixel devices first this summer, but nothing about the preparation requires waiting for the OS. The resizable emulator, the size-class refactor, the per-screen locks — all of it runs in today's tooling.
Across my six apps the budget worked out to: 10 minutes for the impact assessment, half a day for app.json and per-screen lock rework, one to two days for size classes and layout fixes, and half a day for verification. At most three days per app to turn the tablet and foldable experience from "visibly broken" into "actually uses the screen" strikes me as a clearly worthwhile trade.
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.