avatar

Catalog
Flutter学习笔记3 - 基础控件

Widget

在Flutter里,所有UI控件都叫Widget,包括基本的文本、按钮、图片,还有容器、布局,以及动画等等都通过Widget抽象类实现的。

Widget下面可分为两种子类,一种是无状态的,继承自StatelessWidget,只负责展示信息,没有交状态变化。StatelessWidget的构造方法只有一个BuildContext参数,context记录了widget树的上下文信息,可以通过context查找到指定特征的widget。

class TestWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Widget();
  }
}

另一种是有状态的,继承自StatefulWidget,它比StatelessWidget多了一个State参数,State记录了widget的各种状态信息,当State发现变化时,会调用setState()方法通知Flutter framework,再次调用build方法重新构建widget树,从而达到更新UI的目的。

class TestWidget extends StatefulWidget {
  
  State createState() {
    return _ControlWidgetState();
  }
}

class _ControlWidgetState extends State<TestWidget> {
  int _counter = 0;
  
  Widget build(BuildContext context) {
        return Center(
        child: RaisedButton(
          child: Text("button " + _counter),
        onPressed: (){
          setState((){    // 调用setState()后build()方法会被重新调用
            _counter++;
          })
        }
      )
    );
  }
}

文本展示

Flutter提供的文本展示控件叫Text,可以设置文本字体大小、粗细、颜色等样式。Text控件不能指定自身尺寸,其宽高根据内容自适应。另外,还可以使用TextSpan组合不同样式的文本。

Text常用参数

const Text(
  ...
  this.data, {// 文本内容
  this.style, // 文本样式,包括字体大小、颜色、粗细、背景色等
  this.textAlign, // 对齐方式
  this.overflow,  // 设置文本截断方式
  this.textScaleFactor, // 放大倍数
  this.maxLines, // 最大行数,默认是1
  ...
})

TextStyle常用参数

const TextStyle({
    ...
  this.color,    // 字体色
  this.backgroundColor, // 背景色
  this.fontSize, // 字体大小
  this.fontWeight, // 粗细
  this.letterSpacing, // 字母间距
  this.height,    // 行高
  this.background, // 背景色
    this.shadows, // 阴影
    String fontFamily, // 字体
    ...
  })

TextSpan常用参数

const TextSpan({
  TextStyle style, // 通用样式
  Sting text,
  List<TextSpan> children, // 嵌套子TestSpan,
  GestureRecognizer recognizer, // 响应的手势
});

示例代码

Text(
  "Hello world! " * 10,
  maxLines: 3,    
  textAlign: TextAlign.left,
  textScaleFactor: 1.5, 
    style: TextStyle(
        color: Colors.blue,
        fontSize: 17.0,
        fontWeight: FontWeight.bold,
    )
);

Text.rich(TextSpan(
  style: TextStyle(
      fontSize: 20.0,
  )
    children: <Widget> [
    TextSpan(
    text: "Domain:"
    ),
    TextSpan(
        text: "https://www.songjiaqiang.cn",
      style: TextStyle(
          color: Colors.blue
      ),
      recognizer: _tapRecognizer
    )
  ]
));

图片展示

Flutter提供的图片展示控件有两个,一个是Icon,用于展示内置的矢量图标,另一个是Image ,用于加载标量图片。

Image

系统内置了四种加载图片的方式,分别是项目资源,磁盘文件、网络、内存。

Image常用参数

const Image({
  ...
  this.width, //图片的宽
  this.height, //图片高度
  this.color, //图片的混合色值
  this.colorBlendMode, //混合模式
  this.fit, //填充模式
  this.alignment = Alignment.center, //对齐方式
  this.repeat = ImageRepeat.noRepeat, //重复方式
  ...
})

图片填充模式

enum BoxFit {
  none,    // 按图片真实尺寸显示
  fill, // 拉伸图片填充容器
  contain, // 完全显示在容器内,如果图片尺寸比容器小,放大图片
  scaleDown, // 完全显示在容器内,如果图片尺寸比容器小,不放大
  cover, // 图片缩放到正好可以覆盖容器的大小
  fitWidth, // 图片水平方向填充容器,垂直方向等比缩放
  fitHeight, // 图片垂直方向填充容器,水平方向等比缩放
}

加载图片方式

Image.asset("asset/path");
Image.file("/file/path");
Image.network("http://domain.com/image/url");
Image.memory(bytes) //  AssetBundle().load("/file/path"); byteData.buffer.asUint8List();

代码示例

Image.network( // 默认最大缓存数量是1000,最大缓存空间为100M,不做数据持久化
  "https://res.klook.com/image/upload/v1464854586/web3.0/mobile.jpg",
  width: 200,
  height: 100,
  fit: BoxFit.fill,
  color: Colors.blue,
  colorBlendMode: BlendMode.difference,
)

Icon

Icon是一种字体图标,可以像字体一样设置文本样式,也可以通过TextSpan和文本混用,相对于Image具有体积小,矢量性的好处。

系统提供了一套Material风格的字体图标,可在pubspec.yaml文件配置启用。

flutter:
  uses-material-design: true

自定义图标字体

Step1:导入图片字体文件到工程目录,比如”fonts/iconfont.ttf”

Setp2:在pubspec.yaml文件配置自定义字体

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

Step3:创建图标引用工具类

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
  );
}

Step4:使用字体图标

Icon(Icons.accessible, color: Colors.green),
Icon(MyIcons.book, color: Colors.blue,),

按钮

Flutter提供了多个基本的Material按钮控件,比如FlatButtonRaiseButtonIconButton。可以设置按钮的基本样式和按压事件onPressed,自带icon构造函数可以直接设置带图标的按钮,自定义按钮内部布局可以使用child参数配置。

常用参数

const RaisedButton({
     VoidCallback onPressed, // 点击事件
    VoidCallback onLongPress,     // 长按事件
    Color textColor, //文本颜色
    Color disabledTextColor, // enabled=false时的文本颜色
    Color color,  // 按钮颜色
    Color disabledColor,  // enabled=false时的按钮颜色 
    Color highlightColor, // 高亮状态的按钮颜色
    EdgeInsetsGeometry padding, //内边距
    Widget child, //子控件
  }) 

代码示例

RaisedButton(
    child: Text("Button"),
    onLongPress: () => print("Loog Pressed Button"),
),

FlatButton.icon(
  icon: Icon(Icons.info),
  label: Text("Info"),
    onPressed: () => print("Pressed Button"),
),

输入框

Flutter提供的文本输入框叫TextField,通过InputDecoration设置文本的信息,通过TextEditingController监听文本框事件。

TextField的基础参数

const TextField({
  ...
  TextEditingController controller, // 编辑框控制器
  FocusNode focusNode, // 键盘焦点
  InputDecoration decoration = const InputDecoration(), // 编辑框样式,设置占位符
  TextInputType keyboardType, // 键盘类型
  TextStyle style, // 文本样式
  TextAlign textAlign = TextAlign.start, // 对齐方式
  bool autofocus = false, // 是否获得焦点
  bool obscureText = false, // 是否隐藏正在编辑的文本,用于密码输入
  int maxLines = 1, // 最大显示行数
  int maxLength, // 最大输入长度
  bool maxLengthEnforced = true,
  ValueChanged<String> onChanged, // 文本内容变化回调
  VoidCallback onEditingComplete, // 编辑结束回调
  List<TextInputFormatter> inputFormatters, // 校验输入内容格式
  bool enabled, // 是否可编辑
  this.cursorWidth = 2.0, // 光标宽度
  this.cursorRadius, // 光标圆角
  this.cursorColor, // 光标颜色
  ...
})

代码示例

class MessageForm extends StatefulWidget {
  
  State createState() {
    return _MessageFormState();
  }
}

class _MessageFormState extends State<MessageForm> {
  var _editController = TextEditingController();

  
  Widget build(BuildContext context) {
    return Column(
      mainAxisAignment: MainAxisAlignment.center,
      children: <Widget>[
        TextField(
          controller: _editController, // 需要控制器负责监听输入内容
          decoration: InputDecoration(
              hintText: 'Type something',
          ),
        ),
        RaisedButton(
            onPressed: () {
            print('_controller.text');
          }
          child: Text('Done'),
        ),
      ],
    );
  }

   
  void dispose() {
    super.dispose();
    _editController.dispose();
  }
}

弹窗

Flutter提供的弹窗控件叫AlertDialog,可以设置标题、内容、按钮等属性,使用导航pop()方法退出。

常用参数

const AlertDialog({
  Key key,
  this.title, //对话框标题组件
  this.titlePadding, // 标题填充
  this.titleTextStyle, //标题文本样式
  this.content, // 对话框内容组件
  this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0), //内容的填充
  this.contentTextStyle,// 内容文本样式
  this.actions, // 对话框操作按钮组
  this.backgroundColor, // 对话框背景色
  this.elevation,// 对话框的阴影
  this.semanticLabel, //对话框语义化标签(用于读屏软件)
  this.shape, // 对话框外形
})

示例代码

class TestWidget extends StatelessWidget {

  
  Widget build(BuildContext context) {
    return Column(
      mainAxisAignment: MainAxisAlignment.center,
      children: <Widget>[
        RaisedButton(
          child: Text('Done'),
            onPressed: () {
            showDialog(
                context: context,
                builder: (_) {    // 
                  return AlertDialog(    // 
                    title: Text('Title'),
                      content: Text('This is a Dialog'),
                      actions: <Widget> [
                        FlatButton(
                            child: Text('Cancel'),
                            onPressed: () => Navigator.of(context).pop(),
                        ),
                           FlatButton(
                            child: Text('OK'),
                            onPressed: () => Navigator.of(context).pop(),
                        ),
                      ],
                    ),
              }
            );
          },
        ),
      ],
    );
  }
}

更多控件

Flutter还提供了很多基础控件,比如单选框Switch、复选框Checkbox、进度指示器LinearProgressIndicator等等,就不一一列举了。

不过Flutter很多控件平时是用不到的,因此也被认为是过度设计了。

参考资料

Flutter中文网:https://book.flutterchina.club/chapter3/

Flutter学习指南 - UI布局和控件:https://juejin.im/post/5bd54b7be51d456c430e35f6

获取图片bytes:https://github.com/flutter/flutter/issues/17038

颜色混合模式:https://wenku.baidu.com/view/11635cf3ba0d4a7302763a95.html?re=view

Material Design Icons:https://material.io/resources/icons/?style=baseline

Author: 若鱼
Link: http://songjiaqiang.com/2020/02/05/007-learning-flutter-3-base-widget/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment