/ mobile_app_design
MOBILE_APPiOS and Android Are Different Systems, Not One Design Reused Twice
Where HIG and Material genuinely diverge: navigation, back behavior, type defaults, and which components need two designs, not one resized.
On this page
- The shared-Figma-file trap
- Two philosophies of navigation
- Back is two systems, not one gesture
- Typography is a contract, not a shared scale
- Same problem, two different adaptive answers
- Sheets, dialogs, and the gesture grammar around them
- Touch targets and safe areas aren't interchangeable units
- Depth: shadows vs. glass
- 2025 reset the gap: Liquid Glass vs. Material 3 Expressive
- What can actually share a design
- Common mistakes
- The spec
03Back is two systems, not one gesture
This is the single biggest structural gap between the two platforms, and it's almost entirely invisible in a static mockup, because it's not about how the back affordance looks — it's about who owns it.
On iOS, the back affordance is
component-owned. It's the leading button of
UINavigationBar, automatically labeled with the
previous screen's title unless a developer overrides it, and
it's paired with a system-provided edge-swipe-from-the-left
shortcut that's wired to that exact same pop action. There
is no operating-system-level "back" primitive on iOS. If a
screen isn't hosted inside a navigation controller, swiping
from the left edge does nothing at all, because nothing is
listening for it. Leaving the app is a categorically
different gesture that has no relationship to any
navigation stack.
On Android, back is dispatched by the system to whatever currently owns the screen — an open keyboard, a modal dialog, a bottom sheet, a fragment's own nested back stack, the hosting activity, and, if nothing along that chain intercepts it, all the way out to the home screen. That's a fundamentally different mental model to design against: on Android, every screen state has to answer "what does back do right here," because the same physical gesture routes through all of them. On iOS the question mostly doesn't come up, because navigation-stack pop and app-exit are different gestures with different owners.
The mechanics of that Android gesture have also been changing on a yearly cadence, which matters because a design spec written against last year's behavior can be quietly wrong today:
| Version | What changed |
|---|---|
| 13 (API 33) | Introduces a predictive back-to-home preview when exiting an app. |
| 14 (API 34) | Adds in-app predictive back — the previous destination previews mid-swipe, and the user can cancel before committing. |
| 15 (API 35) | Predictive back's developer-option toggle is removed; enabled by default for apps that have migrated. Edge-to-edge layout is enforced by default for apps targeting this level. |
| 16 (API 36) | Remaining opt-outs for predictive-back animations and edge-to-edge enforcement are deprecated for apps targeting this level. |
The practical consequence: for every Android screen that holds unsaved state — a half-filled form, an open bottom sheet, a nested flow — the design has to explicitly define what back does at each layer, because the platform fires that event by default whether or not anyone designed for it. An iOS screen with no navigation controller behind it simply never receives an unhandled back event in the first place.
04Typography is a contract, not a shared scale
iOS's type system is eleven named text styles — Large Title, Title 1, Title 2, Title 3, Headline, Body, Callout, Subhead, Footnote, Caption 1, Caption 2 — each with a fixed default point size and line height, all drawn from SF Pro. Every one of those styles scales along Dynamic Type's twelve steps: seven standard sizes from xSmall to xxxLarge, plus five larger accessibility sizes, AX1 through AX5. What changes app to app is which of the eleven named roles gets used where — the letterforms themselves are locked to a single system typeface.
Material 3's type system is organized differently: five roles — display, headline, title, body, label — each in three sizes, large/medium/small, for fifteen tokens total, built on Roboto Flex by default. The meaningful structural difference isn't the token count, though — it's that Material explicitly splits a "brand" typeface (used for display and headline) from a "plain" typeface (used for title, body, and label), making a per-brand typeface swap a supported, first-class customization rather than a workaround. SF Pro has no equivalent split; the system typeface is the typeface, by design.
Lining the two scales up by nearest point size is a useful exercise precisely because it shows why the naive version of this — copy the number, keep the role name — doesn't work:
| iOS text style | Size / weight | Nearest Material 3 token | Size / weight |
|---|---|---|---|
| Large Title | 34pt regular | Display Small | 36sp regular |
| Title 1 | 28pt regular | Headline Medium | 28sp regular |
| Title 2 | 22pt regular | Title Large | 22sp regular |
| Headline | 17pt semibold | Title Medium | 16sp medium |
| Body | 17pt regular | Body Large | 16sp regular |
| Caption 1 | 12pt regular | Body Small / Label Medium | 12sp (tie) |
Two things fall out of that table that don't fall out of either spec sheet on its own. First, iOS separates Headline from Body almost entirely by weight — both sit at 17pt, and semibold is the only thing distinguishing them — while Material separates its comparable tier partly by size and partly by weight, so a same-named role doesn't land on a same-sized token. Second, at the small end the nearest-size match is a genuine tie between two different Material roles with different jobs (a body token and a label token), which is a sign the two scales weren't built to line up in the first place — they were each built to fit their own platform's density of named roles.
Worth knowing
17pt and 17sp aren't the same physical size, either.
Android's sp unit is a density-independent
pixel additionally scaled by the user's system font-size
preference — so identical numbers don't render
identically even before any accessibility scaling is
applied on either platform. Treat a hand-off spec as two
scales to re-derive role by role, not one set of numbers
to transliterate.
06Sheets, dialogs, and the gesture grammar around them
iOS sheets — partial- or full-height, with a grabber at the top — dismiss with a discrete swipe-down gesture that's independent of the edge-swipe-back gesture. The two never compete for the same touch input, so a sheet can safely stack on top of a screen that also supports edge-swipe-back without any gesture conflict between them.
Android's bottom sheets, side sheets, and navigation drawers automatically animate with the predictive back gesture once an app has opted in and is running on API 33+. That's good for consistency, but it means the exact same edge-swipe that navigates a screen up a level is also the gesture that dismisses a modal sheet — a sheet's dismiss affordance and the screen's "go back" affordance are the same physical gesture on Android, where they're deliberately different gestures on iOS.
Common misconception
There's a long-repeated claim that iOS orders dialog buttons Cancel-then-OK left-to-right while Android orders them the other way around. Current guidance for both platforms has mostly converged: modern HIG says to place the button people are most likely to choose on the trailing edge — so a destructive "Delete" sits to the right of "Cancel" — and Material's own dialog guidance places the dismissive action directly to the left of the affirmative one, the same left-to-right order. Don't design around a button-order split that mostly isn't there anymore. What still genuinely differs is styling — iOS colors a destructive action's text red; Material routes it through its own error color role — and how tap-outside-to-dismiss defaults behave per dialog type.
07Touch targets and safe areas aren't interchangeable units
iOS's minimum touch target is 44×44 points. Material's is 48×48dp, though WCAG's own Success Criterion 2.5.8 (Level AA) sets a lower absolute floor of 24×24dp, with the stricter Level AAA criterion, 2.5.5, landing at 44×44 — the same number as Apple's baseline, and a lower bar than Material's own recommendation.
A point and a density-independent pixel are not the same
physical measurement, and treating them as unit-convertible
is a quiet source of drift between platform specs. Android's
dp has a published formula: it's anchored to a
160dpi reference density, applied uniformly across a
documented set of density buckets, so
px = dp × (dpi ÷ 160) everywhere. Apple's point
has never had an equivalent public per-inch formula — it's
a lookup table Apple maintains per device model, where each
device is simply assigned a pixel scale factor (@1x, @2x,
@3x), not a value derived from a universal density formula.
Don't assume 44pt and 48dp are the same size scaled by a
fixed ratio; treat each as its own platform's independently
tuned constant, verified against real devices.
Safe areas follow the same pattern of "similar problem,
different mechanism." iOS exposes safe-area insets around
the home indicator, notch or Dynamic Island, and rounded
corners, opted into with viewport-fit=cover
and respected with the environment variable:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
.bottom-bar {
padding-bottom: max(12px, env(safe-area-inset-bottom));
}
Android's model went from opt-in to enforced: apps targeting Android 15 (API 35) get edge-to-edge layout by default, with content expected to draw behind the system bars and use the platform's window-insets APIs to avoid placing touch targets under the gesture-navigation zones — not just the top and bottom bars, but the left and right edges too, since that's exactly where the back gesture lives. The previous opt-out attribute is deprecated for apps targeting Android 16. A control pinned flush to either screen edge on a modern Android build isn't just a reachability problem the way it would be on iOS — it's sitting directly in a zone the system gesture already claims.
08Depth: shadows vs. glass
Material's elevation model pairs a soft drawn shadow with a tonal surface-color shift — a translucent wash of the primary color layered over the surface, so higher elevation reads as more tinted, not just less flat. That tonal approach exists specifically because a drawn shadow barely registers in dark theme; the color shift keeps elevation legible even where a shadow alone would disappear.
iOS has historically leaned on blur-based materials and vibrancy instead of a drawn-shadow elevation ladder — the frosted-glass tab bar background is the clearest everyday example. Liquid Glass (2025) pushes that further into an explicitly lensing, refractive material that simulates real glass optics — bending and magnifying whatever sits behind it, with a springy deformation on interaction — a genuinely different physical metaphor from Material's flat, tonal surfaces.
The practical consequence: expressing "this card is elevated" with one drawn box-shadow token on both platforms isn't actually matched. On Android that's incomplete without the tonal shift, especially in dark theme; on iOS, a raised surface in current default styling more likely wants a translucent or vibrancy treatment than a shadow at all.
092025 reset the gap: Liquid Glass vs. Material 3 Expressive
Both redesigns landed within a few months of each other and pull in opposite directions. Liquid Glass — announced by Apple's VP of Human Interface Design, Alan Dye, at WWDC on June 9, 2025, and shipped across the "26" generation of Apple's platforms that fall — emphasizes restraint and depth through translucency and refraction, drawing on visionOS's spatial visual language, and deliberately pulls emphasis toward the content underneath the UI chrome rather than the chrome itself.
Material 3 Expressive — announced at Google I/O on May 13, 2025 and rolled out through Android 16 QPR1 that September — leans the opposite way: bolder, more saturated color, springier motion curves, and shape used expressively, with components that morph rather than just resize, aimed at adding emotional warmth and personality rather than restraint.
Neither direction is more correct than the other — they're two different bets about what a mobile interface should feel like in the mid-2020s. What matters for a working designer is narrower: any shared token layer — shadow values, corner radii, translucency levels — that was "close enough" to bridge both platforms during the flat- design decade needs re-examining now, because the assumption of a shared visual baseline underneath brand styling is weaker than it's been in years.
11Common mistakes
- Designing the iOS screen first, then "porting" it to Android by swapping the typeface and rounding the corners, without re-deriving the type scale or the navigation model underneath.
- Treating 44pt and 48dp as unit-convertible instead of as two independently tuned platform constants.
- Shipping a custom in-app back button on Android without also wiring it to the system's predictive-back callback, producing two different "back" behaviors half a swipe apart.
- Placing an interactive control flush against the left or right screen edge on a modern Android build without accounting for the gesture-inset zone the back gesture already claims there.
- Assuming a tab bar and a navigation bar can share one component with a class swap, when their adaptive behavior at larger widths — sidebar vs. rail or drawer — diverges completely.
12The spec
// platform_defaults.spec
- iOS min touch target
- 44×44pt
- Android min touch target
- 48×48dp (WCAG AA floor: 24×24dp)
- iOS tab bar
- 49pt tall, 3–5 tabs, edge-swipe-back is left only
- Android nav bar
- ~80dp container, 3–5 destinations, back gesture works from either edge
- iOS Dynamic Type
- 11 named text styles across 7 standard + 5 accessibility sizes
- Material type scale
- 15 tokens — 5 roles × 3 sizes
- Android back gesture
- Predictive preview since API 34; default-on, no dev toggle, since API 35
- 2025 visual reset
- Liquid Glass (iOS 26) vs. Material 3 Expressive (Android 16 QPR1)
- Validate on
- Real devices, both platforms, default OS gesture navigation enabled
None of these numbers are permanent — Android alone has changed its back-gesture defaults in three of the last four annual releases, and both platforms just reset their visual language in the same year. Treat this spec as a snapshot worth re-checking against the current OS release, not a constant. What doesn't change from release to release is the underlying shape of the problem: iOS's navigation is component-owned and Android's is system-dispatched, and that one structural fact is why a screen "resized" from one platform to the other keeps quietly breaking in the same places.