Flutter基本组件Basics Widget怎么用

发布时间:2021-12-18 17:04:36 作者:小新
来源:亿速云 阅读:180

这篇文章主要介绍Flutter基本组件Basics Widget怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1. 概述

Basics Widget 并不是 Flutter 的一个专门的Widget类别,而是 Flutter 官方挑选一些开发常用的 Widget 构成的,希望我们掌握到一些最基本的开发能力。

包括:

2. 常用组件

2.1 Text

Text 用于显示简单样式文本,然后可以填充一些文本显示样式的属性,如下例子:

Text("Hello World",
        textAlign: TextAlign.left,
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
        textScaleFactor: 1.5);
2.1.1 TextStyle

TextStyle 用于指定文本样式,例如颜色、字体、粗细、背景等,如下:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "Flutter",
        home: Scaffold(
            appBar: AppBar(
              title: const Text("Basics Widget"),
            ),
            body: Text(
              "Hello World",
              style: TextStyle(
                  color: Colors.blue,
                  fontSize: 19.0,
                  height: 2,
                  fontFamily: "Courier",
                  background: Paint()..color = Colors.yellow,
                  decoration: TextDecoration.underline,
                  decorationStyle: TextDecorationStyle.dashed),
            )));
  }

效果如图:

Flutter基本组件Basics Widget怎么用

一些属性:

2.1.2 TextSpan

如果我们需要对Text内容不同部分按照不同的样式显示,就可以使用 TextSpan,代表文本的一个“片段”,看看 TextSpan的定义:

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

其中 styletext 代表样式和文本内容, children是 List<InlineSpan>? 类型,也就说 TextSpan 可以包含其他 Span

reconizer 用于表示该文本片段上用于手势进行识别处理,下面我们看一个效果图,然后用 TextSpan 来实现:

Flutter基本组件Basics Widget怎么用

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

这里的代码,用 TextSpan实现了一个基础文本和一个链接片段

2.1.3 DefaultTextStyle

在 Widget 树中, 文本的样式默认是可以被继承的,因此如果 Widget树的某一个节点处设置一个默认的文本样式,那么该节点的子树所有的文本都会默认使用这个样式,而 DefaultTextStyle 正是用于设置默认文本样式的,看下面例子:

DefaultTextStyle(
  //1.设置文本默认样式  
  style: TextStyle(
    color:Colors.red,
    fontSize: 20.0,
  ),
  textAlign: TextAlign.start,
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      Text("hello world"),
      Text("I am Jack"),
      Text("I am Jack",
        style: TextStyle(
          inherit: false, //2.不继承默认样式
          color: Colors.grey
        ),
      ),
    ],
  ),
);

这里的代码首先设置了一个默认的样式,字体大小为20,、颜色为红色,然后将 DefaultTextStyle 设置给了子树,这样一来 Column 所有子孙 Text 默认都会继承该样式, 除非 Text 设置 inherit: false,如下所示:

Flutter基本组件Basics Widget怎么用

2.1.4 使用字体

在 Flutter 中可以使用自定义的字体,或者其他第三方字体, 这里就不介绍配置了,具体可以看官方文档:字体

2.2 Button

Material 组件库提供了多种多样的按钮,他们都是直接或间接对 RawMaterialButton 的包装定制,所以大部分属性都一样。另外 Marterial 库中的按钮都有以下共同点:

2.2.1 ElevatedButton

即 带阴影的按钮, 默认带有阴影和灰色背景,按下后阴影会变大,如下所示:

Flutter基本组件Basics Widget怎么用

代码如下:

child: ElevatedButton(
          child: const Text("i am ElevatedButton"),
          onPressed: () {},
        ),
      ),
2.2.2 TextButton

文本按钮,按下后会有背景色,如下图所示:

Flutter基本组件Basics Widget怎么用

2.2.3 OutlinedButton

默认有一个边框,不带阴影且背景透明,按下后,边框颜色会变亮、同时出现背景和阴影,如下图所示:

Flutter基本组件Basics Widget怎么用

2.2.4 IconButton

可以点击的 Icon, 不包含文字,点击后会出现背景,如下所示:

Flutter基本组件Basics Widget怎么用

Flutter基本组件Basics Widget怎么用

代码设置为:

IconButton(
 icon: Icon(Icons.eleven_mp),
 onPressed: () {},
),
2.2.5 带图标的按钮

