Как сделать круглую кнопку flutter

Обновлено: 07.07.2024

Переключатель Flutter используется для переключения между настройками вкл / выкл, соответственно true / false.

Когда переключатель включен, значение, возвращаемое свойством Switch onChanged, имеет значение true, а переключатель выключен, свойство onChanged возвращает значение false.

В следующем примере приложения Flutter мы определили виджет Switch. Всякий раз, когда Switch переключается, onChanged вызывается с новым состоянием Switch в качестве значения.

Мы определили логическую переменную isSwitched для хранения состояния Switch.

Ядром механизма макетов Flutter являются виджеты. В Flutter почти все является виджетами — даже модели макетов являются виджетами. Изображения, значки и текст, которые вы видите в приложении Flutter, являются виджетами. Все невидимые элементы — это также виджеты, например, строки, столбцы и сетки, которые упорядочивают, сжимают и выравнивают видимые виджеты.

Вы создаете макет путем компоновки виджетов для построения более сложных виджетов. Например, на первом скриншоте ниже показаны 3 значка с надписями под каждым из них:

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

Вот диаграмма дерева виджетов для этого пользовательского интерфейса:


Большая часть этого должна выглядеть так, как вы могли бы ожидать, но вас могут заинтересовать контейнеры (показаны розовым цветом). Container (контейнер) — это класс виджетов, который позволяет настраивать свои дочерние виджеты. Используйте Container (контейнер), когда вы хотите добавить внутренние отступы, поля, границы или цвет фона, чтобы обозначить некоторые из его характеристик.

В данном примере каждый Text (текстовый) виджет помещается в Container (контейнер) для добавления полей. Все Row (строки) также помещаются в Container, чтобы добавить внутренний отступ вокруг строки.

Остальная часть пользовательского интерфейса в этом примере контролируется свойствами. Установите цвет значка, используя его цветовое свойство color. Используйте свойство Text.style для установки шрифта, его цвета, ширины и так далее. Столбцы и строки имеют свойства, которые позволяют указать, как их дочерние элементы выровнены по вертикали или горизонтали, и сколько места должно занимать дочернее пространство.

Как расположить один виджет в Flutter? В этом разделе показано, как создать и отобразить простой виджет. Он также показывает весь код для простого приложения Hello World.

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

1.Выберите виджет макета

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

В данном примере используется Center (центр), который центрирует содержимое по горизонтали и вертикали.

2. Создайте видимый виджет

Например, создайте Text (текстовый) виджет:

Создайте Image (изображение) виджет:

Создайте виджет с иконкой Icon:

3. Добавьте видимый виджет в виджет макета

Все виджеты макета имеют одно из следующих свойств:

  • Свойство дочернего виджета child если берется один дочерний виджет — Center (центр) или Container (контейнер)
  • Свойство дочерних виджетов children, если они берут список виджетов, например, Row (строка), Column (столбец), ListView (просмотр списка) , или Stack (стек).

Добавьте виджет Text (текст) в виджет Center (центр):

4. Добавьте виджет макета на страницу

Приложение Flutter само по себе является виджетами, и большинство виджетов имеют метод build(). При приведении и возврате виджета в метод build() приложения отображается виджет.

Приложения Material

Для приложения Material можно использовать виджет Scaffold; он предоставляет баннер по умолчанию, цвет фона, а также имеет API для добавления элементов оформления контейнеров, верхних меню и нижних меню кнопок. Затем можно добавить виджет Center (центр) непосредственно в свойство Body (тело) для главной страницы.

lib/main.dart (MyApp)

Приложения не Material

Для не-Material приложений можно добавить виджет Center в метод build() приложения:

lib/main.dart (MyApp)

По умолчанию не-Material приложение, не содержит AppBar (меню), заголовка или цвета фона. Если вы хотите, чтобы эти функции были доступны в не-Material приложении, вам необходимо собрать их самостоятельно. Это приложение меняет цвет фона на белый, а текст — на темно-серый, чтобы имитировать приложение Material.


Исходный код приложения:

Разместите несколько виджетов вертикально и горизонтально

Одной из наиболее распространенных схем макета является расположение виджетов по вертикали или горизонтали. Виджет Row (строка) можно использовать для расположения виджетов по горизонтали, а виджет Column (столбец) — для расположения виджетов по вертикали.

В чем смысл?

  • Row (строка) и Column (столбец) — два наиболее часто используемых шаблона макета.
  • Row и Column каждый из них берет список дочерних child виджетов.
  • Дочерний Child виджет может быть сам по себе виджет Row, Column или другой сложный виджет.
  • Вы можете указать, как Row (строка) или Column (столбец) выравнивает свои дочерние виджеты как по вертикали, так и по горизонтали.
  • Можно растягивать или ограничивать определенные дочерние Child виджеты.
  • Вы можете указать, как дочерние виджеты используют доступное пространство строки или столбца.

Эта разметка организована как Строка. Строка содержит два дочерних Children элементов: слева — столбец, справа — изображение:


Дерево виджетов левого столбца содержит строки и столбцы.


Вы реализуете код макета Павловой в строках и столбцах вложенности.

Вы управляете выравниванием дочерних элементов строки или столбца с помощью свойств mainAxisAlignment (выравнивание по главной оси) и crossAxisAlignment (выравнивание по поперечной оси). Для строки главная ось работает горизонтально, а поперечная — вертикально. В случае столбца главная ось работает вертикально, а поперечная ось — горизонтально.



Классы MainAxisAlignment и CrossAxisAlignment предлагают различные константы для управления выравниванием.

В следующем примере каждое из 3-х изображений имеет ширину 100 пикселей. Окно рендера (в данном случае весь экран) имеет ширину более 300 пикселей, поэтому установка выравнивания по главной оси на SpaceEvenly (равномерное пространство) равномерно делит свободное горизонтальное пространство между, до и после каждого изображения.


Колонки работают так же, как и строки. В следующем примере показан столбец из 3-х изображений, каждое из которых имеет высоту 100 пикселей. Высота окна рендера (в данном случае всего экрана) составляет более 300 пикселей, поэтому установка выравнивания по главной оси на SpaceEvenly (равномерное пространство) равномерно разделяет свободное вертикальное пространство между, над и под каждым изображением.


Виджеты для измерения размеров

Когда макет слишком велик, чтобы подойти к устройству, вдоль затронутого края появляется желто-черная полоска. Вот пример слишком широкой полосы:



Возможно, вы хотите, чтобы виджет занимал вдвое больше места, чем другие дочерние виджеты. Для этого используйте свойство Expanded виджета flex, целое число, определяющее коэффициент гибкости для виджета. По умолчанию коэффициент гибкости равен 1. Следующий код устанавливает коэффициент гибкости среднего изображения равным 2:


Виджеты для упаковки

По умолчанию строка или столбец занимает как можно больше места вдоль своей главной оси, но если вы хотите упаковать дочерние виджеты близко друг к другу, установите mainAxisSize в MainAxisSize.min. В следующем примере это свойство используется для упаковки значков звезд вместе.


Вложенные строки и столбцы

Макет фреймворка позволяет вложить строки и столбцы внутри строк и столбцов настолько глубоко, насколько это необходимо. Рассмотрим код выделенного участка следующего макета:


Выделенный раздел выполнен в два ряда. Строка рейтингов содержит пять звезд и количество отзывов. Строка значков содержит три столбца значков и текста.

Дерево виджетов для строки рейтингов:


Переменная рейтингов создает строку, содержащую меньшую строку из 5-звездочных значков и текста:

Строка значков под строкой рейтингов содержит 3 столбца; каждый столбец содержит значок и две строки текста, как видно из дерева виджетов:


Переменная iconList определяет строку значков:

Переменная leftColumn (левый столбец) содержит строки рейтингов и значков, а также заголовок и текст, описывающий Павлову:

Левый столбец помещается в Container (контейнер) для ограничения его ширины. Наконец, пользовательский интерфейс строится всем рядом (содержащим левый столбец и изображение) внутри Card (карты).

Общие виджеты макета

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

  • Container (контейнер): Добавляет в виджет отступы, поля, границы, цвет фона или другие украшения.
  • GridView (сетка): Размещает виджеты в виде прокручиваемой сетки.
  • ListView (список): Размещает виджеты в виде прокручиваемого списка.
  • Stack: (набор) Накладывает виджет на другой.
  • Card (карточка): Организует необходимую информацию в блок (карточку) с закругленными углами и тенью от падения.
  • ListTile (список-плитка): Организует до 3 строк текста, а также опционально ведущие и задние значки в строку.

