1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Flutter-8.md 14 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 10.03.2025 00:06 5767d61

Как восьмую статью серии, эта статья рассказывает о полезных советах при разработке с использованием Flutter, чтобы помочь вам избежать распространённых ошибок и трудностей. Вся статья представляет собой концентрированный набор практических рекомендаций, который дополняется практическими примерами.

Ссылка на статью:

Полный гайд по Flutter

Специальные статьи о мире Flutter

1. Эффект свойства TextOverflow.ellipsis для Text не работает

Иногда вы задаете свойство ellipsis для компонента Text, но эффект от этого не проявляется, вместо этого вы видите предупреждение "overflowed", как показано на следующем рисунке слева.

На самом деле большинство случаев связано с тем, что внутренний метод RenderParagraph проверяет условие final bool didOverflowWidth = size.width < textSize.width;. Когда значения size.width и textSize.width равны, это приводит к тому, что свойство ellipsis не применяется.

Поэтому вам следует ограничить размер компонента Text путём помещения его в контейнер типа Container или использование сочетания Row и Expanded для установки границ для вашего Text. Если вы не знаете, какой размер выбрать, можно воспользоваться LayoutBuilder.

2. Получение размера и положения компонентаЕсли вы читали шестую статью этой серии, то должны знать, что можно использовать ключ GlobalKey для получения объекта BuildContext компонента. Мы также говорили ранее, что BuildContext реализуется через Element, а Element хранит RenderObject. Таким образом, когда мы получаем RenderObject, на самом деле мы получаем RenderBox. Используя RenderBox, мы можем получить размер и положение компонента:

showSizes() {
  RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
  print(renderBoxRed.size);
}
``````markdown
### 3\. Получение высоты области состояния и безопасной разметки

Если вы изучили исходный код `MaterialApp`, вы заметили бы, что внутри него находится `WidgetsApp`, который содержит `MediaQuery`. Те, кто знаком с этим компонентом, могут использовать `MediaQuery.of(context).size` для получения размера экрана.

`MediaQuery` является типом `InheritedWidget`, который имеет параметр `MediaQueryData`, который устанавливается следующим образом. Изучив исходный код, мы узнали, что обычно значение поля `top` параметра `padding` в `MediaQueryData` равно высоте области состояния. Поэтому мы можем получить высоту области состояния через `MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top`, а иногда может потребоваться рассмотреть параметр `viewInsets`.

![](http://img.cdn.guoshuyu.cn/bk/Flutter-8/image2)

Что касается высоты компонента `AppBar`, то по умолчанию она равна `Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0))`, где `kToolbarHeight`  это константное значение. Конечно, вы можете использовать реализацию `PreferredSizeWidget` для кастомизации `AppBar`.

Вы также можете заметить, что иногда при размещении элементов происходит смещение расчёта от области состояния вверх. В этом случае вам следует использовать `SafeArea` для обёртки. Причины этого можно найти в исходном коде, где используется `MediaQueryData`.
```### 4. Установка цвета области состояния и цвета значков

Просто используйте свойство `brightness` компонента `AppBar` или `ThemeData` для установки цвета области состояния.

Однако если вы не хотите использовать `AppBar`, вы можете обернуть его в `AnnotatedRegion<SystemUiOverlayStyle>`, чтобы установить стиль области состояния. Через `SystemUiOverlayStyle` вы сможете быстро настроить внешний вид области состояния и нижней навигационной панели.

Кроме того, вы можете использовать `SystemChrome.setSystemUIOverlayStyle` для установки стилей, но только если вы не используете `AppBar`. **Важно отметить, что все изменения стиля области состояния являются глобальными**, поэтому если вы установите стиль на странице A, он будет применяться автоматически на странице B, если там нет других настроек или использования `AppBar`.

### 5. Системное масштабирование шрифтов

Современные телефоны обычно предоставляют возможность масштабировать шрифты, что усложняет адаптивность приложений. Поэтому большинство разработчиков предпочитает запрещать масштабирование шрифтов в своих приложениях.

Масштабирование шрифтов в Flutter связано с параметром `textScaleFactor` объекта `MediaQueryData`. Поэтому вы можете использовать следующий код для установки шрифтов так, чтобы они не масштабировались:

```dart
MediaQuery(
  data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: 1),
  child: new Container(),
);
```### 6. Отступы и поля

При использовании контейнера `Container` часто используют параметры `margin` и `padding`. Мы уже говорили ранее, что `Container` является просто обёрткой различных типов размещения, где внутренние параметры `margin` и `padding` реализуются через `Padding`. Однако `Padding` не поддерживает отрицательные значения, поэтому рекомендуется использовать `Transform`, если вам нужны такие значения.

```dart
Transform(
    transform: Matrix4.translationValues(10, -10, 0),
    child: Container(),
);

