Кнопки Flutter: ElevatedButton вместо RaisedButton, TextButton, FilledButton

Егор Долгов · 10.11.2026
Chrome
localhost
Кнопки
FilledButton
ElevatedButton
OutlinedButton
TextButton
onPressed: () { … }
Показать по шагам
Субтитры
Во Flutter пять видов кнопок Material Design. Они различаются заметностью, а нажатие у всех задаётся одинаково — функцией в onPressed.

Кнопки Material Design во Flutter — FilledButton , ElevatedButton , OutlinedButton , TextButton и IconButton . Они различаются заметностью на экране, а действие по нажатию у всех задаётся одинаково — функцией в onPressed . Все примеры — в Material 3: эта версия дизайна во Flutter включена по умолчанию.

Если вы ищете RaisedButton или FlatButton : их заменили — RaisedButton → ElevatedButton , FlatButton → TextButton , OutlineButton → OutlinedButton . Пример «было → стало», версии и замена ButtonTheme — в разделе 6.

Содержание:

  1. Какую кнопку выбрать
  2. Минимальный пример
  3. Основные параметры
  4. Примеры: неактивная кнопка, значок, размер
  5. Свой стиль: styleFrom и тема
  6. Чем заменить RaisedButton, FlatButton, OutlineButton и ButtonTheme
  7. Частые ошибки

1. Какую кнопку выбрать

По документации Flutter:

  • FilledButton — самая заметная из этих кнопок, для главного действия, которое завершает шаг: «Сохранить», «Подтвердить». Заметнее неё только FloatingActionButton — круглая плавающая кнопка в углу экрана.
  • FilledButton.tonal — промежуточный вариант между FilledButton и OutlinedButton : залит дополнительным, более спокойным цветом темы — заметнее кнопки с рамкой, но тише залитой. Например, «Далее».
  • ElevatedButton — приподнятая кнопка с тенью. Нужна, чтобы добавить объём плоскому макету, например в длинном списке. Не ставьте её на приподнятые элементы: диалоги и карточки.
  • OutlinedButton — кнопка с рамкой: для важного, но не главного действия.
  • TextButton — кнопка без рамки: на панелях, в диалогах, рядом с текстом. Не ставьте её туда, где она сольётся с содержимым, например посреди списка.
  • IconButton — кнопка-значок, часто в шапке приложения ( AppBar.actions ).

2. Минимальный пример

Пять видов кнопок и вариант FilledButton.tonal на одном экране:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Кнопки')),
        body: const Center(child: ButtonsDemo()),
      ),
    );
  }
}

class ButtonsDemo extends StatelessWidget {
  const ButtonsDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        FilledButton(onPressed: () {}, child: const Text('FilledButton')),
        FilledButton.tonal(
          onPressed: () {},
          child: const Text('FilledButton.tonal'),
        ),
        ElevatedButton(onPressed: () {}, child: const Text('ElevatedButton')),
        OutlinedButton(onPressed: () {}, child: const Text('OutlinedButton')),
        TextButton(onPressed: () {}, child: const Text('TextButton')),
        IconButton(onPressed: () {}, icon: const Icon(Icons.favorite_border)),
      ],
    );
  }
}

На экране — столбец из шести кнопок по центру, между ними по 12 пикселей ( spacing: 12 ).

3. Основные параметры

Общие параметры FilledButton , ElevatedButton , OutlinedButton и TextButton :

  • onPressed ( VoidCallback? ) — функция, которую кнопка вызовет при нажатии.
  • onLongPress ( VoidCallback? ) — функция для долгого нажатия.
  • child ( Widget? ) — что на кнопке, обычно Text . Передавать обязательно.
  • style ( ButtonStyle? ) — вид кнопки: цвета, отступы, размер, форма (раздел 5).

VoidCallback — функция без параметров, которая ничего не возвращает, например () { … } . Знак ? после типа значит, что вместо значения можно передать null . У IconButton вместо child — обязательный icon .

