Flutter. Изучаем виджеты.

Предисловие.

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

Виджет Scaffold.

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

Вот его код.

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Tutorial"),
        ),
        body: Center(
          child: Text("Hello"),
        ),
      ),
    ),
  );
}

Рассмотрим параметры Scaffold:

  • appBar — полоска сверху
  • body — основной контент.
  • floatingActionButton — весящая кнопка сбоку (не добавлял)

Таким образом, мы создали экран с полоской сверху, с надписью Tutorial, и внутри, по центру, расположили надпись Hello.

Теперь, создайте новый StatelessWidget (о котором, я говорил ранее), и измените функцию main.

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: NewWidget(),
      ),
    ),
  );
}

Далее, разберем макеты, чтобы было удобней располагать элементы.

Макет Row.

Виджет Row, позволяет располагать вложенные в него элементы, друг за другом, по горизонтали.

Элементы помещаются в массив children

 Widget build(BuildContext context) {
    return Row(
      children: [
        Text("elem"),
        Text("elem"),
        Text("elem"),
        Text("elem"),
      ],
    );
  }

Макет Column.

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

Widget build(BuildContext context) {
    return Column(
      children: [
        Text("elem"),
        Text("elem"),
        Text("elem"),
        Text("elem"),
      ],
    );
  }

Container.

Виджет Container, это аналог <div> из html, он позволяет менять свойства вложенных элементов, такие как:

  • color — цвет фона, внутри контейнера
  • margin — отступ за пределами контейнера
  • padding — отступ внутри контейнера
  • и другие
Widget build(BuildContext context) {
    return Container(
      child: Text("123"),
      color: Colors.red,
      margin: EdgeInsets.all(10),
      padding: EdgeInsets.all(30),
    );
  }

С помощью EdgeInsets.all(), задается отступ по всем сторонам.

Виджеты кнопок (TextButton, ElevatedButton, OutlinedButton, IconButton).

При нажатии на TextButton, выполняется метод переданный в onPressed. В нашем случае, была передана пустая функция «() {}». В child, вкладываются виджеты, тем самым меняя вид кнопки.

 Widget build(BuildContext context) {
    return Column(
      children: [
        TextButton(onPressed: () {}, child: Text("TextButton")),
        ElevatedButton(onPressed: () {}, child: Text("ElevatedButton")),
        OutlinedButton(onPressed: () {}, child: Text("OutlinedButton")),
        IconButton(
          onPressed: () {},
          icon: Icon(Icons.search),
        ),
      ],
    );
  }

Кнопки ElevatedButton и OutlinedButton, отличаются только видом. Поэтому, их рассматривать не буду.

Кнопка IconButton, принимает иконку. Иконки, это векторные изображения, это значит, что их можно бесконечно увеличивать без потери качества.

У Flutter, есть стандартный набор иконок, который находится в объекте Icons.

Выводим изображение (Image).

Виджет Image, может подгрузить изображение из интернета, с помощью NetworkImage.

Widget build(BuildContext context) {
    return Column(
      children: [
        Image(
          image: NetworkImage("https://under-prog.ru/favicon.png"),
        ),
      ],
    );
  }

Если хотите подгрузить свою картинку то, создайте папку images, в папке с проектом, и поместите туда любую png картинку.

И пропишите путь до папки images в pubspec.yaml, таким образом.

Сохраните pubspec.yaml, тем самым, вы импортируйте ресурсы в проект.

Запись такого типа

- images/

Позволяет импортировать все ресурсы в папке images.

Далее, в AssetImage, передайте путь до картинки.

Image(
  image: AssetImage("images/coffe_cup_2.png"),
)

И запустите, перезагрузив проект. В итоге, картинка загрузилась из локального хранилища.

Делаем прокручиваемый список (ListView).

В параметр children виджета ListView, передайте массив виджетов. Тем самым вы получите прокручиваемый список.

Widget build(BuildContext context) {
    return ListView(
      children: [
        Text("1"),
        Text("2"),
        Text("3"),
        Text("4"),
        Text("1"),
        Text("2"),
      ],
    );
  }

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

ListView.builder и бесконечный список.

Спасет нас ListView.builder, который, строит элементы списка на ходу, т.е. подгружает лишь те элементы, что видны на экране.

Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (context, index) {
        return Text("Number $index");
      },
    );
  }

У ListView.builder, в itemBuilder, надо передать функцию, которая будет возвращать виджет элемента списка. В неё передается 2 аргумента.

  • context — нужен при работе с окнами (об этом позже)
  • index — индекс текущего элемента списка.

В этом примере, я вывел индекс текущего элемента, и завернул его, в виджет Text.

return Text("Number $index");

Чтобы вывести значение переменной в строке, используется знак $ перед названием переменной. Когда используется что-то кроме названия переменной (например нужно получить элемент массива, или вызвать функцию), используется запись с фигурными скобками. Например так:

"${array[12]} some text ${randObj.randVar}"

По итогу, получился бесконечный список, который отображает номер индекса.

Передача массива в ListView.

Теперь, попробуем занести массив в этот список.

Widget build(BuildContext context) {
    final _array = ["Under-Prog", "Flutter", "Tutorials"]; 
    return ListView.builder(
      itemCount: _array.length,
      itemBuilder: (context, index) {
        return Text("${_array[index]}");
      },
    );
  }

Этой строкой.

final _array = ["Under-Prog", "Flutter", "Tutorials"];

Я создал неизменяемый (final) массив, и сразу же, задал ему значения.

Нижнее подчеркивание перед названием переменной, означает, что переменная недоступна из вне (аналог private из Java и C++).

Далее, в параметре itemCount

itemCount: _array.length,

Задали размер списка (_array.length), чтобы индекс, не выходил за пределы массива.

И вывели элемент массива на экран.

return Text("${_array[index]}");

Украшаем список виджетом ListTile.

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

Widget build(BuildContext context) {
    final _array = ["Under-Prog", "Flutter", "Tutorials"];
    return ListView.builder(
      itemCount: _array.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text("${_array[index]}"),
          leading: Text("$index"),
        );
      },
    );
  }
  • titile, отвечает за содержание
  • leading, за левую сноску.

Делаем свой ListTile.

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

Widget build(BuildContext context) {
    final _array = ["Under-Prog", "Flutter", "Tutorials"];
    return ListView.builder(
      itemCount: _array.length,
      itemBuilder: (context, index) {
        return Row(
          children: [
            Image(
              image: NetworkImage("https://under-prog.ru/favicon.png"),
            ),
            Expanded(
              child: Center(
                child: Text("${_array[index]}"),
              ),
            ),
          ],
        );
      },
    );
  }

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

Заключение.

В этой статье, вы узнали о базовых виджетах в Flutter, это лишь малая часть от всего многообразия виджетов. Разумеется, всех их учить не надо (да и не все они потребуются), просто, скачайте себе на телефон Flutter Catalog, от Maxing, и используйте приглянувшиеся вам виджеты. В этом каталоге есть большое количество примеров использования виджетов с приложенными исходниками.

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

Итоговый результат.

Пожалуйста отключи блокировщик рекламы, или внеси сайт в белый список!

Please disable your adblocker or whitelist this site!