Flutter基本组件Basics Widget学习

目录
  • 1. 概述
  • 2. 常用组件
    • 2.1 Text
      • 2.1.1 TextStyle
      • 2.1.2 TextSpan
      • 2.1.3 DefaultTextStyle
      • 2.1.4 使用字体
    • 2.2 Button
      • 2.2.1 ElevatedButton
      • 2.2.2 TextButton
      • 2.2.3 OutlinedButton
      • 2.2.4 IconButton
      • 2.2.5 带图标的按钮
    • 2.3 图片及Icon
      • 2.3.1 图片
      • 2.3.2 Icon
    • 2.4 单选开关和复选框
      • 2.4.1 属性
    • 2.5 输入框以及表单
      • 2.5.1 输入框 TextField
      • 2.5.2 表单

1. 概述

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

包括:

  • 文本 Text
  • 按钮 Button
  • 图片 Image
  • 单选框、复选框
  • 输入框、表单
  • 指示器
  • Container

2. 常用组件

2.1 Text

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

Text("Hello World",
        textAlign: TextAlign.left,
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
        textScaleFactor: 1.5);
  • textAlign
    文本对齐方式
  • maxLinesoverflow
    maxLines 指定文本显示的最大行数。
    当文本内容超过最大行数时, overflow 指定了阶段方式, 例如 ellipsis 就是将多余的文本用 “…” 表示
  • textScaleFactor
    代表文本相对于当前字体大小的缩放因子,想你对于去设置文本的样式 style 属性的 fontSize, 它是调整字体大小的一个快捷方式, 该属性的默认值可以通过 MediaQueryData.textScaleFactor 获得, 如果没有 MediaQuery,那么会默认值为 1.0

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

效果如图:

一些属性:

  • height
    行高,它不是一个绝定的值,因为具体的行高为 height*fontSize ,同理行宽也是
  • fontFamily
    由于不同平台默认支持的字体集不同,所以在手动指定字体时一定要先在不同平台测试一下
  • fontSize
    改属性和 Text 的 textScaleFactor 都用于控制字体大小,但是有两个区别,
    ①:fontSize 可以精确指定字体大小, 而 textScaleFactor 只能缩放比例
    ②: textScaleFactor 主要是用于系统字体大小设置改变时,对Flutter 应用字体进行全局调整,而 fontSzie通常用于单个文本,字体大小不会跟随系统字体大小变化

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 来实现:

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

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

  • Text.rich 方法将 TextSpan 添加到 Text 中,之所以可以这样做,是因为 Text 其实就是 RichText 的一个包装,而 RichText 是可以显示多种多样的 widget
  • _reconizer 是点击链接的处理器

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,如下所示:

2.1.4 使用字体

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

2.2 Button

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

  • 按下时都有水波纹
  • 动画统一用 onPressed 属性来设置回调,当按钮按下时会执行该回调,如果不提供回调则按钮会处于禁用状态,不会响应用户点击

2.2.1 ElevatedButton

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

代码如下:

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

2.2.2 TextButton

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

2.2.3 OutlinedButton

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

2.2.4 IconButton

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

代码设置为:

IconButton(
 icon: Icon(Icons.eleven_mp),
 onPressed: () {},
),

2.2.5 带图标的按钮

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

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

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

2.3 图片及Icon

2.3.1 图片

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

  • asset
  • 文件
  • 内存
  • 网络
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 模拟器会报错,不知道是什么原因造成的

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,
  })
  • widthheight
    设置图片宽高,当不指定宽高时,会根据当前父容器的限制尽可能的显示其原始大小,如果只设置其中一个,那么另一个属性默认会按比例缩放
  • fit
    该属性用于用于在图片的显示空间和图片本身大小不同时指定图片的适应模式。适应模式是在 BoxFit 中定义的,它是一个枚举类型,有这些值:
    fill:拉伸填充满显示空间 ,图片会便是
    cover:会按图片的长宽比放大后居中填满显示空间,图片不会变形,超出显示部分会被剪裁
    contain:图片默认适应规则,图片会保证图片本身长宽比不变的情况下缩放以适应当前的显示空间
    fitWidth:图片宽度会缩放到显示空间的宽度,高度会按比例缩放,居中显示,图片不会变形
    fitHeight:和上面的反着来
  • none:图片没有适应策略,会在显示空间内显示图片

  • colorcolorBlendMode:在图片绘制时可以对每一个像素进行颜色混合处理,color指定混合色,而 colorBlendMode 指定混合模式下,因为用的比较少,这里就不做实例
  • repeat:当图片本身大小小于显示空间时,指定图片的重复规则,这里也不做展示