4. Примеры: неактивная кнопка, значок, размер

Как сделать кнопку неактивной, добавить значок и долгое нажатие

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: Variants())),
    ),
  );
}

class Variants extends StatelessWidget {
  const Variants({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        // Неактивная кнопка: onPressed и onLongPress равны null.
        const ElevatedButton(onPressed: null, child: Text('Недоступна')),
        // Кнопка со значком.
        FilledButton.icon(
          onPressed: () {},
          icon: const Icon(Icons.send),
          label: const Text('Отправить'),
        ),
        // Долгое нажатие.
        TextButton(
          onPressed: () {},
          onLongPress: () {},
          child: const Text('Нажмите и держите'),
        ),
        // Варианты IconButton.
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
            IconButton.filled(onPressed: () {}, icon: const Icon(Icons.add)),
            IconButton.filledTonal(
              onPressed: () {},
              icon: const Icon(Icons.add),
            ),
            IconButton.outlined(onPressed: () {}, icon: const Icon(Icons.add)),
          ],
        ),
      ],
    );
  }
}

На экране — столбец: бледная неактивная кнопка, кнопка со значком, текстовая кнопка и ряд из четырёх кнопок-значков.

  • Неактивная кнопка. Если onPressed и onLongPress равны null , кнопка выключена: не реагирует на нажатия, и Flutter рисует её приглушёнными цветами неактивного состояния. IconButton выключается одним onPressed: null .
  • Кнопка со значком. У FilledButton , ElevatedButton , OutlinedButton и TextButton есть конструктор .icon : значок — в icon , текст — в обязательном label . Для FilledButton.tonal — FilledButton.tonalIcon .
  • Долгое нажатие. onLongPress вызывается, когда кнопку нажали и держат.
  • Варианты IconButton . Кроме обычного, есть IconButton.filled , IconButton.filledTonal и IconButton.outlined — с заливкой основным цветом, с заливкой спокойным цветом и с рамкой.

Как задать размер кнопки и сделать её на всю ширину

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: Sizes())),
    ),
  );
}

class Sizes extends StatelessWidget {
  const Sizes({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        // Точный размер: 200 × 60.
        ElevatedButton(
          onPressed: () {},
          style: ElevatedButton.styleFrom(fixedSize: const Size(200, 60)),
          child: const Text('200 × 60'),
        ),
        // На всю ширину: SizedBox с бесконечной шириной.
        SizedBox(
          width: double.infinity,
          child: FilledButton(
            onPressed: () {},
            child: const Text('На всю ширину'),
          ),
        ),
      ],
    );
  }
}

На экране — кнопка 200 × 60 и под ней кнопка на всю ширину экрана.

  • fixedSize в styleFrom задаёт размер кнопки: здесь 200 × 60. Только ширину — Size.fromWidth(320) , только высоту — Size.fromHeight(100) .
  • Кнопка на всю ширину — внутри SizedBox(width: double.infinity) : SizedBox с бесконечной шириной растягивает кнопку на всю ширину, которую даёт родитель.
  • minimumSize задаёт наименьший размер: по умолчанию у ElevatedButton в Material 3 — 64 × 40.

Раньше размер задавали через ButtonTheme(minWidth:, height:) ; у новых кнопок для этого fixedSize и minimumSize .

5. Свой стиль: styleFrom и тема

Вид кнопки задаёт объект ButtonStyle в параметре style . Проще всего собрать его методом styleFrom — из цветов, отступов и размеров. Этот метод есть у каждой кнопки:

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: StyledButton())),
    ),
  );
}

class StyledButton extends StatelessWidget {
  const StyledButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {},
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.deepPurple,
        foregroundColor: Colors.white,
        padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
      ),
      child: const Text('Своя кнопка'),
    );
  }
}