Во многих макетах контейнеры свободно используются для разделения виджетов с помощью отступов или добавления границ или полей. Вы можете изменить фон устройства, поместив весь макет в Container и изменив цвет его фона или изображение.

  • Добавляет отступы, поля, границы
  • Изменяет цвет фона или изображение
  • Содержит один дочерний виджет, но этот виджет может быть Row, Column или даже корнем дерева виджетов.

Этот макет состоит из столбца с двумя строками, каждая из которых содержит 2 изображения. Container используется для изменения цвета фона столбца на более светло-серый.


Container также используется для добавления закругленной границы и полей к каждому изображению:

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

  • Выкладывает виджеты в сетку
  • Обнаруживает, когда содержимое столбца выходит за пределы области рендеринга, и автоматически обеспечивает прокрутку
  • Создает свою собственную сетку или использует одну из предоставленных сеток:
  • GridView.count позволяет указать количество столбцов
  • GridView.extent позволяет задать максимальную ширину плитки в пикселях.


Используйте GridView.count для создания сетки шириной 2 плитки в портретном режиме и 3 плитки в ландшафтном режиме. Заголовки создаются путем установки свойства footer для каждого GridTile.


Используйте GridView.extent для создания сетки с плитками шириной не более 150 пикселей.

ListView, виджет, похожий на колонку, автоматически обеспечивает прокрутку, когда его содержимое слишком длинное для его рендеринга.

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


Используйте ListView для отображения списка компаний с помощью ListTiles. Делитель отделяет театры от ресторанов.


Используйте ListView для отображения цветов из Material Design palette для определенного семейства цветов.

Используйте Stack, чтобы расположить виджеты поверх базового виджета — часто изображение. Виджеты могут полностью или частично перекрывать базовый виджет.

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


Используйте Stack для наложения Container (текст которого отображается на полупрозрачном черном фоне) на верхнюю часть CircleAvatar. Stack сбивает текст, используя свойство выравнивания Alignment.


Используйте Stack для наложения градиента на верхнюю часть изображения. Градиент обеспечивает четкое разделение значков панели инструментов по отношению к изображению.

Карточка Card из Material library содержит сопутствующие самородки информации и может быть составлена практически из любого виджета, но часто используется со списком ListTile. Card имеет единственный дочерний элемент, но это может быть столбец, строка, список, сетка или другой виджет, поддерживающий несколько дочерних элементов. По умолчанию размер Card уменьшается до 0 на 0 пикселей. Вы можете использовать SizeBox для ограничения размера Card.

  • Встраивается в Material карточку
  • Используется для представления соответствующих кусков информации
  • Принимает один дочерний элемент, но этот дочерний элемент может быть Row (строка), Column (столбец) или другим видом, который содержит список дочерних элементов.
  • Отображается со скругленными углами и каплевидной тенью
  • Содержимое Card не может прокручиваться.
  • Из библиотеки Material


Card (карточка), содержащая 3 плитки ListTiles и размером с SizeBox. Делитель Divider разделяет первую и вторую плитку ListTiles.


Card, содержащая изображение и текст.

Dart код: cards_demo.dart из Flutter галереи

Используйте ListTile (список плиток), специализированный виджет строк из библиотеки Material, для простого способа создания строки, содержащей до 3 строк текста и опциональных ведущих и следующих значков . ListTile чаще всего используется в Card или ListView, но может использоваться и в других местах.

  • Специализированная строка, содержащая до 3 строк текста и дополнительные иконки
  • Менее настраиваемый, чем Row, но более простой в использовании.
  • Из библиотеки Material


Карточка Card, содержащая 3 плитки ListTiles.


Использует ListTile для перечисления 3 типов выпадающих кнопок.
Dart код: buttons_demo.dart из галереи Flutter Gallery

Чтобы полностью понять систему макетов Flutter, вам необходимо узнать, как Flutter позиционирует и размещает компоненты в макетах. Для получения дополнительной информации см. раздел «Понимание ограничений«.

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

Код для указания цвета иконок для AppBar

Пример использования кода в приложении

Как во Flutter установить цвет кнопки

Как во Flutter установить цвет кнопки "назад" для AppBar.

Ключи во Flutter

Во Flutter есть много разных виджетов, но если вы посмотрите на свойства любого из них, вы, скорее всего, найдете параметр key (ключ).

