Сводка колонных компонентов

Flutter

предисловие

Эта статья представляет собой просто краткое изложение электронной книги, которую я прочитал за последние два дня.Если вы хотите увидеть знания из первых рук, вы можете перейти к электронной книгеbook.flutter ест тот.club/chapter7/дней спустя…. Фронтенд-разработка — это не более чем два шагаПервое это макет,Второй — запросить данные для обновления интерфейса., Прочитав его за последние два дня, я чувствую, что, по крайней мере, написать несколько простых интерфейсов не проблема. Остальные запросы, а также некоторые сторонние библиотеки успевают продолжиться. Для тех, кто не играл в код Flutter, предлагаю хотя бы поиграть в него самому после прочтения, не нужно играть во все это, потому что играть и читать — разные вещи.

StatefulWidget

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

Определение динамических компонентов

горячая клавиша

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

сгенерированный код

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
  • State — это класс, который содержит жизненный цикл элемента управления и имеет следующие методы. Включая инициализацию, построение, уничтожение и т. д. При использовании метода setState соответствующий обратный вызов будет обновлен.
  @override
  void initState() {
    _controller = AnimationController(vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Container();
  }
  ...

StatelessWidget

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

Виджет и элемент

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

Компоненты по функциям

Существует четыре типа, а именно основные компоненты, компоненты макета, компоненты контейнера и компоненты прокрутки.

компоненты базового класса

Основные компоненты делятся на текст (Text), изображение (Image), кнопку (xxButton), поле ввода (TextField), переключатель (Switch) и флажок (CheckBox), форму (Form)** и так далее. Основной формат:

    //文本
    Text("Hello world! I'm Jack. "*4,
            maxLines: 1,
         overflow: TextOverflow.ellipsis,
);
//按钮的种类有很多
RaisedButton(
  child: Text("normal"),
  onPressed: () => {},
);

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

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

Простое понимание: форма предоставляет средство проверки свойств для каждого поля ввода, чтобы определить, следует ли проверять то же самое. И предоставьте метод запуска кнопки отправки для запуска обратного вызова. Конкретный код можно ввести по следующему адресу.book.flutter съешь это.club/chapter3/in…

Компоненты класса макета

Горизонтальная линейная компоновка (ряд), вертикальная линейная компоновка (столбец), гибкая компоновка (Flex), непрерывная компоновка (Wrap|Flow), стопочная компоновка (Stack|Positioned)

Линейная планировка

И горизонтальные, и вертикальные — это базовые слои и Flex. Основной формат следующий

    Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.max, //有效,外层Colum高度为整个屏幕
      children: <Widget>[
        Container(
          color: Colors.red,
          child: Column(
            mainAxisSize: MainAxisSize.max,//无效,内层Colum高度为实际高度  
            children: <Widget>[
              Text("hello world "),
              Text("I am Jack "),
            ],
          ),
        )
      ],
    )

В основном то же самое, что и линейная компоновка Android.

  • crossAxisAlignment: почувствуйте выравнивание дочерних элементов управления
  • mainAxisSize: собственный размер, если он вложен, то будет недействителен
  • дети: дочерние элементы управления
  • Есть другие ссылки, чтобы увидетьbook.flutter съешь это.club/chapter4/RO…

Гибкая компоновка

  • Свойства Flex аналогичны линейному макету
  • Расширенный. Масштаб может быть установлен в гибком контейнере

Например, следующий код будет занимать экран в соотношении 1:2.

  Flex(
          direction: Axis.horizontal,
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Container(
                height: 30.0,
                color: Colors.red,
              ),
            ),
            Expanded(
              flex: 2,
              child: Container(
                height: 30.0,
                color: Colors.green,
              ),
            ),
          ],
        )

Схема потока

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

Каскадная компоновка

  • Стек похож на FrameLayout в Android, абсолютное позиционирование в Интернете.
  • Позиция в сочетании со стеком позволяет достичь эффекта абсолютного позиционирования.

компонент контейнера

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

Padding

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

 Padding(
      //上下左右各添加16像素补白
      padding: EdgeInsets.all(16.0),
      child: Column()

Контейнеры ограниченного класса (ConstrainedBox, SizedBox и т. д.)

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

ConstrainedBox(
    constraints: BoxConstraints(minWidth: 60.0, minHeight: 100.0),  //父
    child: UnconstrainedBox( //“去除”父级限制
      child: ConstrainedBox(
        constraints: BoxConstraints(minWidth: 90.0, minHeight: 20.0),//子
        child: redBox,
      ),
    )
)

ДекораторУкрашениеКоробка

Подобно форме Android, вы можете установить закругленные углы, градиенты, тени и многое другое. Формат следующий

 DecoratedBox(
    decoration: BoxDecoration(
      gradient: LinearGradient(colors:[Colors.red,Colors.orange[700]]), //背景渐变
      borderRadius: BorderRadius.circular(3.0), //3像素圆角
      boxShadow: [ //阴影
        BoxShadow(
            color:Colors.black54,
            offset: Offset(2.0,2.0),
            blurRadius: 4.0
        )
      ]
    ),
  child: Padding(padding: EdgeInsets.symmetric(horizontal: 80.0, vertical: 18.0),
    child: Text("Login", style: TextStyle(color: Colors.white),),
  )
)

Преобразование Преобразование

Вращать, переводить, масштабировать

DecoratedBox(
  decoration:BoxDecoration(color: Colors.red),
  child: Transform.rotate(
    angle:90 ,
    child: Text("Hello world"),
  ),
);

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

RotatedBox
 DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      //将Transform.rotate换成RotatedBox  
      child: RotatedBox(
        quarterTurns: 1, //旋转90度(1/4圈)
        child: Text("Hello world"),
      ),
    

Здесь не упомянуто преобразование прозрачности

Opacity(
        opacity: 0.1,
        child: new Container(
        width: 250.0,
        height: 100.0,
        decoration: new BoxDecoration(
        backgroundColor: const Color(0xff000000),
    ),
)

Контейнер-контейнер

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

Container({
  this.alignment,
  this.padding, //容器内补白,属于decoration的装饰范围
  Color color, // 背景色
  Decoration decoration, // 背景装饰
  Decoration foregroundDecoration, //前景装饰
  double width,//容器的宽度
  double height, //容器的高度
  BoxConstraints constraints, //容器大小的限制条件
  this.margin,//容器外补白,不属于decoration的装饰范围
  this.transform, //变换
  this.child,
  padding,
  margin,
})

Scaffold

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

Scaffold(
      appBar: AppBar( //导航栏
        title: Text("App Name"), 
        actions: <Widget>[ //导航栏右侧菜单
          IconButton(icon: Icon(Icons.share), onPressed: () {}),
        ],
      ),
      drawer: new MyDrawer(), //抽屉
      bottomNavigationBar: BottomNavigationBar( // 底部导航
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
          BottomNavigationBarItem(icon: Icon(Icons.business), title: Text('Business')),
          BottomNavigationBarItem(icon: Icon(Icons.school), title: Text('School')),
        ],
        currentIndex: _selectedIndex,
        fixedColor: Colors.blue,
        onTap: _onItemTapped,
      ),
      floatingActionButton: FloatingActionButton( //悬浮按钮
          child: Icon(Icons.add),
          onPressed:_onAdd
      ),
    );

Из подуправления следующего уровня Scaffold есть панель навигации (панель приложения), боковая панель (ящик), нижняя панель навигации (нижняя панель навигации), тело (контент)

Appbar

В Android тоже есть панель приложений, и эффект, можно сказать, тот же, и свойства похожи.

AppBar({
  Key key,
  this.leading, //导航栏最左侧Widget,常见为抽屉菜单按钮或返回按钮。
  this.automaticallyImplyLeading = true, //如果leading为null,是否自动实现默认的leading按钮
  this.title,// 页面标题
  this.actions, // 导航栏右侧菜单
  this.bottom, // 导航栏底部菜单,通常为Tab按钮组
  this.elevation = 4.0, // 导航栏阴影
  this.centerTitle, //标题是否居中 
  this.backgroundColor,
  ...   //其它属性见源码注释
})

Его можно использовать больше, чем TabBar под панелью приложений. Похоже на TabBar в Android

 bottom: TabBar(
      controller: _tabController,
      tabs: tabs.map((e) => Tab(text: e)).toList())
Drawer (боковая панель), BottomNacigationBar (нижняя панель навигации)

Это ничем не отличается от обычного использования компонентов контейнера.

Drawer(
        child: Container(
          padding: EdgeInsets.zero,
          children: <Widget>[
           
        ),
//中间有圆弧的效果
bottomNavigationBar: BottomAppBar(
  color: Colors.white,
  shape: CircularNotchedRectangle(), // 底部导航栏打一个圆形的洞
  child: Row(
    children: [
      IconButton(icon: Icon(Icons.home)),
      SizedBox(), //中间位置空出
      IconButton(icon: Icon(Icons.business)),
    ],
    mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部导航栏横向空间
  ),
)

компонент прокрутки

SingleChildScrollView, ListView, GridView, ConstomScrollView и прослушиватель прокрутки ScrollController

SingleChildScrollView

SingleChildScrollView({
 this.scrollDirection = Axis.vertical, //滚动方向,默认是垂直方向
 this.reverse=false,//滚动方向是否反向
 this.padding,//边距bool primary,//这是否是与父控件关联的主滚动视图 应该是是否与父控件一起滑动 用来解决滑动冲突
 this.physics,//滑动松手后的滑动方式
 this.controller,
 this.child,//子view
})
Scrollbar(
      child: SingleChildScrollView(
        padding: EdgeInsets.all(16.0),
        child: Center(
          child: Column( 
            //动态创建一个List<Widget>  
            children: str.split("") 
                //每一个字母都用一个Text显示,字体为原来的两倍
                .map((c) => Text(c, textScaleFactor: 2.0,)) 
                .toList(),
          ),
        ),
      )

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

physics
  • const ClampingScrollPhysics(): Эффект низкой освещенности в Android.
  • const BouncingScrollPhysics(): эффект эластичности в iOS.

ListView

ListView похож на Listview в Android и используется для отображения данных списка.

ListView({
  ...  
  //可滚动widget公共参数
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  ScrollController controller,
  bool primary,
  ScrollPhysics physics,
  EdgeInsetsGeometry padding,

  //ListView各个构造函数的共同参数  
  double itemExtent,
  bool shrinkWrap = false,
  bool addAutomaticKeepAlives = true,
  bool addRepaintBoundaries = true,
  double cacheExtent,

  //子widget列表
  List<Widget> children = const <Widget>[],
})
  1. Если данных не так много, используйте их напрямую
ListView(
  shrinkWrap: true, 
  padding: const EdgeInsets.all(20.0),
  children: <Widget>[
    const Text('列表数据'),
  ],
);
  1. Если данных много, используйте построитель или разделите для удобства
  • разделенный аналогичен конструктору, за исключением того, что в нем удобно определять разделительные линии.
class ListViewDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //下划线widget预定义以供复用。  
    Widget divider1=Divider(color: Colors.blue,);
    Widget divider2=Divider(color: Colors.green);
    return ListView.separated(
        itemCount: 100,
        //列表项构造器
        itemBuilder: (BuildContext context, int index) {
          return ListTile(title: Text("$index"));
        },
        //分割器构造器
        separatorBuilder: (BuildContext context, int index) {
          return index%2==0?divider1:divider2;
        },
    );
  }
}

GridView

Макет сетки также похож на тот, что в Android. Использование также примерно такое же, как ListView

class _GridViewLayoutState extends State<GridViewLayout> {
  @override
  Widget build(BuildContext context) {
    return GridView(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3, //横轴三个子widget
            childAspectRatio: 1.0 //宽高比为1
        ),
        children:<Widget>[
          Icon(Icons.ac_unit),
          Icon(Icons.airport_shuttle),
          Icon(Icons.all_inclusive),
          Icon(Icons.beach_access),
          Icon(Icons.cake),
          Icon(Icons.free_breakfast)
        ]
    );
  }
}

Я не хочу видеть слишком много вещей в будущем, поэтому нажмите здесь. Макеты сетки могут реализовывать только обычные сетки. Если вы хотите добиться эффекта водопада. Есть библиотека с открытым исходным кодомGitHub.com/let SAR/Flutong…

CustomScrollView

Приклейте элементы управления для размещения элементов управления прокруткой в ​​одном контейнере для достижения согласованных эффектов прокрутки. Его дочерние элементы управления имеют соответствующие элементы управления прокруткой для реализации Sliver.

Sliver

Щепка означает тонкий кусок и маленький кусочек.В Flutter Щепка обычно относится к прокручиваемому блоку с определенным эффектом прокрутки. Прокручиваемые виджеты, такие как ListView, GridView и т. д., имеют соответствующие реализации Sliver, такие как SliverList, SliverGrid и т. д. Вставьте фрагмент кода эффекта md, и эффект будет неплохим.

import 'package:flutter/material.dart';

class CustomScrollViewTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //因为本路由没有使用Scaffold,为了让子级Widget(如Text)使用
    //Material Design 默认的样式风格,我们使用Material作为本路由的根。
    return Material(
      child: CustomScrollView(
        slivers: <Widget>[
          //AppBar,包含一个导航栏
          SliverAppBar(
            pinned: true,
            expandedHeight: 250.0,
            flexibleSpace: FlexibleSpaceBar(
              title: const Text('Demo'),
              background: Image.asset(
                "./images/avatar.png", fit: BoxFit.cover,),
            ),
          ),

          SliverPadding(
            padding: const EdgeInsets.all(8.0),
            sliver: new SliverGrid( //Grid
              gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2, //Grid按两列显示
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
                childAspectRatio: 4.0,
              ),
              delegate: new SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  //创建子widget      
                  return new Container(
                    alignment: Alignment.center,
                    color: Colors.cyan[100 * (index % 9)],
                    child: new Text('grid item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
          ),
          //List
          new SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: new SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  //创建列表项      
                  return new Container(
                    alignment: Alignment.center,
                    color: Colors.lightBlue[100 * (index % 9)],
                    child: new Text('list item $index'),
                  );
                },
                childCount: 50 //50个列表项
            ),
          ),
        ],
      ),
    );
  }
}