На экране — фиолетовая кнопка с белым текстом и углами, скруглёнными на 8. По умолчанию края у неё полукруглые — это и меняет shape .

  • backgroundColor — цвет фона, foregroundColor — цвет текста и значка.
  • padding — внутренние отступы, shape — форма: здесь прямоугольник со скруглением 8.
  • У выключенной кнопки backgroundColor и foregroundColor не действуют — для неё есть disabledBackgroundColor и disabledForegroundColor (пример в разделе 6).

Другие параметры styleFrom — minimumSize , fixedSize , elevation , side (рамка), textStyle — описаны в справке ElevatedButton.styleFrom .

Чтобы не повторять style у каждой кнопки, задайте его в теме приложения — объекте ThemeData в параметре theme у MaterialApp . У каждого вида кнопок своё поле в ThemeData : elevatedButtonTheme , filledButtonTheme , outlinedButtonTheme , textButtonTheme , iconButtonTheme . В поле передаётся объект …ThemeData , например ElevatedButtonThemeData :

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData(
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(minimumSize: const Size(200, 48)),
        ),
      ),
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {},
            child: const Text('Размер из темы'),
          ),
        ),
      ),
    ),
  );
}

Теперь у всех ElevatedButton в приложении минимальный размер — 200 × 48.

6. Чем заменить RaisedButton, FlatButton, OutlineButton и ButtonTheme

Замены — из руководства по миграции :

  • RaisedButton → ElevatedButton ; тема: elevatedButtonTheme: ElevatedButtonThemeData(…)
  • FlatButton → TextButton ; тема: textButtonTheme: TextButtonThemeData(…)
  • OutlineButton → OutlinedButton ; тема: outlinedButtonTheme: OutlinedButtonThemeData(…)

Параметры цвета старых кнопок ( color , textColor ) переехали в styleFrom :

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: SaveButton(enabled: true))),
    ),
  );
}

class SaveButton extends StatelessWidget {
  const SaveButton({super.key, required this.enabled});

  final bool enabled;

  @override
  Widget build(BuildContext context) {
    // Было: RaisedButton(color: Colors.blue, textColor: Colors.white, …)
    return ElevatedButton(
      onPressed: enabled ? () {} : null,
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
        disabledBackgroundColor: Colors.blueGrey,
        disabledForegroundColor: Colors.white70,
      ),
      child: const Text('Сохранить'),
    );
  }
}

Старые кнопки объявили устаревшими во Flutter 2.0. OutlineButton удалили к версии 3.0, RaisedButton и FlatButton — к 3.3. Поэтому код из старых статей на современном Flutter не собирается.

ButtonTheme для новых кнопок не используется: вид задаёт один объект ButtonStyle вместо множества отдельных параметров — через style и styleFrom (раздел 5), а для всех кнопок сразу — через тему.

7. Частые ошибки

  • The method 'RaisedButton' isn't defined for the type '…' . Если в коде new RaisedButton(…) , текст другой — The name 'RaisedButton' isn't a class , а если кнопка создаётся вне класса — The function 'RaisedButton' isn't defined . Код написан для старой версии Flutter — замените кнопку по таблице раздела 6. Так же выглядят ошибки с FlatButton и OutlineButton .
  • Кнопка бледная и не нажимается. У неё onPressed (и onLongPress ) равны null — например, передали переменную, которая ещё null . Такая кнопка выключена.
  • Цвет из styleFrom не применяется. Проверьте, что кнопка не выключена: у неё onPressed не null . Цвет выключенной кнопки задают disabledBackgroundColor и disabledForegroundColor .
  • onPressed: _save() со скобками. Так кнопке передаётся не функция, а результат её вызова. Если функция ничего не возвращает ( void ), анализатор выдаст ошибку use_of_void_result . Нужно onPressed: _save — без скобок — или onPressed: () { … } .

Смотрите также: Урок 1 — первая кнопка FilledButton в приложении; справка ButtonStyle , FilledButton , IconButton .

Вопросы и предложения по статье присылайте на contact@flutter.su.