Awalim Groupعوالِم قروب

Interface engineering · Mobile3 min read

Flutter and Apple's standards: building an experience at the level of official iOS

The differences a user notices without naming them: motion curves, scroll bounce and touch timing — and where they come from when they are not native.

By Awalim mobile team

An iPhone user does not say «this app is not native». They say «something feels off» and delete it. That something is usually one of five details that can be measured — and all of them are fixable in Flutter if you know where to look.

1. Motion curves

Screen transitions in iOS use a spring curve with a specific damping, and menus open on a different curve than buttons. Flutter, by default, animates most things with Material curves, and that is the first thing that feels wrong to an iPhone user.

// Between screens: CupertinoPageRoute, not MaterialPageRoute
Navigator.of(context).push(
  CupertinoPageRoute(builder: (_) => const DetailsScreen()),
);

// Inside a screen: a soft deceleration instead of a symmetric easeInOut
AnimatedContainer(
  duration: const Duration(milliseconds: 350),
  curve: Curves.easeOutCubic,
  // ...
);

2. Scroll bounce

Lists in iOS bounce at the edge and decelerate with a specific friction coefficient. Flutter applies BouncingScrollPhysics on iOS automatically; the trouble starts when someone forces ClampingScrollPhysics on a single list, or builds on one platform and assumes the other behaves the same. Leave the physics to the platform, and only override it for a written reason.

3. Touch timing

A button in iOS gives feedback by dimming, not with a ripple, and cancels if the finger leaves it before release. CupertinoButton does this; ElevatedButton draws a Material ripple. Both fire on release, but they feel completely different, and the difference shows in the first second of use.

4. Typography and Arabic letterforms

SF Pro is the system font and Flutter cannot ship it. But using .SF Pro Text through the platform's default font family works on iOS. Arabic, though, needs a font you ship yourself — and we use IBM Plex Sans Arabic at its real weights, not one weight faked with a stroke.

  • Never apply letterSpacing to Arabic text — it severs the joins between letters
  • A taller line height for Arabic (1.6 and up), because diacritics and extenders need the room
  • Tabular figures (tabularFigures) in any column of numbers

5. Safe areas and direction

An Arabic screen mirrors: back is on the right, and drawers pull from the right. Flutter mirrors automatically if you use EdgeInsetsDirectional and AlignmentDirectional — and breaks the app if you use explicit left/right. The rule: no word «left» or «right» in the code without a written reason.

A native app is not the one that uses the system's widgets, but the one that behaves the way the system's user expects — on the first touch, the first scroll, and the first transition.

In short

Flutter is capable of an experience at the level of official iOS, but it does not hand it to you by default. Five decisions — the curve, the physics, the touch, the typography, the direction — are taken once at the root of the app, and everything after inherits the right feel.

Next step

Have a specific engineering question?

Sometimes one short call saves weeks on the wrong path.

  • We reply within two working days
  • The code is entirely yours
  • Published numbers, signed and verifiable