上面学到的 ElevatedButtonTextButtonOutlinedButton 都有一个 icon() 的构造函数,这样就可以代入一个图片进去,例如设置:

ElevatedButton.icon(
          icon: const Icon(Icons.send),
          label: const Text("发送"),
          onPressed: () {},
        ),

效果为(这里有编码问题,可以无视):

Flutter基本组件Basics Widget怎么用

2.3 图片及Icon

2.3.1 图片

可以通过 Image 组件来加载并显示布局, Image 的数据源可以是

2.3.1.1 ImageProvider

ImageProvider 是抽象类,主要定义了图片的获取接口 load(),从不同的数据源获取图片需要实现不同的 ImageProvider,如 AssetImage 是实现了从 Asset 中加载图片, NetworkImage 则实现了从网络中加载图片。

2.3.1.2 Image Widget

Image 组件在构建时有一个必选的 image 参数,它对应一个 ImageProvier,下面分别演示一下如何从 asset 和 网络中加载图片。

1.从 asset 中加载图片

在工程根目录下创建一个 images 目录,并将图片拷贝到该目录。

接下来在 pubspec.yaml 文件的 flutter部分 中,写入(注意缩进):

flutter:
  ..
  assets:
    - assets/images/bobo.jpg

最后在代码中使用:

Image(
  image: AssetImage("images/bobo.jpg"),
  width: 100.0,
)

就能展示图片。

(不过我这里遇到一个问题,使用手机运行Flutter应用能正常展示图片,但是使用 Chrome 模拟器会报错,不知道是什么原因造成的

Flutter基本组件Basics Widget怎么用

2.从网络URL中加载图片

直接使用代码:

Image(
  image: NetworkImage("https://www.wahaotu.com/uploads/allimg/201904/1554901831804910.jpg"),
  width: 100.0,
)

可以正常展示图片。

(不过这里出现了很上面一样的问题,但是使用官方使用的url又能正常展示图片

2.3.1.3 Image 参数

我们可以来看下 Image 的参数,通过这些参数可以控制图片外观、大小、混合效果等。

  const Image({
    Key? key,
    required this.image,
    this.frameBuilder,
    this.loadingBuilder,
    this.errorBuilder,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    this.width,
    this.height,
    this.color,
    this.opacity,
    this.colorBlendMode,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.centerSlice,
    this.matchTextDirection = false,
    this.gaplessPlayback = false,
    this.isAntiAlias = false,
    this.filterQuality = FilterQuality.low,
  })

Flutter基本组件Basics Widget怎么用

2.3.2 Icon

Android中有 svg 矢量图, 而 Flutter 中的也有,就是 Icon,它有下面这些优点:

Flutter 默认实现了一套Icon,在 pubspec.yaml 的配置文件可以看到:

flutter:
  uses-material-design: true

来看下官方的示例代码:

String icons = "";
// accessible: 0xe03e
icons += "\uE03e";
// error:  0xe237
icons += " \uE237";
// fingerprint: 0xe287
icons += " \uE287";

Text(
  icons,
  style: TextStyle(
    fontFamily: "MaterialIcons",
    fontSize: 24.0,
    color: Colors.green,
  ),
);

效果为:

Flutter基本组件Basics Widget怎么用

为了不让开发者码点,Flutter 封装了 IconDataIcon来专门显示字体图片,上面的例子也可以用下面方式实现:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(Icons.accessible,color: Colors.green),
    Icon(Icons.error,color: Colors.green),
    Icon(Icons.fingerprint,color: Colors.green),
  ],
)

我们也可以使用自定义的字体图标,这里就不赘述了,可以看看官方示例:Icon自定义字体图标

2.4 单选开关和复选框

Flutter 提供了 Material 风格的 开关Switch复选框Checkbox,它们都继承自 StatfulWidget,但是它们不会保存选中的状态,选中状态是由父组件来管理的。 当 Switch 或者 Checkbox 被点击时,会触发 onChanged 回调,我们可以在此回调中处理选中状态改变逻辑,下面看官方例子:

class SwitchAndCheckBoxTestRoute extends StatefulWidget {
  @override
  _SwitchAndCheckBoxTestRouteState createState() => _SwitchAndCheckBoxTestRouteState();
}

