【Flutter】 自学(三)-Flutter基础组件

762 阅读11分钟

文本

		Text(
              'Hello World Hello WorldHello WorldHello WorldHello WorldHello WorldHello 			WorldHello WorldHello WorldHello WorldHello World',
              //对齐方式
              textAlign: TextAlign.center,
              //最大行数
              maxLines: 2,
              //超过最大行数显示规则
              overflow: TextOverflow.ellipsis,
              //文本缩放
              textScaleFactor: 1.4,
              //设置颜色,大小之类的不能直接设置,需要使用style
              style: TextStyle(
                  //设置文本大小
                  fontSize: 20,
                  //设置文本颜色,也可以自定义
                  // color: Colors.white,
                  // 自定义颜色 16进制 前两位是透明度,后6位是颜色值
                  color: const Color(0xffffffff),
                  //设置字体
                  fontFamily: 'yahei',
                  //背景
                  backgroundColor: Colors.red,
                  //下划线
                  decoration: TextDecoration.underline,
                  //下划线样式
                  decorationStyle: TextDecorationStyle.dashed),
            )

Text属性

  • textAlign : 文本的对齐方式;可以选择左对齐、右对齐还是居中。注意,对齐的参考系是Text widget本身,只有Text宽度大于文本内容长度时指定此属性才有意义
  • maxLines、overflow:指定文本显示的最大行数,默认情况下,文本是自动折行的,如果指定此参数,则文本最多不会超过指定的行。如果有多余的文本,可以通过overflow来指定截断方式,默认是直接截断,本例中指定的截断方式TextOverflow.ellipsis,它会将多余文本截断后以省略符“...”表示;TextOverflow的其它截断方式请参考SDK文档。
  • textScaleFactor:代表文本相对于当前字体大小的缩放因子,相对于去设置文本的样式style属性的fontSize,它是调整字体大小的一个快捷方式。该属性的默认值可以通过MediaQueryData.textScaleFactor获得,如果没有MediaQuery,那么会默认值将为1.0。

TextStyle属性

  • height:该属性用于指定行高,但它并不是一个绝对值,而是一个因子,具体的行高等于fontSize*height。
  • fontFamily :由于不同平台默认支持的字体集不同,所以在手动指定字体时一定要先在不同平台测试一下。
  • fontSize:该属性和Text的textScaleFactor都用于控制字体大小。但是有两个主要区别:

fontSize可以精确指定字体大小,而textScaleFactor只能通过缩放比例来控制。 textScaleFactor主要是用于系统字体大小设置改变时对Flutter应用字体进行全局调整,而fontSize通常用于单个文本,字体大小不会跟随系统字体大小变化。

TextSpan

//一段文字分段控制
            Text.rich(TextSpan(children: [
              TextSpan(text: '主页', style: TextStyle(fontSize: 25)),
              TextSpan(
                  text: 'www.baidu.com',
                  style: TextStyle(
                    fontSize: 18,
                    color: Colors.blue,
                  ))
            ])),

通用样式

 //设置一个通用样式
    const commonStyle = TextStyle(
      fontSize: 28,
      fontFamily: 'yahei',
      color: Colors.blue,
    );
	Text(
              '通用样式',
              textAlign: TextAlign.left,
              style: commonStyle,
            )

按钮

            //即"漂浮"按钮,它默认带有阴影和灰色背景。按下后,阴影会变大
            RaisedButton(
              child: Text("RaisedButton"),
              onPressed: () => {
                print('RaisedButton onPressed'),
              },
            ),
            //即扁平按钮,默认背景透明并不带阴影。按下后,会有背景色
            FlatButton(
              onPressed: () => {},
              child: Text('FlatButton'),
            ),
            //默认有一个边框,不带阴影且背景透明。按下后,边框颜色会变亮、同时出现背景和阴影(较弱)
            OutlineButton(
              child: Text("OutlineButton"),
              onPressed: () {},
            ),
            //图标按钮
            IconButton(
              icon: Icon(Icons.add),
              onPressed: () {},
            ),
            //带图标的按钮
            RaisedButton.icon(
              icon: Icon(Icons.send),
              label: Text("发送"),
              onPressed: () {},
            ),
            //自定义按钮
            FlatButton(
              //颜色
              color: Colors.blue,
              //高亮 按下
              highlightColor: Colors.blue[700],
              colorBrightness: Brightness.dark,
              splashColor: Colors.grey,
              child: Text("Submit"),
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20.0)),
              onPressed: () {},
            ),
          ],

