Можно ли использовать Material-виджеты в iOS-приложении на Flutter?

«Можно ли использовать Material-виджеты в iOS-приложении на Flutter?» — вопрос из категории UI и вёрстка, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, Material-виджеты работают на iOS, но это нарушает Apple Human Interface Guidelines (HIG) и создает неестественный пользовательский опыт для iOS-пользователей.

Пример Material-виджетов на iOS:

import 'package:flutter/material.dart';

MaterialApp(
  theme: ThemeData.light(),
  home: Scaffold(
    appBar: AppBar(
      title: Text('Material Design on iOS'),
      actions: [
        IconButton(
          icon: Icon(Icons.more_vert),
          onPressed: () {},
        ),
      ],
    ),
    body: Center(
      child: Column(
        children: [
          ElevatedButton(
            onPressed: () {},
            child: Text('Material Button'),
          ),
          Switch(
            value: true,
            onChanged: (bool value) {},
          ),
          CircularProgressIndicator(),
        ],
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {},
      child: Icon(Icons.add),
    ),
  ),
);

Проблемы Material Design на iOS:

  1. Визуальные различия:

    • Material использует shadows и elevation, iOS — flat design с blurs
    • Разные типографика и spacing
    • Material buttons имеют ripple effect, iOS — highlight
  2. Навигационные паттерны:

    • Material: hamburger menu, tabs сверху
    • iOS: tab bar снизу, navigation bar сверху
    • Разные жесты для возврата
  3. Компоненты:

    • Material dialogs vs. iOS alerts
    • Material snackbars vs. iOS toasts
    • Разные pickers и date selectors

Когда Material допустим на iOS:

// 1. Корпоративные/инструментальные приложения
Material(
  elevation: 4,
  borderRadius: BorderRadius.circular(8),
  child: Container(
    padding: EdgeInsets.all(16),
    child: Text('Инструментальный интерфейс'),
  ),
);

// 2. Приложения с сильным брендингом
Theme(
  data: ThemeData(
    primaryColor: BrandColors.primary,
    buttonTheme: ButtonThemeData(/* кастомный стиль */),
  ),
  child: MaterialWidget(),
);

// 3. Прототипы и MVP

Лучшие практики для iOS-приложений:

// 1. Использование Cupertino-виджетов
CupertinoApp(
  theme: CupertinoThemeData(
    primaryColor: CupertinoColors.systemBlue,
  ),
  home: CupertinoPageScaffold(
    navigationBar: CupertinoNavigationBar(
      middle: Text('Нативный iOS'),
    ),
    child: SafeArea(
      child: ListView.builder(
        itemBuilder: (context, index) => CupertinoListTile(
          title: Text('Item $index'),
          onTap: () {},
        ),
      ),
    ),
  ),
);

// 2. Адаптивные компоненты
Widget buildPlatformButton() {
  if (Theme.of(context).platform == TargetPlatform.iOS) {
    return CupertinoButton.filled(
      onPressed: () {},
      child: Text('iOS Button'),
    );
  } else {
    return ElevatedButton(
      onPressed: () {},
      child: Text('Android Button'),
    );
  }
}

// 3. Пакет platform_widgets для упрощения
PlatformWidget(
  android: (context) => MaterialWidget(),
  ios: (context) => CupertinoWidget(),
);

Для production iOS-приложений рекомендуется использовать Cupertino-виджеты или реализовывать адаптивный UI, который соответствует ожиданиям пользователей каждой платформы.