2.3.2 Icon

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

  • 体积小
  • 因为是矢量图,所以拉伸不会影响清晰程度
  • 可以通过 TextSpan 和 文本混用
  • 可以引用到文本样式

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 封装了 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 重绘。

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

  • 将开关、复选框的状态抛给父组件,可以更加灵活,比如在勾选时候做一些网络请求,即异步的操作
  • 一般来说,这些item是否选中,是和用户数据关联的,用户数据也不可能是他们的私有状态,所以放在一起管理更好

2.4.1 属性

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

  • activeColor:设置激活状态的颜色
  • tristate: 是否为三态,仅 Checbox有,一般情况下只有 “true” 和 “false”,表示选中和非选中,如果设置了 tristate 后,还会增加一个 “null” 状态

此外, 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,
  })

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

  • controller
    编辑框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显示提供一个 controller 来与文本框交互,如果设置的话, TextField 内部会创建一个
  • focusNode
    用于控制 TextField 是否占有当前键盘的输入焦点
  • InputDecoration
    用于控制 TextField 的外观显示,如提示文本、背景颜色、边框等。
  • keyboardType
    用于设置该输入框默认的键盘输入类型, 有文本、电话、email等格式
  • textInputAction
    键盘动作按钮图标,就是右下角的那个图标设置
  • style
    文本的样式(正在编辑中的)
  • textAlign
    输入框内编辑文本在水平方向的对齐方式
  • autofocus
    是否自动获取焦点
  • obscureText
    是否隐藏正在编辑的文本, 比如输入密码的场景,文本内容会用 “•” 来代替
  • maxLines
    最大行数
  • maxLenthmaxLengthEnforcement
    maxLenth 代表输入框文本的最大长度,设置后输入框右下角会显示输入的文本计数
    maxLengthEnforcement 决定输入文本长度超过 maxLength 时如何处理,如截断
  • toolbarOptions
    长按时出现的菜单,可以选择 copy、cut、paste 、selectAll
  • onChange
    输入框内容改变的回调, 当然 controller 也可以做到监听
  • onEditingCompleteonSubmitted
    作用一样,都是在输入完成时触发,比如点击了键盘的 完成键、搜索键不同的是两个回调签名不同
  • inputFormatters
    指定输入格式,当用户输入内容改变时,会根据指定格式来校验
  • enable
    如果为false, 则输入框会被禁用
  • cursorWidthcursorRadiuscursorColor
    分别表示自定义输入框光标宽度、圆角和颜色

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

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,
        )
      ]),

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,
  })
  ...
  • autovalidate
    是否自动校验输入内容,当为true时,每一个 FormField 内容发生变化时都会校验合法性,并直接显示错误信息,否则就需要通过调用 FormState.validate() 来手动校验
    v1.19 已经废弃了,改成使用 AutovalidateMode
  • autovalidateMode
    自动校验模式,是上面的替换,它有三个枚举值:
    disable:当 FormField 内容改变时不做校验
    always:即使用户没有用户交互也要校验合法性
    onUserInteraction:只有在用户交互时才会去校验合法性
  • onWillPop
    决定 Form 所在的路由是否可以直接返回。该回调返回一个 Future 对象,如果 Future 的最终结果是 false,则当前路由不会返回,如果为 true,则会返回到上一个路由。
    这个属性通常是用于拦截返回按钮的
  • onChanged
    Form 的任意一个 FormField 内容发生改变时就会调用该方法
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,
  })
  • onSaved
    保存时的回调
  • validator
    验证合法性的回调
  • initValue
    初始值

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

2.5.2.2 FormState

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

