阅读 69

Flutter-常用Widget

前言

从上一篇中主要了解了Flutter环境的搭建,以及ListView的简单使用,这篇中将继续熟悉一下其他的一些Widget

工程创建

首先创建一个工程,这里可以通过Android Studio或者命令行创建,进入到工程的目录路径,命令行如下:

# -i:iOS 
# objc:选择Objective-C语言,这里不选择语言,iOS默认是Swift,Android默认的是Kotlin
flutter create -i objc flutter_demo复制代码

创建工程以后会在lib/main.dart默认生成一些简单的UI样式,运行看一下效果(这里打开的是iPhone的模拟器)。 01.png 从运行结果可以看到文字和按钮的显示,点击按钮计数会增加。下面我们删掉原来的代码,然后自定义一些Widget玩玩,看看效果,为了使代码不要太乱,下面一个Widget创建一个dart文件分开。

常用Widget

lib文件目录下再创建一个views目录。删掉之前的代码,下面是main.dart的代码。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: Container(),
      ),
    );
  }
}复制代码

Text

创建一个StatelessWidgettext_widget.dart文件放在views里,首先看一下Text的一些属性。

const Text(
  String this.data, {
  Key? key,
  this.style,
  this.strutStyle,
  this.textAlign,
  this.textDirection,
  this.locale,
  this.softWrap,
  this.overflow,
  this.textScaleFactor,
  this.maxLines,
  this.semanticsLabel,
  this.textWidthBasis,
  this.textHeightBehavior,
})复制代码

可以对Text设置样式,对齐方式,文字方向,最大行数等等。可以简单的设置一些属性

import 'package:flutter/material.dart';

class TextWidget extends StatelessWidget {
  const TextWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Text(
      'Flutter 是 Google 发布的一个用于创建跨平台、高性能移动应用的框架。Flutter 和 Qt mobile 一样,都没有使用原生控件,相反都实现了一个自绘引擎,使用自身的布局、绘制系统。',
      textAlign: TextAlign.center,
      style: TextStyle(
        fontSize: 16.0,
        color: Colors.red,
      ),
    );
  }
}复制代码

main.dartContainer替换刚创建的TextWidget,再运行。 02.png 如果要设置最大行数,然后多余的用...的方式,可以设置maxLineoverflow属性。完成后点击Hot reload就可以看到效果了。 03.png

RichText

在文本样式里经常会用到富文本,Flutter中提供了富文本的Widget就是RichText,看看RichText的属性定义

RichText({
  Key? key,
  required this.text,
  this.textAlign = TextAlign.start,
  this.textDirection,
  this.softWrap = true,
  this.overflow = TextOverflow.clip,
  this.textScaleFactor = 1.0,
  this.maxLines,
  this.locale,
  this.strutStyle,
  this.textWidthBasis = TextWidthBasis.parent,
  this.textHeightBehavior,
})复制代码

要求传的text这里传TextSpanTextSpanText的区别是有children属性,所以可以做嵌套,这样就是可以对文本设置不同的样式。

const TextSpan({
  this.text,
  this.children,
  TextStyle? style,
  this.recognizer,
  MouseCursor? mouseCursor,
  this.onEnter,
  this.onExit,
  this.semanticsLabel,
  this.locale,
  this.spellOut,
})复制代码

把之前的代码用RichText里嵌套TextSpan稍改一下,然后运行,就实现了简单的富文本效果。 04.png

Container

再创建一个container_demo.dart文件,返回一个ContainerWidget,然后引入到mainbody里,我们给Container设置个颜色,运行。 01.png 可以看到整个bodyContainer占满,它是个弹性布局,我们在Container里面放个Row,然后再嵌套个Icon,代码如下:

import 'package:flutter/material.dart';

class ContainerDemo extends StatelessWidget {
  const ContainerDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Row(
        children: [
          Container(
            color: Colors.red,
            child: const Icon(Icons.add),
          ),
        ],
      ),
    );
  }
}复制代码

再次运行。 02.png 可以看到之前黄色占满bodyContainer变小了,所以如果Container不设置宽度和高度会受到子部件的大小影响。接着看一下Container的属性:

Container({
  Key? key,
  this.alignment,
  this.padding,
  this.color,
  this.decoration,
  this.foregroundDecoration,
  double? width,
  double? height,
  BoxConstraints? constraints,
  this.margin,
  this.transform,
  this.transformAlignment,
  this.child,
  this.clipBehavior = Clip.none,
}) 
复制代码
margin & padding

在上面的代码中再设置一下paddingmargin,看一下效果,代码如下: 03.png 红色Container到加号图标的距离是30,也就是内边距padding属性,红色Container到黄色的距离是20,也就是外边距margin属性。

alignment

上面的Container内嵌套了RowRow是横向占满屏幕的,现在删除之前的Row,在Container内放一个Text,然后设置它的alignment(值的范围是从-1~1),再次运行看一下效果。 Container.gif 通过alignment可以设置元素的坐标点。

Row

Row是一个横向布局的Widget,横向会占满屏幕,纵向会根据子部件的大小弹性布局,接下来再创建一个row_demo.dart,在Row里放置3个Icon,也设置alignment为(0, 0),代码如下:

import 'package:flutter/material.dart';

class RowDemo extends StatelessWidget {
  const RowDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: const Alignment(0, 0),
      color: Colors.yellow,
      child: Row(
        children: [
          Container(
            child: const Icon(Icons.add, size: 45,),
            color: Colors.red,
          ),
          Container(
            child: const Icon(Icons.ac_unit, size: 45,),
            color: Colors.blue,
          ),
          Container(
            child: const Icon(Icons.access_alarm, size: 45,),
            color: Colors.white,
          ),
        ],
      ),
    );
  }
}复制代码

接下来运行看一下效果 04.png 可以看到图标在横向是靠左边的,纵向是中心位置,因为Row是占满横向的,所以对于Row来说alignment设置x轴方向是无效的,同样对于Column设置y轴方向是无效的。

Column

Column是一个纵向布局的Widget,纵向占满屏幕,横向会根据子部件大小自动布局,把上面的代码的Row改成Column,运行。 05.png

Stack

Stack是一个层叠布局的Widget,从内层忘外层布局,如果各个子部件的大小一致,外层Widget会覆盖内层的Widget,还是上面的代码,只是改成Stack,运行。 06.png 可以看到只显示最后面添加的alarmIcon图标,我们把每个子Widget的大小,这样就更直观一点。 07.png 更改大小后,可以看到Stack的子部件是堆叠显示的。

主轴和交叉轴

RowColumnStack都有主轴交叉轴的概念,也就是mainAxisAlignmentcrossAxisAlignment属性,横向布局主轴方向是往右的,纵向布局主轴方向是往下的,层叠布局主轴方向是往外的,交叉轴是主轴的垂直方向。

mainAxisAlignment

先看一下MainAxisAlignment的定义。

enum MainAxisAlignment {
  start,
  end,
  center,
  spaceBetween,
  spaceAround,
  spaceEvenly,
}复制代码

前三个很好理解,start是默认的从开始方向,end是从结束方向开始,center是中间位置。我们以Row作为例子,分别在这3种方式运行看看效果。 demo.gif 下面再看一下spaceBetweenspaceAroundspaceEvenly的效果都是什么样的? demo.gif 根据运行效果可以看到:

  • spaceBetween: 剩下的空间平均分布到小部件之间。

  • spaceAround: 剩下的空间平均分布到小部件周围。

  • spaceEvenly: 剩下的空间和小部件一起平均分。

crossAxisAlignment

看一下CrossAxisAlignment的定义。

enum CrossAxisAlignment {
  start,
  end,
  stretch,
  baseline,
}复制代码

直接加上crossAxisAlignment相关属性运行看一下效果。 demo.gif 前3个属性运行都正常,但改为baseline运行报错了,这里baseline属性要配合Row组件的textBaseline属性使用,代码如下:

Widget build(BuildContext context) {
  return Container(
    alignment: const Alignment(0, 0),
    color: Colors.yellow,
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.baseline,
      textBaseline: TextBaseline.alphabetic,
      children: [
        Container(
          child: const Icon(Icons.add, size: 120,),
          color: Colors.red,
        ),
        Container(
          child: const Icon(Icons.ac_unit, size: 60,),
          color: Colors.blue,
        ),
        Container(
          child: const Icon(Icons.access_alarm, size: 30,),
          color: Colors.white,
        ),
      ],
    ),
  );
}复制代码

再次运行,可以看到和end效果一样。 01.png 这时我们把Icon改成Text,并把文字大小设置成不一样,再看效果。 02.png 可以看到所有文字的底部的对齐的。

  • start: 开始位置对齐。

  • end: 结束位置对齐。

  • stretch: 交叉轴方向占满屏幕。

  • baseline: 需要配合textBaseline使用,文字底部对齐。

Expanded

接下来把之前Rowchildren内的子部件再嵌套在Expanded里,看一下效果。 03.png 子控件占满主轴方向,如果主轴方向放不下会自动换行。

  • Expanded: 在主轴方向不会剩下间隙,将被Expanded拉伸。

总结

通过这篇对Flutter常用的Widget做了了解,也在实际运行后看不同Widget对应属性的使用的改变,根据这些Widget的使用做个简单的总结。

  • Text控件的使用,以及RichText富文本控件的使用。

  • Container的用法,Alignment的参数xy

  • RowColumn,认识了主轴和交叉轴的概念。

  • Stack的用法,层叠显示。

  • Expanded,填充Widget,可以占满父组件。

文章分类


作者:Atom
链接:https://juejin.cn/post/7025196336253239303

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