7. Обрезка углов компонентов

В повседневной разработке мы обычно используем два способа создания закругленных углов:

  • Один из них реализуется с помощью класса BoxDecoration, который является частью интерфейса Decoration.
  • Второй метод использует компонент ClipRRect.

Класс BoxDecoration обычно применяется в компонентах DecoratedBox и Container. Этот подход обычно приводит к непосредственному отрисовыванию канваса для текущего компонента, что позволяет создать закругленные углы для фона, но это не влияет на его потомков (children). Это значит, что если ваш потомок — это изображение или имеет свой фон, эффект закругленных углов может быть потерян.

С другой стороны, компонент ClipRRect действительно влияет на потомков. Это можно понять из следующего источника кода рендера объекта.

Изображение

8. PageViewЕсли вы используете TabBarView вместе с KeepAlive, то я рекомендую вам использовать PageView. На данный момент, до версии 1.2, при использовании KeepAlive, переход между двумя и более страницами через TabBarView приводит к вызову методов dispose и initState для каждой страницы. Хотя внутри TabBarView используется комбинация PageView и TabBar.

Вы можете использовать комбинацию PageView и TabBar напрямую, а также использовать _pageController.jumpTo(MediaQuery.of(context).size.width * index) для перехода между страницами, чтобы избежать некоторых проблем. Однако это будет означать потерю анимационного эффекта. В действительности, TabBarView представляет собой просто обёртку над PageView и TabBar.

Кроме того, существует второй подход, который использует PageStorageKey для хранения состояния страниц. Однако, поскольку этот метод основан на "сохранении и восстановлении значений", каждый раз при переходе между страницами будут вызываться методы dispose и initState.

return Scaffold(
    key: PageStorageKey<String>('your_value'),
);

9. Ленивая загрузка данных

В Flutter ленивая загрузка данных может быть легко реализована с помощью FutureBuilder или StreamBuilder. Эти компоненты позволяют асинхронно получать данные через future или stream, после чего данные могут быть загружены с помощью AsyncSnapshot.data. Подробнее о потоках и асинхронных операциях можно узнать позже.### 10. Возврат на главный экран Android устройства

Официальный плагин Flutter android_intent предлагает простое решение для возврата на главный экран устройства:

import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter/material.dart';
import 'package:android_intent/android_intent.dart';

void main() {
  runApp(MaterialApp(home: Home()));
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: RaisedButton(
            onPressed: () async {
              final intent = AndroidIntent(action: 'android.intent.action.MAIN');
              await intent.start();
            },
            child: Text('Возврат на главный экран')));
  }
}
Future<bool> _диалогВыходИзПриложения(BuildContext context) async {
    if (Platform.isAndroid) {
      AndroidIntent intent = AndroidIntent(
        action: 'android.intent.action.MAIN',
        category: "android.intent.category.HOME",
      );
      await intent.launch();
    }

    return Future.value(false);
  }
return WillPopScope(
      onWillPop: () {
        return _диалогВыходИзПриложения(context);
      },
      child: xxx);

Наконец, восьмая статья завершена! (///▽///)

Рекомендованные ресурсы

Рекомендованные полные открытые проекты:

Увидимся ли мы снова?

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/CarGuo-GSYFlutterBook.git
git@api.gitlife.ru:oschina-mirror/CarGuo-GSYFlutterBook.git
oschina-mirror
CarGuo-GSYFlutterBook
CarGuo-GSYFlutterBook
master