Flutter系列教程第一章:基础组件

188 阅读7分钟

一、文本组件-Text

1.1 Text

用于显示文本,控制文本的显示样式,下边几个例子

      Text('hello flutter'),
      Text(
        'hello flutter',
        textAlign: TextAlign.left,
      ),
      Text(
        'Hello Flutter i am tom' * 4,
        overflow: TextOverflow.ellipsis,
      ),
      Text(
        'Hello Flutter',
        textScaler: TextScaler.linear(1.5),
      ),
      Text(
        'Hello Flutter',
        style: TextStyle(
          fontSize: 30,
        ),
      ),
  • textAlign 控制文本位置 left/right/center
  • maxLinesoverflow 控制文本超出时显示方式
  • style 控制文本:大小、颜色、字体 等

1.2 TextSpan

Text组件内的文本只能一种样式如果想多种样式,就得用TextSpan,当然你也可以text里边嵌套text,看你的使用场景

      Text.rich(TextSpan(children: [
        TextSpan(text: "Home: "),
        TextSpan(
            text: "https://flutterchina.club",
            style: TextStyle(color: Colors.blue),
            recognizer: null),
      ]))

image.png

二、按钮组件-Button

Material 组件库中提供了多种按钮组件如ElevatedButtonTextButtonOutlinedButton,所有 Material 库中的按钮都有如下相同点:

  1. 按下时都会有“水波动画”(又称“涟漪动画”,就是点击时按钮上会出现水波扩散的动画)。
  2. 有一个onPressed属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

2.1 ElevatedButton 悬浮按钮

默认有个灰色背景以及边框

2.2 TextButton 文本按钮

2.3 OutlinedButton

带边框背景透明

2.4 IconButton

2.5 带图标的按钮

ElevatedButtonTextButtonOutlinedButton都有一个icon 构造函数,通过它可以轻松创建带图标的按钮

      ElevatedButton(onPressed:_onPressed,child: Text("ElevatedButton")),
      TextButton(onPressed: _onPressed, child: Text("TextButton")),
      OutlinedButton(onPressed: _onPressed, child: Text("OutlinedButton")),
      IconButton(onPressed: _onPressed, icon: Icon(Icons.thumb_up)),
      ElevatedButton.icon(
        onPressed: _onPressed,
        icon: Icon(Icons.send),
        label: Text("发送"),
      ),

image.png

三、图片组件-Image 图标-Icon

3.1 加载本地图片

  • 在工程根目录下创建一个images目录,并将图片 avatar.png 拷贝到该目录。
  • pubspec.yaml中的flutter部分添加如下内容:
assets:
    - images/avatar.png

注意: 由于 yaml 文件对缩进严格,所以必须严格按照每一层两个空格的方式进行缩进,此处 assets 前面应有两个空格。

  • 加载该文件 Image.network('images/avatar.png', width: 100.0),

3.2 加载网络图片

Image.network(src)
可以设置加载图片的 宽、高、对齐方式、重复方式等

image.png

3.3 使用图标

Flutter默认包含了一套Material Design的字体图标,在pubspec.yaml文件中的配置如下

flutter:
  uses-material-design: true

使用图标Icon(Icons.business)
官网图标可以在这里查询

使用自定义图标

我们也可以使用自定义字体图标。iconfont.cn上有很多字体图标素材,我们可以选择自己需要的图标打包下载后,会生成一些不同格式的字体文件,在Flutter中,我们使用ttf格式即可。

fonts:
  - family: myIcon  #指定一个字体名
    fonts:
      - asset: fonts/iconfont.ttf

注意缩进 为了使用方便,我们定义一个MyIcons类,功能和Icons类一样:将字体文件中的所有图标都定义成静态变量:

class MyIcons{
  // book 图标
  static const IconData book = const IconData(
      0xe614, 
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
  // 微信图标
  static const IconData wechat = const IconData(
      0xec7d,  
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
}

使用图标

Icon(MyIcons.book,color: Colors.purple),
Icon(MyIcons.wechat,color: Colors.green),

四、单选-Radio 复选-Checkbox

Material 组件库中提供了 Material 风格的单选开关Switch和复选框Checkbox,虽然它们都是继承自StatefulWidget,但它们本身不会保存当前选中状态,选中状态都是由父组件来管理的。当SwitchCheckbox被点击时,会触发它们的onChanged回调,我们可以在此回调中处理选中状态改变逻辑。下面看一个简单的例子:

import 'package:flutter/material.dart';

class MyView extends StatefulWidget {
  const MyView({super.key});
  @override
  State<MyView> createState() => _MyViewState();
}

class _MyViewState extends State<MyView> {
  bool _switchCheck = false;
  bool _checkboxCheck = false;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Switch(
          value: _switchCheck,
          onChanged: (value) {
            setState(() {
              _switchCheck = value;
              print(_switchCheck);
            });
          },
        ),
        Checkbox(
          value: _checkboxCheck,
          onChanged: (value) {
            setState(() {
              _checkboxCheck = value ?? false;
              print(_checkboxCheck);
            });
          },
        ),
      ],
    );
  }
}

