Создание красивых интерфейсов пользовательского интерфейса с помощью Flutter — основные компоненты

Flutter
Создание красивых интерфейсов пользовательского интерфейса с помощью Flutter — основные компоненты

1. Введение

FlutterКак одна из самых популярных технологий в настоящее время, она уже привлекла внимание большого количества энтузиастов технологий, и даже некоторых闲鱼,美团,腾讯и другие крупные компании начали использовать его. Хотя его экология еще не полностью созрела,GoogleБлаго, скорость его развития уже достаточно поразительна, можно предвидеть, что в будущемFlutterСпрос на разработчиков также будет расти.

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

Сегодня я поделюсь некоторыми из наиболее часто используемых базовых компонентов во Flutter, которые являются основными элементами, составляющими интерфейс пользовательского интерфейса:容器,,,绝对定位布局,文本,图片а также图标Ждать.

2. Основные компоненты

2.1 Контейнер (контейнерный компонент)

ContainerКомпонент является одним из наиболее часто используемых компонентов макета и может рассматриваться как один из элементов веб-разработки.div, р-н в разработкеView. Его часто можно использовать для управления размером, цветом фона, границами, тенями, полями и расположением содержимого. Давайте сначала посмотрим на его конструктор:

Container({
  Key key,
  double width,
  double height,
  this.margin,
  this.padding,
  Color color,
  this.alignment,
  BoxConstraints constraints,
  Decoration decoration,
  this.foregroundDecoration,
  this.transform,
  this.child,
})

2.1.1 width,height,margin,padding

Смысл этих свойств ничем не отличается от того, что мы уже знаем. Единственное, что следует отметить, это то, чтоmarginа такжеpaddingПрисвоение не является простым числом, потому что оно имеетleft, top, right, bottomНеобходимо установить значения для четырех направлений.Flutterпри условииEdgeInsetsЭтот класс помогает нам легко генерировать значения в четырех направлениях. Обычно мы можем использоватьEdgeInsets4 метода строительства:

  • EdgeInsets.all(value): используется для установки одного и того же значения в 4 направлениях;
  • EdgeInsets.only(left: val1, top: val2, right: val3, bottom: val4): значение определенного направления может быть установлено индивидуально;
  • EdgeInsets.symmetric(horizontal: val1, vertical: val2): используется для установки значения в горизонтальном/вертикальном направлении;
  • EdgeInsets.fromLTRB(left, top, right, bottom): Установите значения в 4 направлениях в порядке сверху слева и снизу справа.

2.1.2 color

Смысл этого свойства — цвет фона, который эквивалентен backgroundColor в web/rn. должен быть в курсеFlutterЕсть специальный цветColorclass вместо нашей обычной строки. Но мы можем сделать преобразование очень легко, например:

В web/rn мы будем использовать'#FF0000'или'red'для представления красного цвета, а во Flutter мы можем использоватьColor(0xFFFF0000)илиColors.redПредставлять.

2.1.3 alignment

Это свойство используется для определенияContainerКак будут расположены подкомпоненты компонента (PS: больше не беспокойтесь о центрировании). Обычно используется его необязательное значение:

  • Alignment.topLeft: верхний левый
  • Alignment.topCenter: На
  • Alignment.topRight: в правом верхнем углу
  • Alignment.centerLeft: слева посередине
  • Alignment.center: центр
  • Alignment.centerRight: среднее право
  • Alignment.bottomLeft: внизу слева
  • Alignment.bottomCenter: нижняя середина
  • Alignment.bottomRight: Нижний правый

2.1.4 constraints

В web/rn мы обычно используемminWidth/maxWidth/minHeight/maxHeightи другие свойства для ограничения ширины и высоты контейнера. существуетFlutterВ, вам нужно использоватьBoxConstraints(Box Constraint) для достижения этой функции.

// 容器的大小将被限制在[100*100 ~ 200*200]内
BoxConstraints(
  minWidth: 100,
  maxWidth: 200,
  minHeight: 100,
  maxHeight: 200,
)

2.1.5 decoration

Это свойство очень мощное и буквально означает украшение, потому что с его помощью можно установить边框,阴影,渐变,圆角и другие общие свойства.BoxDecorationунаследовано отDecorationкласс, поэтому мы обычно генерируемBoxDecorationэкземпляр для установки этих свойств.

1) Граница

Можно использоватьBorder.allКонструктор напрямую генерирует 4 границы, или вы можете использоватьBorderКонструктор самостоятельно устанавливает границы в разные стороны. Но удивительно, что официально предоставленная граница не поддерживает虚线(issueэто здесь).