FormState 常用的三个方法:

  • FormState.validate():调用此方法后, 会调用 Form 子孙 FormField.validate() 回调,如果有一个检验失败,那么会返回 false,这样所有校验失败的 Widget 都会给出错误提示
  • FormState.save():调用此方法后,会调用 子孙的 FormFild.save() 回调,用于保存表单内容
  • FormState.reset(): 会将子孙 FormField 的内容清空
2.5.2.3 示例

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

  • 用户名不能为空,如果为空则提示“用户名不能为空”
  • 密码不能小于6位,如果小于6位则提示 “密码不能少于6位”

代码如下:

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学习,希望对大家有所帮助。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • flutter传递值到任意widget(当需要widget嵌套使用需要传递值的时候)

    如果我们有这样一个应用场景: WidgetA执行点击之后将数据通过widgetB传递到其下的widgetC. 通常可以通过设置构造函数,传递对应参数到制定的widget树中,如下面代码所描述: 表示需要将widgetA中的点击改变内容传递到widgetB中的widgetC中展示: 需要通过设置widgetB的构造函数,接收对应参数,再传递给widgetC展示: class Inheritedwidget extends StatefulWidget { @override _InheritedW

  • 详解Flutter Widget

    目录 概述: Widget的本质: 分类: Widget StatelessWidget StatefulWidget State ParentDataWidget RenderObjectWidget 小结 概述: 所有的一切都可以被称为widget 在开发 Flutter 应用过程中,接触最多的无疑就是Widget,是『描述』 Flutter UI 的基本单元,通过Widget可以做到: 描述 UI 的层级结构 (通过Widget嵌套): 定制 UI 的具体样式 (如:font.color等

  • Flutter开发之Widget自定义总结

    前言 在Flutter实际开发中,大家可能会遇到flutter框架中提供的widget达不到我们想要的效果,这时就需要我们去自定义widget,从Flutter构建.布局.绘制三部曲中我们了解到,实际的测量.布局.绘制操作都在RenderObject中,我们是可以进行继承相关的RenderObject来实现自定义的.但是其实flutter框架在设计之初就给我们预留出了自定义的入口,方便我们进行自定义. CustomPaint自定义绘制 例:圆形进度条 思路:使用CustomPaint绘制需要的效

  • Flutter中获取屏幕及Widget的宽高示例代码

    前言 我们平时在开发中的过程中通常都会获取屏幕或者 widget 的宽高用来做一些事情,在 Flutter 中,我们有两种方法来获取 widget 的宽高. MediaQuery 一般情况下,我们会使用如下方式去获取 widget 的宽高: final size =MediaQuery.of(context).size; final width =size.width; final height =size.height; 但是如果不注意,这种写法很容易报错,例如下面的写法就会报错: impor

  • Flutter基本组件Basics Widget学习

    目录 1. 概述 2. 常用组件 2.1 Text 2.1.1 TextStyle 2.1.2 TextSpan 2.1.3 DefaultTextStyle 2.1.4 使用字体 2.2 Button 2.2.1 ElevatedButton 2.2.2 TextButton 2.2.3 OutlinedButton 2.2.4 IconButton 2.2.5 带图标的按钮 2.3 图片及Icon 2.3.1 图片 2.3.2 Icon 2.4 单选开关和复选框 2.4.1 属性 2.5 输

  • Flutter投票组件使用方法详解

    本文实例为大家分享了Flutter投票组件的使用方法,供大家参考,具体内容如下 前景 基于公司项目需求,仿照微博实现投票功能. 开发遇到的问题 1.选项列表的高度,自适应的问题:2.进度条动画的问题:3.列表回收机制,导致进度条动画重复:4.自定义进度条四周圆角: 如何解决问题 拿到数组列表最长的数据,然后根据屏幕宽度计算,超出一行则设定两行高度,否则使用一行的高度: _didExceedOneMoreLines(String text, double width, TextStyle styl

  • Android桌面组件App Widget用法入门教程

    本文实例讲述了Android桌面组件App Widget用法.分享给大家供大家参考.具体如下: Android开发应用除了程序应用,还有App Widget应用.好多人会开发程序应用而不会开发App Widget应用.本帖子就是帮助大家学习如何开发App Widget应用的. 先简单说说App Widget的原理.App Widget是在桌面上的一块显示信息的东西,通过单击App Widget跳转到程序入口类.而系统自带的程序,典型的App Widget是music,这个Android内置的音乐

  • Flutter 剪裁组件的使用

    目录 效果展示 剪裁 Widget ClipRRect(圆角矩形剪裁) 其他属性 其他形状剪裁 ClipOval(椭圆剪裁) 其他属性 ClipRect(矩形剪裁) ClipPath(路径剪裁) 做个优化 源码仓库 参考链接 效果展示 在实际项目当中我们经常看到如下各种剪裁形状的效果,Flutter 为我们提供了非常方便的 Widget 很轻松就可以实现,下面我们来一起看看吧 剪裁 Widget ClipRRect(圆角矩形剪裁) 这里我们通过 borderRadius 属性就可以很方便的设置圆

  • Flutter绘图组件之CustomPaint使用详解

    目录 简介 CustomPaint介绍 CustomPainter示例 总结 简介 在有些场景中,我们会需要绘制一些高度定制化的组件,比如 UI 设计师给我们出了个难题 —— 弄一个奇形怪状的边框.看在 UI 设计师是一个漂亮小姐姐的份上,又不好意思说这个做不了(那样也很没面子).这个时候我们就不能直接使用 Flutter 自带的那些组件了,而是需要手动绘制组件,那就会需要用到 CuntomPaint 组件.CustomPaint 组件和前端的 Canvas差不多,允许我们在一个画布上绘制各种元

  • Android Flutter表格组件Table的使用详解

    目录 Table.TabRow.TabCell 小结 之前开发中用到的表格,本篇文章主要介绍如何在页面中使用表格做一个记录. Table组件不同于其它Flex布局,它是直接继承的RenderObjectWidget的.相当于是一个独立的组件,区别与其他系列组件. Table.TabRow.TabCell 惯例,先看下Table相关的构造方法: Table({ Key? key, this.children = const <TableRow>[],//行列表 表示多少行 this.column

  • Flutter 日历组件简单实现

    目录 前言 安装 效果 demo 演示 业务使用 headerView 使用 配置属性 DEMO 感谢 前言 近期有个业务需求,涉及用户付费相关的计算,需要一个日历组件,组件功能如下: 仅支持从明天开始选择预定日期 仅支持可选范围内的日期 日期的选择是连续的 有个推荐日期,需要联动更新 todo: 支持不连续的日期选择 Github:tw_calendar 安装 dependencies: tw_calendar: latest_version 效果 demo 演示 业务使用 headerVie

  • Flutter GetPageRoute实现嵌套导航学习

    目录 1. 嵌套导航-GetPageRoute 2. 自定义拓展 3. 使用bottomNavigationBar 4.小结 1. 嵌套导航-GetPageRoute 本文主要介绍在Getx下快速实现一个嵌套导航 嵌套导航顾名思义,我们导航页面中嵌套一个独立的路由,效果如下 点击跳转 代码如下,也是比较简单 return Scaffold( appBar: AppBar(title: const Text('嵌套导航'),), body: Navigator( key: Get.nestedKe

  • Flutter StreamBuilder组件实现局部刷新示例讲解

    目录 一.前言 二.StreamBuilder 简介 三.StreamBuilder的实际应用 总结 一.前言 在flutter项目中,页面内直接调用setState方法会使得页面重新执行build方法,导致内部组件被全量刷新,造成不必要的性能消耗.出于性能和用户体验方面的考虑我们经常会使用局部刷新代替全量刷新进行页面更新的操作.包括Provider.ValueNotifier和StatefulBuilder等在内的技术方案,都能够帮助我们实现Flutter局部刷新的需求. 本文记录的是通过St

  • flutter text组件使用示例详解

    目录 正文 Text组件 Text组件构造器上的主要属性 正文 flutter组件的实现参考了react的设计理念,界面上所有的内容都是由组件构成,同时也有状态组件和无状态组件之分,这里简单介绍最基本的组件. 在组件代码的书写方式上,web端开发的样式主要有由css进行控制,而客户端开发根据使用的技术栈不同,写法也稍微有些不同:ReactNative的写法和web比较类似,但是ReactNative是使用StyleSheet.create()方法创建样式对象,以内联的方式进行书写. import

随机推荐