class _SwitchAndCheckBoxTestRouteState extends State<SwitchAndCheckBoxTestRoute> {
  bool _switchSelected=true; //维护单选开关状态
  bool _checkboxSelected=true;//维护复选框状态
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Switch(
          value: _switchSelected,//当前状态
          onChanged:(value){
            //重新构建页面  
            setState(() {
              _switchSelected=value;
            });
          },
        ),
        Checkbox(
          value: _checkboxSelected,
          activeColor: Colors.red, //选中时的颜色
          onChanged:(value){
            setState(() {
              _checkboxSelected=value!;
            });
          } ,
        )
      ],
    );
  }
}

代码中需要维护 SwitchCheckbox 的选中状态,所以 Widget 继承自 StatefulWidget。 在其 build 方法中分别状态了 Switch 和 Checkbox, 并且用两个 bool 值来维护分别的选中状态。 当按钮被点击时,会回调 onChanged 回调选中状态出去,此时我们需要调用 setState() 方法来触发 Flutter 重绘。

为什么要这样子设计,我的理解是:

2.4.1 属性

它们的属性比较简单,常用的有:

此外, Checkbox 不可设置宽高,其大小是自定义的,而 Switch 也仅能设置宽度而已。

2.5 输入框以及表单

Flutter Material组件提供了 输入款TextField表单Form

2.5.1 输入框 TextField
2.5.1.1 属性

来看下 TextField 提供的属性:

  const TextField({
    ...
    this.controller,
    this.focusNode,
    this.decoration = const InputDecoration(),
    TextInputType? keyboardType,
    this.textInputAction,
    this.textCapitalization = TextCapitalization.none,
    this.style,
    this.strutStyle,
    this.textAlign = TextAlign.start,
    this.textAlignVertical,
    this.textDirection,
    this.readOnly = false,
    ToolbarOptions? toolbarOptions,
    this.showCursor,
    this.autofocus = false,
    this.obscuringCharacter = '•',
    this.obscureText = false,
    this.autocorrect = true,
    SmartDashesType? smartDashesType,
    SmartQuotesType? smartQuotesType,
    this.enableSuggestions = true,
    this.maxLines = 1,
    this.minLines,
    this.expands = false,
    this.maxLength,
    this.maxLengthEnforcement,
    this.onChanged,
    this.onEditingComplete,
    this.onSubmitted,
    this.onAppPrivateCommand,
    this.inputFormatters,
    this.enabled,
    this.cursorWidth = 2.0,
    this.cursorHeight,
    this.cursorRadius,
    this.cursorColor,
    this.selectionHeightStyle = ui.BoxHeightStyle.tight,
    this.selectionWidthStyle = ui.BoxWidthStyle.tight,
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.start,
    this.enableInteractiveSelection = true,
    this.selectionControls,
    this.onTap,
    this.mouseCursor,
    this.buildCounter,
    this.scrollController,
    this.scrollPhysics,
    this.autofillHints,
    this.restorationId,
    this.enableIMEPersonalizedLearning = true,
  })

属性比较多,列几个关键的讲解:

一个简单的设置代码如下:

Column(children: const <Widget>[
        TextField(
          autofocus: true,
          decoration: InputDecoration(
            labelText: "用户名",
            hintText: "请输入用户名或密码",
            prefixIcon: Icon(Icons.person)
          ),
        ),
        TextField(
          decoration: InputDecoration(
            labelText: "密码",
            hintText: "请输入密码",
            prefixIcon: Icon(Icons.lock)
          ),
          obscureText: true,
        )
      ]),

Flutter基本组件Basics Widget怎么用

2.5.1.2 通过 controller 获取输入内容

我们可以通过 onChange 拿到内容。 当然也可以使用 controller 来获取

步骤为:

定义一个 controller
final TextEditingController _tfController = TextEditingController();
然后在 TextFiled 中传入这个 controller
TextField(
  controller: _tfController,
  ...
)

最后就可以通过 : print(_tfController.text) 来获得输入框的内容

2.5.1.3 通过 controller 监听文本内容变化

可以通过 onChange 来监听文本, controller 可以通过设置监听器来监听文本,如下:

  @override
  void initState() {
    super.initState();
    _tfController.addListener(() { 
      print(_tfController.text);
    });
  }

controller 的功能更多,除了监听文本,还可以设置默认值、选择文本等,这里就不多赘述。

2.5.1.4 控制焦点

可以使用 FocusNodeFocusScopeNode 来控制焦点。默认情况下是由 FocusScope 来管理,可以在这个范围内通过 FocusScopeNode 在输入框之间移动焦点、设置默认焦点。

我们可以通过下面代码来获取当前 Widget 树中默认的 FocusScopeNode:

focusScopeNode = FocusScope.of(context)

拿到句柄后,可以使用下面代码来获取焦点:

focusScopeNode.requestFocus(focusNode);

其中 focucsNode 是为 TextField 创建的 FocusNode, 这个操作可以让该 TextField 获取焦点。 调用 focusNode.unfocus() 可以取消焦点。

2.5.1.5 监听焦点状态改变事件

通过 FocusNode 可以监听焦点改变的事件:

focusNode.addListener((){
   print(focusNode.hasFocus);
})

true为获取焦点,false为失去焦点

2.5.2 表单

表单Form 对输入框进行分组和统一操作。 就像 Android 的原生组件 RadioGroup 之于 RadioButton 一样, Form 可以管理内容校验、输入框重置等。

Form 继承自 StatefulWidget,其状态管理在 FormState 里面,来看看 From 的定义:

class Form extends StatefulWidget {
  const Form({
    Key? key,
    required this.child,
    @Deprecated(
      'Use autovalidateMode parameter which provides more specific '
      'behavior related to auto validation. '
      'This feature was deprecated after v1.19.0.',
    )
    this.autovalidate = false,
    this.onWillPop,
    this.onChanged,
    AutovalidateMode? autovalidateMode,
  })
  ...
2.5.2.1 FormField

Form 的子孙元素是 FormField 类型,FormField 是一个抽象类,定义了几个属性, FormState 内部通过他们来完成操作, FormField 部分定义如下:

  const FormField({
    Key? key,
    required this.builder,
    this.onSaved,
    this.validator,
    this.initialValue,
    @Deprecated(
      'Use autovalidateMode parameter which provides more specific '
      'behavior related to auto validation. '
      'This feature was deprecated after v1.19.0.',
    )
    this.autovalidate = false,
    this.enabled = true,
    AutovalidateMode? autovalidateMode,
    this.restorationId,
  })

为了方便使用, Flutter 提供了一个 TextFormFild 组件,继承自 FormField 类,还包装了 TextFileld ,可以直接当成 Form 的 FormField 来使用, 相当于用 Form 来管理 TextField

2.5.2.2 FormState

Form 表单的状态类就是 FormState, 可以通过 Form.of 或者 GlobalKey 获得,通过获得它来对 Form 的子孙 FormField 进行统一操作。

FormState 常用的三个方法:

2.5.2.3 示例

我们做一个用户登录的程序,再点击登录前需要做到输入检查:

代码如下:

import 'package:flutter/material.dart';

class FormTestRoute extends StatefulWidget {
  const FormTestRoute({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _FormTestRouteState();
}

class _FormTestRouteState extends State<FormTestRoute> {
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  final GlobalKey _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Form demo'),
        ),
        body: Form(
            key: _formKey,
            autovalidateMode: AutovalidateMode.onUserInteraction,
            child: Column(
              children: [
                TextFormField(
                  autofocus: true,
                  controller: _usernameController,
                  decoration: const InputDecoration(
                      labelText: "username",
                      hintText: "username or email",
                      icon: Icon(Icons.person)),
                  validator: (username) {
                    return username!.trim().isNotEmpty
                        ? null
                        : "username cannot empty";
                  },
                ),
                TextFormField(
                  controller: _passwordController,
                  decoration: const InputDecoration(
                      labelText: "password",
                      hintText: "please input your password",
                      icon: Icon(Icons.lock)),
                  obscureText: true,
                  validator: (pwd) {
                    return pwd!.trim().length >= 6
                        ? null
                        : "password digit cannot less than 6!";
                  },
                ),
                // login button
                Padding(
                  padding: const EdgeInsets.only(top: 28.0),
                  child: Row(
                    children: [
                      Expanded(
                          child: ElevatedButton(
                        onPressed: () {
                          if ((_formKey.currentState as FormState).validate()) {
                            print("Loing success");
                          }
                        },
                        child: const Padding(
                          padding: EdgeInsets.all(16.0),
                          child: Text("Login"),
                        ),
                      ))
                    ],
                  ),
                )
              ],
            )));
  }
}

效果如下图所示:

Flutter基本组件Basics Widget怎么用

以上是“Flutter基本组件Basics Widget怎么用”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. A Tour of Go: Basics 3
  2. A Tour of Go: Basics 1

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

flutter

上一篇:Android中CountDownTimer类怎么用

下一篇:如何进行springboot配置templates直接访问的实现

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》