// 同时设置4条边框:1px粗细的黑色实线边框
BoxDecoration(
  border: Border.all(color: Colors.black, width: 1, style: BorderStyle.solid)
)

// 设置单边框:上边框为1px粗细的黑色实线边框,右边框为1px粗细的红色实线边框
BoxDecoration(
  border: Border(
    top: BorderSide(color: Colors.black, width: 1, style: BorderStyle.solid),
    right: BorderSide(color: Colors.red, width: 1, style: BorderStyle.solid),
  ),
)

2) Тень

Теневые свойства и сетьboxShadowРазницы почти нет и можно уточнитьx,y,blur,spread,colorи другие свойства.

BoxDecoration(
  boxShadow: [
    BoxShadow(
      offset: Offset(0, 0),
      blurRadius: 6,
      spreadRadius: 10,
      color: Color.fromARGB(20, 0, 0, 0),
    ),
  ],
)

3) Градиент

Если вы не хотите, чтобы цвет фона контейнера был монотонным, попробуйте использоватьgradientАтрибуты.FlutterТакже поддерживает线性渐变а также径向渐变:

// 从左到右,红色到蓝色的线性渐变
BoxDecoration(
  gradient: LinearGradient(
    begin: Alignment.centerLeft,
    end: Alignment.centerRight,
    colors: [Colors.red, Colors.blue],
  ),
)

// 从中心向四周扩散,红色到蓝色的径向渐变
BoxDecoration(
  gradient: RadialGradient(
    center: Alignment.center,
    colors: [Colors.red, Colors.blue],
  ),
)

4) округлые углы

Как правило, вы можете использоватьBorderRadius.circularконструктор, чтобы установить закругленные углы для всех 4 углов одновременно, илиBorderRadius.onlyКонструктор для индивидуальной настройки закругления определенных углов:

// 同时设置4个角的圆角为5
BoxDecoration(
  borderRadius: BorderRadius.circular(5),
)

// 设置单圆角:左上角的圆角为5,右上角的圆角为10
BoxDecoration(
  borderRadius: BorderRadius.only(
    topLeft: Radius.circular(5),
    topRight: Radius.circular(10),
  ),
)

2.1.6 transform

transformАтрибуты в основном такие же, как те, которые мы часто используем в web/rn, в том числе:平移,缩放,旋转а также倾斜. Во Flutter класс матричных преобразований инкапсулированMatrix4Помогите нам преобразовать:

  • translationValues(x, y, z): перевести х, у, г;
  • rotationX(radians): вращение по оси X, радианы, радианы;
  • rotationY(radians): ось Y поворачивает радианы в радианах;
  • rotationZ(radians): ось Z поворачивает радианы в радианах;
  • skew(alpha, beta): ось X наклонена на альфа-градусы, а ось Y наклонена на бета-градусы;
  • skewX(alpha): альфа-градус наклона оси X;
  • skewY(beta): бета-градус наклона оси Y;

2.1.7 Резюме

ContainerАтрибуты компонентов очень богаты, хотя некоторые варианты использования немного отличаются от web/rn, но в основном они одинаковы, поэтому при переходе не будет никаких препятствий. Кроме того, посколькуContainerКомпонент является компонентом с одним дочерним узлом, то есть разрешен только один дочерний узел. Итак, в макете много раз мы будем использоватьRowа такжеColumnкомпоненты/макет.

2.2 Ряд/столбец (строка/столбец в сборе)

Rowа такжеColumnКомпонент на самом деле такой же, как и в web/rnFlex布局(Flexbox) особенно похож, или мы можем понять это так. использоватьFlex布局одноклассники主轴а также次轴Понятие , должно быть очень знакомо.RowОсновная ось компонента горизонтальна,ColumnОсновной осью сборки является продольное направление. И их конструкторы очень похожи (нечастые свойства опущены):

Row({
  Key key,
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
  MainAxisSize mainAxisSize = MainAxisSize.max,
  List<Widget> children = const <Widget>[],
})

Column({
  Key key,
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
  MainAxisSize mainAxisSize = MainAxisSize.max,
  List<Widget> children = const <Widget>[],
})

2.2.1 mainAxisAlignment

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

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

  • MainAxisAlignment.start
  • MainAxisAlignment.end
  • MainAxisAlignment.center
  • MainAxisAlignment.spaceBetween
  • MainAxisAlignment.spaceAround
  • MainAxisAlignment.spaceEvenly

2.2.2 crossAxisAlignment

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

Вот немного нужнообращать внимание:из-заColumnНаправление вторичной оси компонента (то есть горизонтальное) по умолчанию центрировано, поэтому его родительский контейнер не будет заполняться в горизонтальном направлении.CrossAxisAlignment.stretchТолько тогда может.

Кроме того, другие необязательные значения crossAxisAlignment:

  • crossAxisAlignment.start
  • crossAxisAlignment.end
  • crossAxisAlignment.center
  • crossAxisAlignment.stretch
  • crossAxisAlignment.baseline

2.2.3 mainAxisSize

Буквально это свойство относится к размеру на главной оси. На самом деле, это относится к тому, оборачивает ли он свое содержимое или заполняет родительский контейнер в направлении главной оси. Его необязательные значенияMainAxisSize.minа такжеMainAxisSize.max. Поскольку его значение по умолчанию равноMainAxisSize.max, поэтому размер по умолчанию в направлении главной оси должен максимально заполнять родительский контейнер.

2.2.4 Резюме

из-заRow/Columnкомпоненты и то, с чем мы знакомыFlex布局Очень похоже, поэтому очень легко начать работу практически без затрат на обучение.

2.3 Стек/Позиционирование (абсолютно позиционированные компоненты макета)

Макет с абсолютным позиционированием также часто используется в веб-разработке.FlutterТакже предоставляется соответствующая реализация компонента, которую необходимоStackа такжеPositionedКомпоненты используются вместе. Например, в приведенном ниже примере создается желтая коробка и размещаются 4 маленьких красных квадрата в ее четырех углах.StackКомпоненты — это абсолютно позиционированные контейнеры.Positionedкомпоненты проходятleft,top,right,bottomЗначения свойства в четырех направлениях определяют его положение в родительском контейнере.

Container(
  height: 100,
  color: Colors.yellow,
  child: Stack(
    children: <Widget>[
      Positioned(
        left: 10,
        top: 10,
        child: Container(width: 10, height: 10, color: Colors.red),
      ),
      Positioned(
        right: 10,
        top: 10,
        child: Container(width: 10, height: 10, color: Colors.red),
      ),
      Positioned(
        left: 10,
        bottom: 10,
        child: Container(width: 10, height: 10, color: Colors.red),
      ),
      Positioned(
        right: 10,
        bottom: 10,
        child: Container(width: 10, height: 10, color: Colors.red),
      ),
    ],
  ),
)

2.4 Текст (текстовый компонент)

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

const Text(
  this.data, {
  Key key,
  this.style,
  this.textAlign,
  this.softWrap,
  this.overflow,
  this.maxLines,
})
  • data: Отображаемая текстовая информация;
  • style: стиль текста,FlutterпредоставилTextStyleкласс, наиболее часто используемыйfontSize,fontWeight,color,backgroundColorа такжеshadowsчерез него задаются и другие свойства;
  • textAlign: Выравнивание текста, часто используемые необязательные значенияTextAlignизleft,right,centerа такжеjustify;
  • softWrap: переносится ли текст;
  • overflow: Когда текст переполняется, как с этим бороться (по умолчанию прямо обрезается). Необязательные значенияTextOverflowизclip,fade,ellipsisа такжеvisible;
  • maxLines: Если текст превышает максимальное количество строк и не был отображен, он будет отображаться в соответствии сoverflowСвойство определяет, как обрабатывается усечение.

FlutterизTextКомпоненты достаточно гибки, чтобы предоставлять нам различные свойства для настройки, но в целом нам нужны только следующие строки кода:

Text(
  '这是测试文本',
  style: TextStyle(
    fontSize: 13,
    fontWeight: FontWeight.bold,
    color: Color(0xFF999999),
  ),
)

В дополнение к вышеперечисленным сценариям применения иногда мы также сталкиваемся富文本потребности (например, фрагмент текста, для которого может потребоваться другой стиль шрифта). Например, в некоторых дизайнах пользовательского интерфейса часто встречается цена,соотношение знаков金额меньший размер шрифта. Для таких нужд можно использоватьFlutterкоторый предоставилText.richконструктор для создания соответствующего текстового компонента:

Text.rich(TextSpan(
  children: [
    TextSpan(
      '¥',
      style: TextStyle(
        fontSize: 12,
        color: Color(0xFFFF7528),
      ),
    ),
    TextSpan(
      '258',
      style: TextStyle(
        fontSize: 15,
        color: Color(0xFFFF7528),
      ),
    ),
  ]
))

2.5 Изображение (компонент изображения)

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