图片和ICON

Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: <Widget>[
            Text(
              "加载本地图片",
              style: TextStyle(
                fontSize: 20,
              ),
            ),
            //加载本地图片
            Image(
              image: AssetImage("assets/images/bmw.jpeg"),
              width: 100,
            ),
            //加载本地图片简单用法
            Image.asset(
              "assets/images/bmw.jpeg",
              width: 100,
            ),
            Text(
              "加载网络图片",
              style: TextStyle(
                fontSize: 20,
              ),
            ),
            //加载网络图片
            Image(
              image: NetworkImage(
                  "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"),
              width: 100,
            ),
            //加载网络图片简单方式
            Image.network(
              "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
              width: 100,
            ),
            Text(
              "加载系统自带Icon",
              style: TextStyle(
                fontSize: 20,
              ),
            ),
            Icon(
              Icons.alarm,
              color: Colors.red,
            ),
            Text(
              "加载系统自定义Icon",
              style: TextStyle(
                fontSize: 20,
              ),
            ),
            //加载自定义Icon
            Icon(
              MyIcon.wechat,
              color: Colors.blue,
            ),
            Icon(
              MyIcon.aliPay,
              color: Colors.green,
            ),
          ],
        ));

加载本地图片

  1. 在项目根目录创建一个文件夹,把要加载的图片放进去

  2. 在pubspec.yaml中的flutter部分添加如下内容:

注意:这里需要严格执行缩进

  1. 加载图片 flutter提供了两种方式
//加载本地图片
            Image(
              image: AssetImage("assets/images/bmw.jpeg"),
              width: 100,
            ),
            //加载本地图片简单用法
            Image.asset(
              "assets/images/bmw.jpeg",
              width: 100,
            ),

加载网络图片

 Text(
              "加载网络图片",
              style: TextStyle(
                fontSize: 20,
              ),
            ),
            //加载网络图片
            Image(
              image: NetworkImage(
                  "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png"),
              width: 100,
            )

图片可以设置的参数

  • width:图片的宽
  • height:图片的高
  • fit:图片的缩放模式
  • fill:会拉伸填充满显示空间,图片本身长宽比会发生变化,图片会变形。
  • cover:会按图片的长宽比放大后居中填满显示空间,图片不会变形,超出显示空间部分会被剪裁。
  • contain:这是图片的默认适应规则,图片会在保证图片本身长宽比不变的情况下缩放以适应当前显示空间,图片不会变形。
  • fitWidth:图片的宽度会缩放到显示空间的宽度,高度会按比例缩放,然后居中显示,图片不会变形,超出显示空间部分会被剪裁。
  • fitHeight:图片的高度会缩放到显示空间的高度,宽度会按比例缩放,然后居中显示,图片不会变形,超出显示空间部分会被剪裁。
  • none:图片没有适应策略,会在显示空间内显示图片,如果图片比显示空间大,则显示空间只会显示图片中间部分。
  • color:图片的混合色值
  • colorBlendMode:混合模式
  • alignment:对齐方式
  • repeat:当图片本身大小小于显示空间时,指定图片的重复规则

ICON

使用系统自带

 Icon(
              Icons.alarm,
              color: Colors.red,
            )

使用自定义的

  1. www.iconfont.cn/ 找icon,加入购物车,下载代码,解压

解压完之后目录

  1. 把这个iconfont.ttf导入到项目中,可以自定义名字也可以不改

  2. 新建一个类,里面放我们自定义的ICON

注意,这里我们以第一个wechat为例,里面的0xe60a从哪里来的呢?我们还得看刚才我们解压后的目录,我们打开第一个demo_index.html 然后取码的后四位,前面再加上0x即可

  1. 然后在pubspec.yaml中的flutter部分添加如下内容,一样注意缩进

  2. 加载icon

//加载自定义Icon
            Icon(
              MyIcon.wechat,
              color: Colors.blue,
            ),
            Icon(
              MyIcon.aliPay,
              color: Colors.green,
            ),

下拉框

///第一步:创建一个控件,继承StatefulWidget StatefulWidget有状态的控件
class MyDropDownButton extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyDropDownButton();
  }
}
///第二步:创建一个类继承State,一般适合以_开头加上第一步的类,State的泛型是第一步的控件
class _MyDropDownButton extends State<MyDropDownButton> {
  List getCityList() {
    List<DropdownMenuItem> cityList = new List();
    cityList.add(DropdownMenuItem(
      child: new Text("北京"),
      value: "beijing",
    ));
    cityList.add(DropdownMenuItem(
      child: new Text("上海"),
      value: "shanghai",
    ));
    cityList.add(DropdownMenuItem(
      child: new Text("广州"),
      value: "广州",
    ));
    cityList.add(DropdownMenuItem(
      child: new Text("深圳"),
      value: "深圳",
    ));

    return cityList;
  }