这里注意一个事情,在dart语言中bool类型的值可以被定义成?,也就是null,那么就有三种状态true、false和null,checkbox的返回值value就是这种情况,所以要处理下,它有个参数tristate,就是用来设置是否有三种状态,默认是false,activeColor可以设置激活时颜色

四、输入组件-TextField 表单组件-Form

4.1、TextField TextFormField

习惯了双向数据绑定,其实写flutter还是感觉挺麻烦的。下边是第一种获取输入框的值

class _MyViewState extends State<MyView> {
  String _name = '';
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
            onChanged: (value) {
              setState(() {
                _name = value;
                print(_name);
              });
            },
            decoration: InputDecoration(
              labelText: 'Name',
              hintText: 'Enter your name',
              prefixIcon: Icon(Icons.person),
            )),
      ],
    );
  }
}

第二种通过TextEditingController创建,并监听值变化,这种方式较第一种功能稍强大些,可以自定义设置很多属性

class _MyViewState extends State<MyView> {
  final TextEditingController _controller = TextEditingController();
  
  @override
  void initState() {
    _controller.text = 'Hello';
    _controller.addListener(() {
      print(_controller.text);
    });
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          controller: _controller,
          decoration: InputDecoration(
            labelText: 'Name',
            hintText: 'Enter your name',
            prefixIcon: Icon(Icons.person),
          )
        ),
      ],
    );
  }
}

关于它的属性有很多下边列举几个常用的

  • controller:编辑框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显式提供一个controller来与文本框交互。如果没有提供controller,则TextField内部会自动创建一个。
  • focusNode:用于控制TextField是否占有当前键盘的输入焦点。它是我们和键盘交互的一个句柄(handle)。
  • InputDecoration:用于控制TextField的外观显示,如提示文本、背景颜色、边框等。
  • keyboardType:用于设置该输入框默认的键盘输入类型,取值如下:
TextInputType枚举值含义
text文本输入键盘
multiline多行文本,需和maxLines配合使用(设为null或大于1)
number数字;会弹出数字键盘
phone优化后的电话号码输入键盘;会弹出数字键盘并显示“* #”
datetime优化后的日期输入键盘;Android上会显示“: -”
emailAddress优化后的电子邮件地址;会显示“@ .”
url优化后的url输入键盘; 会显示“/ .”
textInputAction:键盘动作按钮图标(即回车键位图标),它是一个枚举值,有多个可选值,全部的取值列表读者可以查看API文档
  • style:正在编辑的文本样式。
  • textAlign: 输入框内编辑文本在水平方向的对齐方式。
  • autofocus: 是否自动获取焦点。
  • obscureText:是否隐藏正在编辑的文本,如用于输入密码的场景等,文本内容会用“•”替换。
  • maxLines:输入框的最大行数,默认为1;如果为null,则无行数限制。
  • maxLengthmaxLengthEnforcement :maxLength代表输入框文本的最大长度,设置后输入框右下角会显示输入的文本计数。maxLengthEnforcement决定当输入文本长度超过maxLength时如何处理,如截断、超出等。
  • toolbarOptions:长按或鼠标右击时出现的菜单,包括 copy、cut、paste 以及 selectAll。
  • onChange:输入框内容改变时的回调函数;注:内容改变事件也可以通过controller来监听。
  • onEditingCompleteonSubmitted:这两个回调都是在输入框输入完成时触发,比如按了键盘的完成键(对号图标)或搜索键(🔍图标)。不同的是两个回调签名不同,onSubmitted回调是ValueChanged<String>类型,它接收当前输入内容做为参数,而onEditingComplete不接收参数。
  • inputFormatters:用于指定输入格式;当用户输入内容改变时,会根据指定的格式来校验。
  • enable:如果为false,则输入框会被禁用,禁用状态不能响应输入和事件,同时显示禁用态样式(在其decoration中定义)。
  • cursorWidthcursorRadiuscursorColor:这三个属性是用于自定义输入框光标宽度、圆角和颜色的。

4.2、表单验证

Form组件,需要设置一个key,验证时用来拿到form表单元素,同时TextFormField要添加validator属性,下边是个例子

class _MyViewState extends State<MyView> {
  String _name = '';
  final GlobalKey _formKey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context) {
    return Form(
        key: _formKey,
        child: Column(
          children: [
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Name',
              ),
              onChanged: (value) {
                setState(() {
                  _name = value;
                });
              },
              validator: (value) {
                return value!.trim().length > 5 ? null : 'Name is required';
              },
            ),
            ElevatedButton(
              onPressed: () {
                // if ((_formKey.currentState as FormState).validate()) {
                //   //验证通过提交数据
                // } else {}
                final snackBar = SnackBar(
                  content: const Text('Yay! A SnackBar!'),
                );

                // Find the ScaffoldMessenger in the widget tree
                // and use it to show a SnackBar.
                ScaffoldMessenger.of(context).showSnackBar(snackBar);
              },
              child: Text('Submit'),
            ),
          ],
        ));
  }
}