Image({
  Key key,
  @required this.image,
  this.width,
  this.height,
  this.color,
  this.fit,
  this.repeat = ImageRepeat.noRepeat,
})
  • image: Источник изображения, есть два наиболее часто используемых (AssetImageа такжеNetworkImage). использоватьAssetImageРаньше надо былоpubspec.yamlРесурсы изображения объявляются в файле до того, как их можно будет использовать; иNextworkImageВы можете указать сетевой адрес образа, который в основном используется при загрузке некоторых сетевых образов;
  • width: ширина изображения;
  • height: высота изображения;
  • color: Цвет фона картинки, который будет отображаться перед загрузкой сетевой картинки;
  • fit: 当我们希望图片根据容器大小进行适配而不是指定固定的宽高值时,可以通过该属性来实现。 Его необязательные значенияBoxFitизfill,contain,cover,fitWidth,fitHeight,noneа такжеscaleDown;
  • repeat: определяет, использовать ли эффект повтора, когда фактический размер изображения меньше указанного размера.

Кроме того,Flutterтакже обеспечиваетImage.networkа такжеImage.assetКонструкторы на самом деле являются синтаксическим сахаром. Например, следующие два фрагмента кода имеют одинаковый результат:

Image(
  image: NetworkImage('https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1402367109,4157195964&fm=27&gp=0.jpg'),
  width: 100,
  height: 100,
)

Image.network(
  'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1402367109,4157195964&fm=27&gp=0.jpg',
  width: 100,
  height: 100,
)

2.6 Icon(компонент значка)

IconСборка иконок чаще используется в повседневной разработке, чем картинка, которая чаще используется в повседневной разработке.FlutterЭто прямо встроенныйMaterialстилизованные значки (вы можетездесьпредварительный просмотр всех типов значков). Взгляните на конструктор:

const Icon(
  this.icon, {
  Key key,
  this.size,
  this.color,
})
  • icon: тип значка;
  • size: размер значка;
  • color: Цвет значка.

3. Макет реального боя

Благодаря введению в предыдущем разделе мы имеемContainer,Row,Column,Stack,Positioned,Text,Imageа такжеIconКомпоненты имеют предварительное понимание. Далее давайте углубим наше понимание и память на практическом примере.

3.1 Подготовка — типы данных

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

class PetCardViewModel {
  /// 封面地址
  final String coverUrl;

  /// 用户头像地址
  final String userImgUrl;

  /// 用户名
  final String userName;

  /// 用户描述
  final String description;

  /// 话题
  final String topic;

  /// 发布时间
  final String publishTime;

  /// 发布内容
  final String publishContent;

  /// 回复数量
  final int replies;

  /// 喜欢数量
  final int likes;

  /// 分享数量
  final int shares;

  const PetCardViewModel({
    this.coverUrl,
    this.userImgUrl,
    this.userName,
    this.description,
    this.topic,
    this.publishTime,
    this.publishContent,
    this.replies,
    this.likes,
    this.shares,
  });
}

3.2 Создание скелета и разделение макета

По данной визуальной карте мы можем разделить целое на 4 части:Cover,UserInfo,PublishContentа такжеInteractionArea. Для этого мы можем составить базовый скелет кода:

class PetCard extends StatelessWidget {
  final PetCardViewModel data;

  const PetCard({
    Key key,
    this.data,
  }) : super(key: key);

  Widget renderCover() {
    
  }

  Widget renderUserInfo() {
    
  }

  Widget renderPublishContent() {
  
  }

  Widget renderInteractionArea() {
   
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            blurRadius: 6,
            spreadRadius: 4,
            color: Color.fromARGB(20, 0, 0, 0),
          ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          this.renderCover(),
          this.renderUserInfo(),
          this.renderPublishContent(),
          this.renderInteractionArea(),
        ],
      ),
    );
  }
}

3.3 Площадь покрытия

Для того, чтобы лучше подчеркнуть эффект от картинки, сюда добавлена ​​маска, поэтому ее можно просто использовать здесьStack/Positionedмакет иLinearGradientСтруктура Gradient, Dom выглядит следующим образом:

code-cover.png

Widget renderCover() {
  return Stack(
    fit: StackFit.passthrough,
    children: <Widget>[
      ClipRRect(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
        child: Image.network(
          data.coverUrl,
          height: 200,
          fit: BoxFit.fitWidth,
        ),
      ),
      Positioned(
        left: 0,
        top: 100,
        right: 0,
        bottom: 0,
        child: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [
                Color.fromARGB(0, 0, 0, 0),
                Color.fromARGB(80, 0, 0, 0),
              ],
            ),
          ),
        ),
      ),
    ],
  );
}

3.4 Область информации о пользователе

Область пользовательской информации очень удобна для использованияRowа такжеColumnКомпоненты используются для макета.Структура Dom выглядит следующим образом:

code-user-info.png

Widget renderUserInfo() {
  return Container(
    margin: EdgeInsets.only(top: 16),
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Row(
          children: <Widget>[
            CircleAvatar(
              radius: 20,
              backgroundColor: Color(0xFFCCCCCC),
              backgroundImage: NetworkImage(data.userImgUrl),
            ),
            Padding(padding: EdgeInsets.only(left: 8)),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  data.userName,
                  style: TextStyle(
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                    color: Color(0xFF333333),
                  ),
                ),
                Padding(padding: EdgeInsets.only(top: 2)),
                Text(
                  data.description,
                  style: TextStyle(
                    fontSize: 12,
                    color: Color(0xFF999999),
                  ),
                ),
              ],
            ),
          ],
        ),
        Text(
          data.publishTime,
          style: TextStyle(
            fontSize: 13,
            color: Color(0xFF999999),
          ),
        ),
      ],
    ),
  );
}

3.5 Область публикации содержимого

С помощью упражнений пользовательского интерфейса в этой области мы можем практиковатьContainerКомпоненты установлены по-разномуborderRadius,так же какTextОбработка усечения, когда текстовое содержимое компонента превышает структуру Dom, выглядит следующим образом:

code-publish-content.png

Widget renderPublishContent() {
  return Container(
    margin: EdgeInsets.only(top: 16),
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          margin: EdgeInsets.only(bottom: 14),
          padding: EdgeInsets.symmetric(horizontal: 8, vertical: 2),
          decoration: BoxDecoration(
            color: Color(0xFFFFC600),
            borderRadius: BorderRadius.only(
              topRight: Radius.circular(8),
              bottomLeft: Radius.circular(8),
              bottomRight: Radius.circular(8),
            ),
          ),
          child: Text(
            '# ${data.topic}',
            style: TextStyle(
              fontSize: 12,
              color: Colors.white,
            ),
          ),
        ),
        Text(
          data.publishContent,
          maxLines: 2,
          overflow: TextOverflow.ellipsis,
          style: TextStyle(
            fontSize: 15,
            fontWeight: FontWeight.bold,
            color: Color(0xFF333333),
          ),
        ),
      ],
    ),
  );
}

3.6 Интерактивная область

В этом модуле мы будем использоватьIconКомпонент Icon, вы можете управлять его свойствами, такими как размер и цвет, структура Dom выглядит следующим образом:

code-interaction-area.png

Widget renderInteractionArea() {
  return Container(
    margin: EdgeInsets.symmetric(vertical: 16),
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Row(
          children: <Widget>[
            Icon(
              Icons.message,
              size: 16,
              color: Color(0xFF999999),
            ),
            Padding(padding: EdgeInsets.only(left: 6)),
            Text(
              data.replies.toString(),
              style: TextStyle(
                fontSize: 15,
                color: Color(0xFF999999),
              ),
            ),
          ],
        ),
        Row(
          children: <Widget>[
            Icon(
              Icons.favorite,
              size: 16,
              color: Color(0xFFFFC600),
            ),
            Padding(padding: EdgeInsets.only(left: 6)),
            Text(
              data.likes.toString(),
              style: TextStyle(
                fontSize: 15,
                color: Color(0xFF999999),
              ),
            ),
          ],
        ),
        Row(
          children: <Widget>[
            Icon(
              Icons.share,
              size: 16,
              color: Color(0xFF999999),
            ),
            Padding(padding: EdgeInsets.only(left: 6)),
            Text(
              data.shares.toString(),
              style: TextStyle(
                fontSize: 15,
                color: Color(0xFF999999),
              ),
            ),
          ],
        ),
      ],
    ),
  );
}

3.7 Резюме

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

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

4. Резюме

Эта статья впервые знакомитFlutterНаиболее часто используемые базовые компоненты для создания UI-интерфейсов (容器,,,绝对定位布局,文本,图片а также图标)Применение. Далее представлен более сложный пример боя с пользовательским интерфейсом. Благодаря поэтапному разбору структуры Домов всесторонне использовались упомянутые выше компоненты, что можно рассматривать как закрепление ранее изученных концептуальных знаний.

Но в конце концов я должен выплюнуть:FlutterГнездование действительно сложное. . . Без модуля, разделяющего макет пользовательского интерфейса, это был бы абсолютный кошмар. И в отличие от стиля разработки web/rn, который можно выделить отдельно,FlutterТакой подход к обработке стилей как атрибутов затрудняет понимание структуры DOM с первого взгляда, а разработчикам, которые плохо знакомы с кодом, требуется некоторое время для понимания. . .

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