Как не «сломать» вёрстку Flutter-приложения из-за textScaleFactor

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Однажды я установил приложение по текущему проекту на свой смартфон и заметил, что на некоторых экранах изменилась вёрстка: «поехало» отображение текста, хотя при работе с эмулятором всё было нормально. 

Меня зовут Даниль Галимзянов, я начинающий Flutter-разработчик в компании Surf. Разобрался, в чём причина проблемы с вёрсткой текста, и хочу поделиться с вами.

Проблема наглядно

Давайте посмотрим на код виджета MyWidget из этого gist в DartPad. 

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double _deviceTsf = 1.0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      builder: (context, child) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(textScaleFactor: _deviceTsf),
          child: child ?? const SizedBox.shrink(),
        );
      },
      home: Scaffold(
        appBar: AppBar(
          title: Text(
            'Text Scale Factor на устройстве = $_deviceTsf',
            textScaleFactor: 1.0,
          ),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const SizedBox(height: 40),
              const Text(
                'Типа настройки размера шрифта в Accessibility',
                textScaleFactor: 1.0,
              ),
              Slider(
                value: _deviceTsf,
                min: 0.85,
                max: 1.3,
                divisions: 3,
                onChanged: (value) {
                  setState(() {
                    _deviceTsf = value;
                  });
                },
              ),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 10),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: const [
                    Text('0.85', textScaleFactor: 1.0),
                    Text('1.00', textScaleFactor: 1.0),
                    Text('1.15', textScaleFactor: 1.0),
                    Text('1.30', textScaleFactor: 1.0),
                  ],
                ),
              ),
              Flexible(child: MyWidget(deviceTsf: _deviceTsf)),
            ],
          ),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  final double deviceTsf;
  const MyWidget({required this.deviceTsf, super.key});

  @override
  Widget build(BuildContext context) {
    const defaultTextSize = 25;
    final defaultTextStyle = TextStyle(
      fontSize: defaultTextSize.toDouble(),
      color: Colors.black,
    );
    const additionalTextSpans = <TextSpan>[
      TextSpan(
        text: ' widget ',
        style: TextStyle(fontStyle: FontStyle.italic),
      ),
      TextSpan(
        text: '- size $defaultTextSize',
        style: TextStyle(fontWeight: FontWeight.bold),
      )
    ];

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          'Text widget - size $defaultTextSize',
          textAlign: TextAlign.center,
          style: defaultTextStyle, // Заданный стиль текста высотой 25
        ),
        const SizedBox(height: 20),
        Text.rich(
          textAlign: TextAlign.center,
          TextSpan(
            text: 'Text.rich',
            style: defaultTextStyle, // Заданный стиль текста высотой 25
            children: additionalTextSpans,
          ),
        ),
        const SizedBox(height: 20),
        RichText(
          textAlign: TextAlign.center,
          text: TextSpan(
            text: 'RichText',
            style: defaultTextStyle, // Заданный стиль текста высотой 25
            children: additionalTextSpans,
          ),
        ),
        const SizedBox(height: 20),
        Text(
          deviceTsf != 1 ? '						
Источник: https://habr.com/ru/company/surfstudio/blog/720098/


Интересные статьи

Интересные статьи

На Хабре ни для кого не секрет, что в текущей повестке практически все сферы частного бизнеса вынуждены реагировать на происходящие изменения. Большое количество привычных всем нам зарубежных сервисов...
Представьте, каково это — найти серьёзный баг в продакшене сразу после выпуска игры. Представьте, что этот баг вредит только платным пользователям. Представьте, что игра зависает сразу после того, к...
Привет! Меня зовут Саша Шутай, я тимлид в AGIMA. В прошлой статье я рассказывал, что делать, если на проекте Bitrix сожительствует с Vue.js и поисковые боты не видят контента сайта. А в этой помогу ра...
Еще неделю назад эксперты “Яндекс.Маркет Аналитика” сообщили о том, что заметили резкий всплеск спроса на жесткие диски и накопители в отечественном ритейле. Новость не н...
2 недели назад в публичном трекере компании GitLab, стоящей за популярным одноимённым Open Source-решением для разработчиков и DevOps-инженеров, появился issue под названием «WIP: блокировка ...