Большинство новичков, начинающих изучать Flutter, не понимают для чего нужны ключи и как правильно их применять. А все потому, что применение ключей не сильно распространено, хотя это очень сильный и полезный инструмент.

В этой статье я попытаюсь объяснить концепцию ключей, их различные типы, где и как их правильно использовать.

Что такое ключи?

Если мы посмотрим на определение слова, Key написанное в официальной документации Flutter, оно гласит:

Ключ - это идентификатор для виджетов, элементов и семантических узлов.

Это означает, что Flutter различает виджеты и место их размещения в дереве виджетов по ключам. Но это еще не все.

Ключи сохраняют, состояние (state) когда вы перемещаетесь по дереву виджетов.

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

Сейчас давайте разберем разные типы ключей один за другим.

UniqueKey

UniqueKey используется для уникальной идентификации каждого виджета вашего приложения.

UniqueKey также сохраняет состояние при перемещении виджетов в дереве виджетов.

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

Это полезно, когда у вас есть несколько виджетов в дереве виджетов с одинаковыми значениями и одним типом, и вы хотите уникально идентифицировать каждый из них.

Это также полезно, когда уникальный идентификатор не определен в вашей коллекции БД, чтобы однозначно идентифицировать весь список элементов. Вы можете использовать, UniqueKey который назначит уникальный ключ этому конкретному виджету.

Разберем один пример:

Я собираюсь создать программу обмена смайликами, в которой на экране будут отображаться два смайлика и кнопка под ними, которая будет менять положение смайликов при нажатии.

Как и следовало ожидать, смайлы поменяются местами, когда мы нажмем кнопку.

Но проблема возникнет, если мы попытаемся преобразовать Stateless виджет в Stateful виджет и сохранить значение в state.

Смайлы не переключаются

Это произошло потому, что под капотом Flutter различает виджеты по типу (runtimeType) и по ключу.

В Stateful в нашем списке два виджета для смайлов. Когда мы меняем позиции смайликов, нажав на кнопку, Flutter видит в дереве виджетов и дереве элементов два виджета с одинаковым типом.

Если вы не знаете что такое дерево элементов (ElementTree): ElementTree содержит информацию только о типе каждого виджета и ссылку на дочерние элементы. Вы можете рассматривать ElementTree как скелет вашего приложения. Другими словами, дерево элементов показывает структуру вашего приложения.

tree

Состояние начальное

После нажатия Flutter проверит типы виджетов.

tree 2

Состояние после нажатия кнопки

Когда я нажал на кнопку, Flutter обходит ElementTree, проверяет тип 😎 Text Element из ElementTree и видит, что он такой же , как 🤠 Text Widget, и поэтому ничего обновлять не будет.

Но. но если мы назовем эти два Stateful виджета по-разному. Тогда не будет проблем. Потому что обоих будут разные идентификаторы / ключи.

Чтобы обновить виджеты, которые имеют тот же тип внутри списка, мы должны присвоить UniqueKey всем виджетам.

Все снова работает

Что же произошло, - когда флаттер попытался сравнить типы виджетов они оказались одинаковыми. Но когда он начал сопоставлять ключи, они оказались разными. Флаттер понял, что это разные виджеты, изменил ссылки в дереве элементов и обновил приложение.

Обновление дерева виджетов Ключи не совпали Обновление дерева виджетов Замена элементов в дереве элементов

Куда ставить ключи

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

Объясню на примере:

Здесь я использовал предыдущий пример. Просто добавил цвет фона, который генерируется случайным образом.

Пока все работает:

Пока все работает

Теперь давайте обернем наши GetEmoji виджеты в Container.

А теперь давайте снова запустим приложение.

Вроде работает, но не корректно

Виджеты меняются местами, это нормально, но новый цвет генерируется снова и снова при нажатии кнопки.

Фактически, это не только новый цвет, который генерируется снова и снова, но также и новый Text Widget который генерируется снова и снова в дереве виджетов, мы не можем этого видеть, потому что мы используем только два статических эмодзи.

Но, мы уже присвоили ключ виджету, правильно? Да, и проблема не в ключах, а в расположении самих ключей.

Так, что же происходит?

Вот структура дерева виджетов и элементов:

new tree

Дерево виджетов и элементов

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

На втором уровне Flutter замечает, что ключ 😎 Container Element не соответствует ключу виджета, поэтому он деактивирует этот 😎 Container Element, разрывая эти соединения.

Поскольку он не может найти на этом уровне Container Element с этим значением ключа, он создает новый и инициализирует новое состояние, в данном случае создавая виджет со случайным цветом фона.

tree upd

Решить эту проблему можно добавив key в Padding виджет.

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

ValueKey :

Ключ, который использует любое указанное нами value для идентификации.

ValueKey полезен, если мы хотим сохранить состояние виджетов с отслеживанием состояния, когда они перемещаются по дереву виджетов.

Рассмотрим приведенный ниже код, где есть 2 Textfield виджета. И мы хотим удалить последний Textfield из дерева виджетов.

Пример

Нажимаем кнопку Remove Favourite Framework field.

Если вы заметили, мы получили Flutter в текстовом поле "Любимый язык" вместо Dart.

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

Мы должны предоставить этим виджетам уникальные значения, которые помогут флаттеру понять, что они разные.

Мы можем предоставить уникальные значения с помощью ValueKey .

Теперь, как мы видим, поле "Favorite Language" сохранило свое реальное значение, как и ожидалось.

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

С ValueKey можно использовать любой тип уникальных значений: String, int, double, Objects и т.д.

Но все виджеты должны иметь уникальные значения. Это следует иметь в виду. Иначе ничего не получится.

Одна важная вещь, когда у нас есть список виджетов внутри Listview, Column или Row, постарайтесь не использовать в ключах значения index, поступающие из списка.

ObjectKey:

Ключ, который использует ссылку определенного типа для идентификации.

Я создал Список объектов SuperHero из класса SuperHero.

Эта программа поменяет местами первые два элемента в superHeroList.

Но если мы попытаемся поменять местами эти два элемента, что-то пойдет не так: вы увидите, что текст элемента меняется местами, а цвет - нет. А он тоже должен измениться, правда? Потому что цвет также связан с этим элементом списка.

Как мы обсуждали выше, флаттер не может различить виджеты одинаковых типов.

Тогда какое решение?

Вы можете подумать, что мы можем использовать ValueKey, верно? И да, вы правы, мы можем использовать ValueKey для различения виджетов в списке. Но есть один нюанс. Посмотрим, что будет, если мы используем ValueKey.

И мы получаем ожидаемый результат. Теперь предметы меняются местами вместе с цветом.

Но, что если теперь усложним и добавим в наш список Object.

Тогда на выходе получим:

Пример 6

И Flutter выдаст ошибку, примерно такую:

Ошибка

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

В данном случае мы добавили два одинаковых объекта с одинаковым значением. Вот почему Flutter выдает ошибку: " Эй, я нашел повторяющиеся ключи".

В таких случаях мы должны использовать ObjectKey .

Как следует из определения ObjectKey , этот ключ будет различать элементы на основе ссылок.

Давайте попробуем добавить ObjectKey :

И как только мы добавим, ObjectKey мы сможем увидеть результат. Теперь все работает нормально.

PageStorageKey

PageStorageKey в основном используется для сохранения позиции прокрутки прокручиваемых виджетов, таких как ListView или GridView и т.д.

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

Давайте рассмотрим пример, чтобы понять, как мы можем использовать PageStorageKey в приложении.

Здесь я создал простой Listview:

А теперь остановим список на середине и перейдем на другую вкладку.

Видите? Позиция списка не сохранилась.

Давайте решим эту проблему добавив PageStorageKey в ListView.

Теперь все отлично работает!

Это все, что вам нужно сделать, чтобы сохранить место прокрутки.

Но, в случае всплывающего окна вы не сможете получить предыдущую позицию представления прокрутки, потому что, когда оно открывается, смена экрана также удаляет PageStorageKey прикрепленный к нему.

GlobalKey

Это наиболее часто используемый ключ во Flutter по сравнению с указанными выше ключами.

GlobalKey может быть использован для изменения родительских виджетов в любом месте вашего приложения без потери состояния.

Его можно использовать для доступа к информации о другом виджете, когда мы находимся в совершенно другом месте дерева виджетов.

Один из вариантов использования - GlobalKey это проверка Form или отображение Snackbar в приложении и т.д.

Теперь мы можем получить доступ к count значению CounterWidget на любой странице, передав GlobalKey.

Итак, как мы видим, что GlobalKey можно использовать для доступа к информации о другом виджете, когда мы находимся в совершенно другом месте дерева виджетов.

Читайте также: