Чисто перекрывающие части темы локально во Флаттере - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть виджет, который имеет два TextField s в качестве потомков. Я хотел бы применить тот же стиль к этим TextField с. Насколько я понимаю, правильный способ сделать это - применить локализованную тему к моему дереву виджетов. Следующее - моя попытка. Это фрагмент кода из функции build моего корневого виджета. Нет ли более чистого способа сделать это?

final ThemeData _themeData = Theme.of(context);
return Theme( // HACK
  data: _themeData.copyWith(
    inputDecorationTheme: InputDecorationTheme(
      border: OutlineInputBorder(),
    ),
    textTheme: _themeData.textTheme.copyWith(
      subhead: _themeData.textTheme.subhead.copyWith(
        fontSize: 30.0,
      ),
    ),
  ),
  child: _buildTheRestOfMyWidgetTree(context),
);

Меня раздражает то, что для переопределения одного свойства (_themeData.textTheme.subhead.fontSize) я должен явно и вручную сделать копии трех промежуточных структур данных (_themeData, затем _themeData.textTheme, затем _themeData.textTheme.subhead ).

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Несмотря на то, что я могу понять разочарование необходимости «копировать» все, это то, как вы должны это делать.

Данные неизменны во Flutter.Вы не можете изменять их, вы вынуждены клонировать их с другими свойствами.

Поэтому ваше предположение верно: если вы хотите изменить вложенное свойство, вы должны также клонировать всех его родителей.Что приводит к:

final ThemeData theme = Theme.of(context);
theme.copyWith(
  textTheme: theme.textTheme.copyWith(
    subhead: theme.textTheme.subhead.copyWith(
      fontSize: 30.0,
    ),
  ),
);

Опять же: вы не можете избежать этого.

0 голосов
/ 22 сентября 2018

Было бы полезно, если бы вы упаковали эту часть кода и сделали ее виджетом, чтобы ваше дерево было чище. Вот как это делается в этом примере .

class TextFieldOverride extends StatelessWidget {
  const TextFieldOverride({this.child});
  final Widget child;
  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context);
    return Theme(
      child: child,
      data: themeData.copyWith(
        inputDecorationTheme: InputDecorationTheme(
          border: OutlineInputBorder()),
      textTheme: themeData.textTheme.copyWith(
        subhead: themeData.textTheme.subhead.copyWith(
          fontSize: 30.0))));
  }
}

...

TextFieldOverride(
  child: TextField(...)
)

Или, если в нескольких местах код будет продублирован, вы можете просто внести изменения напрямую:

...
child: TextField(
  style: Theme.of(context).textTheme.subhead.copyWith(fontSize: 30.0),
  decoration: InputDecoration(border: OutlineInputBorder(),
    ...
  )
)

Или, возможно, лучший выбор - создать функцию, которая будет выполнять все вышеперечисленное.

TextField buildTextField(BuildContext context) => TextField(
  style: Theme.of(context).textTheme.subhead.copyWith(fontSize: 30.0),
  decoration: InputDecoration(border: OutlineInputBorder(),
    ...
  )
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...