монитор прокрутки

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

ScrollController _controller = new ScrollController();
  bool showToTopBtn = false; //是否显示“返回到顶部”按钮

  @override
  void initState() {
    //监听滚动事件,打印滚动位置
    _controller.addListener(() {
      print(_controller.offset); //打印滚动位置
      if (_controller.offset < 1000 && showToTopBtn) {
        setState(() {
          showToTopBtn = false;
        });
      } else if (_controller.offset >= 1000 && showToTopBtn == false) {
        setState(() {
          showToTopBtn = true;
        });
      }
    });
  }

функциональные компоненты

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

1. Вернитесь к перехвату WillPopScope.

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

WillPopScope(
        onWillPop: () async {
          if (_lastPressedAt == null ||
              DateTime.now().difference(_lastPressedAt) > Duration(seconds: 1)) {
            //两次点击间隔超过1秒则重新计时
            _lastPressedAt = DateTime.now();
            return false;
          }
          return true;
        },
        child: Container(
          alignment: Alignment.center,
          child: Text("1秒内连续按两次返回键退出"),
        )
    );

onWillPop — это функция обратного вызова, которая вызывается, когда пользователь нажимает кнопку «Назад» (включая кнопку навигации «Назад» и физическую кнопку «Назад» Android). Обратный вызов должен возвращать объект Future. Если окончательное значение возвращаемого Future равно false, текущий маршрут не складывается (не возвращается), когда окончательное значение равно true, текущий маршрут извлекается из стека и завершается. Нам нужно предоставить этот обратный вызов, чтобы решить, выходить ли.

2. Обмен данными InheritedWidget

Похоже на глобальную переменную

didChangeDependenciesЭта функция обратного вызова будет вызываться при изменении значения. Если вы его инкапсулируете, вы можете переключать языки и темы и так далее. см. конкретные примерыbook.flutter съешь это.club/chapter7/in….

3. Тема

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

ThemeData({
  Brightness brightness, //深色还是浅色
  MaterialColor primarySwatch, //主题颜色样本,见下面介绍
  Color primaryColor, //主色,决定导航栏颜色
  Color accentColor, //次级色,决定大多数Widget的颜色,如进度条、开关等。
  Color cardColor, //卡片颜色
  Color dividerColor, //分割线颜色
  ButtonThemeData buttonTheme, //按钮主题
  Color cursorColor, //输入框光标颜色
  Color dialogBackgroundColor,//对话框背景颜色
  String fontFamily, //文字字体
  TextTheme textTheme,// 字体主题,包括标题、body等文字样式
  IconThemeData iconTheme, // Icon的默认样式
  TargetPlatform platform, //指定平台,应用特定平台控件风格
  ...
})

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