  var selectCity;

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        ///DropdownButton 下拉框控件
        new DropdownButton(
          ///设置数据
          items: getCityList(),
          ///设置回调
          onChanged: (val) {
            setState(() {
              this.selectCity = val;
            });
          },
          ///设置提示语
          hint: new Text("请选择城市"),
          ///设置点击后的数据
          value: selectCity,
        )
      ],
    );
  }
}

单选框和复选框

class SwitchAndCheckboxComponent extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _SwitchAndCheckboxComponent();
  }
}

class _SwitchAndCheckboxComponent extends State<SwitchAndCheckboxComponent> {
  ///注意:初始值一开始就要赋值,要不可能会出问题
  var _switchVal = false;
  var _checkboxVal = false;

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: [
        ///单选框
        Switch(
          value: _switchVal,
          onChanged: (val) {
            setState(() {
              this._switchVal = val;
            });
          },
        ),
        ///复选框
        Checkbox(
          value: _checkboxVal,
          onChanged: (val) {
            setState(() {
              this._checkboxVal = val;
            });
          },
        ),
      ],
    );
  }
}

输入框

TextField

  const TextField({
    Key key,
    this.controller,    //编辑框的控制器,跟文本框的交互一般都通过该属性完成,如果不创建的话默认会自动创建
    this.focusNode,  //用于管理焦点
    this.decoration = const InputDecoration(),   //输入框的装饰器,用来修改外观
    TextInputType keyboardType,   //设置输入类型,不同的输入类型键盘不一样
    this.textInputAction,   //用于控制键盘动作(一般位于右下角,默认是完成)
    this.textCapitalization = TextCapitalization.none,
    this.style,    //输入的文本样式
    this.textAlign = TextAlign.start,   //输入的文本位置
    this.textDirection,    //输入的文字排列方向,一般不会修改这个属性
    this.autofocus = false,   //是否自动获取焦点
    this.obscureText = false,   //是否隐藏输入的文字,一般用在密码输入框中
    this.autocorrect = true,   //是否自动校验
    this.maxLines = 1,   //最大行
    this.maxLength,   //能输入的最大字符个数
    this.maxLengthEnforced = true,  //配合maxLength一起使用,在达到最大长度时是否阻止输入
    this.onChanged,  //输入文本发生变化时的回调
    this.onEditingComplete,   //点击键盘完成按钮时触发的回调,该回调没有参数,(){}
    this.onSubmitted,  //同样是点击键盘完成按钮时触发的回调,该回调有参数,参数即为当前输入框中的值。(String){}
    this.inputFormatters,   //对输入文本的校验
    this.enabled,    //输入框是否可用
    this.cursorWidth = 2.0,  //光标的宽度
    this.cursorRadius,  //光标的圆角
    this.cursorColor,  //光标的颜色
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.down,
    this.enableInteractiveSelection,
    this.onTap,    //点击输入框时的回调(){}
    this.buildCounter,
  })

TextField decoration

InputDecoration({
    this.icon,    //位于装饰器外部和输入框前面的图片
    this.labelText,  //用于描述输入框,例如这个输入框是用来输入用户名还是密码的,当输入框获取焦点时默认会浮动到上方,
    this.labelStyle,  // 控制labelText的样式,接收一个TextStyle类型的值
    this.helperText, //辅助文本,位于输入框下方,如果errorText不为空的话,则helperText不会显示
    this.helperStyle, //helperText的样式
    this.hintText,  //提示文本,位于输入框内部
    this.hintStyle, //hintText的样式
    this.hintMaxLines, //提示信息最大行数
    this.errorText,  //错误信息提示
    this.errorStyle, //errorText的样式
    this.errorMaxLines,   //errorText最大行数
    this.hasFloatingPlaceholder = true,  //labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示
    this.isDense,   //改变输入框是否为密集型,默认为false,修改为true时,图标及间距会变小
    this.contentPadding, //内间距
    this.prefixIcon,  //位于输入框内部起始位置的图标。
    this.prefix,   //预先填充的Widget,跟prefixText同时只能出现一个
    this.prefixText,  //预填充的文本,例如手机号前面预先加上区号等
    this.prefixStyle,  //prefixText的样式
    this.suffixIcon, //位于输入框后面的图片,例如一般输入框后面会有个眼睛,控制输入内容是否明文
    this.suffix,  //位于输入框尾部的控件,同样的不能和suffixText同时使用
    this.suffixText,//位于尾部的填充文字
    this.suffixStyle,  //suffixText的样式
    this.counter,//位于输入框右下方的小控件,不能和counterText同时使用
    this.counterText,//位于右下方显示的文本,常用于显示输入的字符数量
    this.counterStyle, //counterText的样式
    this.filled,  //如果为true,则输入使用fillColor指定的颜色填充
    this.fillColor,  //相当于输入框的背景颜色
    this.errorBorder,   //errorText不为空,输入框没有焦点时要显示的边框
    this.focusedBorder,  //输入框有焦点时的边框,如果errorText不为空的话,该属性无效
    this.focusedErrorBorder,  //errorText不为空时,输入框有焦点时的边框
    this.disabledBorder,  //输入框禁用时显示的边框,如果errorText不为空的话,该属性无效
    this.enabledBorder,  //输入框可用时显示的边框,如果errorText不为空的话,该属性无效
    this.border, //正常情况下的border
    this.enabled = true,  //输入框是否可用
    this.semanticCounterText,  
    this.alignLabelWithHint,
  })

使用

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _pwdController = new TextEditingController();

  @override
  Widget build(BuildContext context) {

    ///输入框监听器
    _pwdController.addListener(() {
      print(_pwdController.text);
    });

    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: <Widget>[
            ///输入框
            TextField(
              autofocus: true,
              decoration: InputDecoration(
                labelText: "手机号",
                hintText: "请输入手机号",
                prefixIcon: Icon(Icons.phone),
                prefixText: "+86"
              ),
              keyboardType: TextInputType.phone,
            ),
            TextField(
              autofocus: false,
              decoration: InputDecoration(
                labelText: "密码",
                hintText: "请输入密码",
                prefixIcon: Icon(Icons.remove_red_eye),
              ),
              ///键盘类型
              keyboardType: TextInputType.visiblePassword,
              ///密码效果,输入完显示圆点
              obscureText: true,
              ///监听器
              controller: _pwdController,
              ///最大行数
              maxLines: 1,
              ///输入框文本的最大长度
              maxLength: 6,
              ///输入文本长度超过maxLength时是否阻止输入,为true时会阻止输入,为false时不会阻止输入但输入框会变红。
              maxLengthEnforced: true,
              ///光标颜色
              cursorColor: Colors.deepOrangeAccent,
              ///光标宽度
              cursorWidth: 2,
            ),
          ],
        ));
  }
}

表单

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _nameController = new TextEditingController();
  TextEditingController _pwdController = new TextEditingController();
  GlobalKey _formKey = new GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: <Widget>[
            Form(
              //设置globalKey,用于后面获取FormState
              key: _formKey,
              autovalidateMode: AutovalidateMode.always,

              child: Column(
                children: <Widget>[
                  TextFormField(
                      autofocus: true,
                      controller: _nameController,
                      decoration: InputDecoration(
                          labelText: "用户名",
                          hintText: "请输入用户名",
                          icon: Icon(Icons.person)),
                      // 校验用户名
                      validator: (v) {
                        return v.trim().length > 0 ? null : "用户名不能为空";
                      }),
                  TextFormField(
                      controller: _pwdController,
                      decoration: InputDecoration(
                          labelText: "密码",
                          hintText: "请输入密码",
                          icon: Icon(Icons.lock)),
                      obscureText: true,
                      //校验密码
                      validator: (v) {
                        return v.trim().length > 5 ? null : "密码不能少于6位";
                      }),
                  RaisedButton(
                    child: Text("提交数据"),
                    textColor: Colors.white,
                    onPressed: () {
                      if ((_formKey.currentState as FormState).validate()) {
                        //验证通过提交数据
                        print("验证提交数据");
                      }
                    },
                  ),
                ],
              ),
            ),
          ],
        ));
  }
}

进度条

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Column(
          children: <Widget>[
            //模糊进度条(会执行一个动画)
            LinearProgressIndicator(
              //value表示当前的进度,取值范围为[0,1];如果value为null时则指示器会执行一个循环动画(模糊进度);当value不为null时,指示器为一个具体进度的进度条。
              value: null,
              //指示器的背景色
              backgroundColor: Colors.grey,
              //指示器的进度条颜色,固定的颜色可以通过AlwaysStoppedAnimation来指定。
              valueColor: AlwaysStoppedAnimation(Colors.blue),
            ),
            //进度显示50%
            LinearProgressIndicator(
              value: 0.5,
              backgroundColor: Colors.grey,
              valueColor: AlwaysStoppedAnimation(Colors.blue),
            ),
            //模糊进度条(会执行一个旋转动画)
            CircularProgressIndicator(
              backgroundColor: Colors.grey[200],
              valueColor: AlwaysStoppedAnimation(Colors.blue),
            ),
            //进度条显示50%,会显示一个半圆
            CircularProgressIndicator(
              backgroundColor: Colors.grey[200],
              valueColor: AlwaysStoppedAnimation(Colors.blue),
              value: 0.5,
            ),
          ],
        ));
  }
}