写点什么

Flutter 中的 widget

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:5479 字

    阅读完需:约 18 分钟

当 State 被改变时,可以手动调用其 setState()方法通知 Flutter framework 状态发生改变,Flutter framework 在收到消息后,会重新调用其 build 方法重新构建 widget 树,从而达到更新 UI 的目的。


class StatefulState extends State<StatefulApp>{int _i;///当 Widget 第一次插入到 Widget 树时会被调用,对于每一个 State 对象,Flutter framework 只会调用一次该回调 @overridevoid initState() {


super.initState();_i= 1;


}@overrideWidget build (BuildContext context) {return MaterialApp (title: "Widget 演示",theme: ThemeData(),home:Scaffold (appBar: AppBar (title: Text("Widget")),body: RaisedButton (onPressed: () {


//修改状态,setState 会重新调用 build 更新 uisetState(() {_i++;});},child: Text("Hello,Flutter! $_i"),),));}}

State 生命周期

State 的生命周期为:



State 类除了 build 之外还提供了很多方法能够让我们重写,这些方法会在不同的状态下由 Flutter 调起执行,所以这些方法我们就称之为生命周期方法。在这里我们用 statefulwidget 点击按钮后移除子 statefulwidget。


import 'package:flutter/material.dart';void main () => runApp(MyApp());class MyApp extends StatefulWidget {@override_MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> {bool isShowChild;


///当 Widget 第一次插入到 Widget 树时会被调用,对于每一个 State 对象,Flutter framework 只会调用一次该回调 @overridevoid initState() {super.initState();isShowChild = true;debugPrint("parent initState......");


}


///初始化时,在 initState()之后立刻调用


///当依赖的 InheritedWidget rebuild,会触发此接口被调用


@overridevoid didChangeDependencies() {


super.didChangeDependencies();debugPrint("parent didChangeDependencies......");


}///绘制界面,当 setState 触发的时候会再次被调用


@overrideWidget build(BuildContext context) {debugPrint("parent build......");


return MaterialApp(home: Scaffold(


body: Center(child: RaisedButton(onPressed: () {setState(() {isShowChild = !isShowChild;


});


},child: isShowChild ? Child() : Text("演示移除 Child"),


)),


),);


}


///状态改变的时候会调用该方法,比如调用了 setState


@overridevoid didUpdateWidget(MyApp oldWidget) {super.didUpdateWidget(oldWidget);debugPrint("parent didUpdateWidget......");


}


///当 State 对象从树中被移除时,会调用此回调


@override


void deactivate() {super.deactivate();debugPrint('parent deactivate......');


}


///当 State 对象从树中被永久移除时调用;通常在此回调中释放资源


@override


void dispose() {


super.dispose();debugPrint('parent dispose......');


}}class Child extends StatefulWidget {


@override_ChildState createState() => _ChildState();}class _ChildState extends State<Child> {


@override


Widget build(BuildContext context) {debugPrint("child build......");


return Tex


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


t('lifeCycle');


}


@overridevoid initState() {


super.initState();debugPrint("child initState......");


}


///初始化时,在 initState()之后立刻调用


///当依赖的 InheritedWidget rebuild,会触发此接口被调用


@override


void didChangeDependencies() {


super.didChangeDependencies();debugPrint("child didChangeDependencies......");


}///父 widget 状态改变的时候会调用该方法,比如父节点调用了 setState


@overridevoid didUpdateWidget(Child oldWidget) {super.didUpdateWidget(oldWidget);debugPrint("child didUpdateWidget......");


}


///当 State 对象从树中被移除时,会调用此回调


@overridevoid deactivate() {


super.deactivate();debugPrint('child deactivate......');


}


///当 State 对象从树中被永久移除时调用;通常在此回调中释放资源


@overridevoid dispose() {


super.dispose();debugPrint('child dispose......');


}}


执行的输出结果显示为:


  • 运行到显示


I/flutter (22218): parent initState......I/flutter (22218): parent didChangeDependencies......I/flutter (22218): parent build......I/flutter (22218): child initState......I/flutter (22218): child didChangeDependencies......I/flutter (22218): child build......


  • 点击按钮会移除 Child


I/flutter (22218): parent build......I/flutter (22218): child deactivate......I/flutter (22218): child dispose......


  • 将 MyApp 的代码由 child:isShowChild?Child():Text("演示移除 Child"),改为 child:Child(),点击按钮时


I/flutter (22765): parent build......I/flutter (22765): child didUpdateWidget......I/flutter (22765): child build......

基础 widget

文本显示

Text


Text 是展示单一格式的文本 Widget(Android TextView)。


import 'package:flutter/material.dart';/// main 方法 调用 runApp 传递 Widget,这个 Widget 成为 widget 树的根 void main() => runApp(TextApp());/// 1、单一文本 Text//创建一个无状态的 Widgetclass TextApp extendsStatelessWidget {


@overrideWidget build(BuildContext context) {


//封装了应用程序实现 Material Design 所需要的一些 widgetreturn MaterialApp(title: "Text 演示",//标题,显示在 recent 时候的标题


//主页面


//Scaffold : Material Design 布局结构的基本实现。home: Scaffold(


//ToolBar/ActionBarappBar: AppBar(title: Text("Text")),body: Text("Hello,Flutter"),


),


);


}}


在使用 Text 显示文字时候,可能需要对文字设置各种不同的样式,类似 Android 的 android:textColor/Size 等


在 Flutter 中也拥有类似的属性


Widget _TextBody() {


return Text("Hello,Flutter",style: TextStyle(


//颜色 color: Colors.red,


//字号 默认 14fontSize: 18,


//粗细 fontWeight: FontWeight.w800,


//斜体 fontStyle: FontStyle.italic,


//underline:下划线,overline:上划线,lineThrough:删除线 decoration: TextDecoration.lineThrough,decorationColor: Colors.black,


//solid:实线,double:双线,dotted:点虚线,dashed:横虚线,wavy:波浪线 decorationStyle:TextDecorationStyle.wavy),


);}class TextApp extends StatelessWidget {


@overrideWidgetbuild(BuildContext context){


return MaterialApp(title: "Text 演示",home: Scaffold(appBar: AppBar(title: Text("Text")),body: _TextBody(),


),


);


}}



RichText


如果需要显示更为丰富样式的文本(比如一段文本中文字不同颜色),可以使用 RichText 或者 Text.rich


Widget _RichTextBody() {


var textSpan = TextSpan(text: "Hello",style: TextStyle(color: Colors.red),children: [TextSpan(text: "Flu", style: TextStyle(color: Colors.blue)),TextSpan(text: "uter", style: TextStyle(color: Colors.yellow)),],


);//Text.rich(textSpan);return RichText(text: textSpan);}



DefaultTextStyle 在 widget 树中,文本的样式默认是可以被继承的,因此,如果在 widget 树的某一个节点处设置一个默认的文本样式,那么该节点的子树中所有文本都会默认使用这个样式。相当于在 Android 中定义 Theme


Widget _DefaultStyle(){DefaultTextStyle(


//设置文本默认样式 style: TextStyle(color:Colors.red,fontSize: 20.0,


),textAlign: TextAlign.start,child: Column(crossAxisAlignment:CrossAxisAlignment.start,children: <Widget>[


Text("Hello Flutter!"),


Text("Hello Flutter!"),


Text("Hello Flutter!",style: TextStyle(inherit: false,//不继承默认样式 color: Colors.grey),


),


],


),


);}


FlutterLogo 这个 Widget 用于显示 Flutter 的 logo......


Widget flutterLogo() {


return FlutterLogo(


//大小 size: 100,


//logo 颜色 默认为 Colors.bluecolors: Colors.red,//markOnly:只显示 logo,horizontal:logo 右边显示 flutter 文字,stacked:logo 下面显示文字 style: FlutterLogoStyle.stacked,


//logo 上文字颜色 textColor: Colors.blue,


);}



Icon


主要用于显示内置图标的 Widget


Widget icon() {


return Icon(


//使用预定义 Material icons


// https://docs.flutter.io/flutter/material/Icons-class.html


Icons.add,size: 100,color: Colors.red);}



Image 显示图片的 Widget。图片常用的格式主要有 bmp,jpg,png,gif,webp 等,Android 中并不是天生支持 gif 和 webp 动图,但是这一特性在 flutter 中被很好的支持了。



Iamge.asset 在工程目录下创建目录,如:assets,将图片放入此目录。打开项目根目录:pubspec.yaml



return MaterialApp(title: "Image 演示",home: Scaffold(appBar: AppBar(title: Text("Image")),body: Image.asset("assets/banner.jpeg"),


),);


Image.file 在 sd 卡中放入一张图片。然后利用 path_provider 库获取 sd 卡根目录(Dart 库版本可以在:https://pub.dartlang.org/packages查询)。



注意权限


class ImageState extends State<ImageApp> {


Image image;


@overridevoid initState() {


super.initState();getExternalStorageDirectory().then((path) {setState(() {image = Image.file(File("{Platform.pathSeparator}banner.jpeg"));});});


}


@override


Widget build(BuildContext context) {


return MaterialApp(title: "Image 演示",home: Scaffold(appBar: AppBar(title: Text("Image")),body: image,


),


);


}}


Image.network


直接给网络地址即可。Flutter 1.0,加载 https 时候经常出现证书错误。必须断开 AS 打开 app


Image.memory


Future<List<int>> _imageByte() async {


String path = (await getExternalStorageDirectory()).path;


return await File("{Platform.pathSeparator}banner.jpeg").readAsBytes();}class ImageState extends State<ImageApp> {


Image image;


@overridevoid initState() {


super.initState();_imageByte().then((bytes) {setState(() {image = Image.memory(bytes);});});


}


@override


Widget build(BuildContext context) {return MaterialApp(title: "Image 演示",home: Scaffold(appBar: AppBar(title: Text("Image")),body: image,


),);}}


CircleAvatar


CircleAvatar(


//图片提供者 ImageProviderbackgroundImage: AssetImage("assets/banner.jpeg"),


//半径,控制大小 radius: 50.0,


);


FadeInImage 当使用默认 Image widget 显示图片时,您可能会注意到它们在加载完成后会直接显示到屏幕上。这可能会让用户产生视觉突兀。如果最初显示一个占位符,然后在图像加载完显示时淡入,我们可以使用 FadeInImage 来达到这个目的!


image = FadeInImage.memoryNetwork(placeholder: kTransparentImage,image: 'https://flutter.io/images/homepage/header-illustration.png',


);


按钮


Material widget 库中提供了多种按钮 Widget 如 RaisedButton、FlatButton、OutlineButton 等,它们都是直接或间接对 RawMaterialButton 的包装定制,所以他们大多数属性都和 RawMaterialButton 一样。所有 Material 库中的按钮都有如下相同点:


  1. 按下时都会有“水波动画”。

  2. 有一个 onPressed 属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。


RaisedButton"漂浮"按钮,它默认带有阴影和灰色背景


RaisedButton(child: Text("normal"),onPressed: () => {},


)


FlatButton


扁平按钮,默认背景透明并不带阴影


FlatButton(child: Text("normal"),onPressed: () => {},


)


OutlineButton


默认有一个边框,不带阴影且背景透明。


OutlineButton(child: Text("normal"),onPressed: () => {},


)


IconButton


可点击的 Icon


IconButton(child: Text("normal"),onPressed: () => {},


)


按钮外观可以通过其属性来定义,不同按钮属性大同小异


const FlatButton({...


@required this.onPressed,//按钮点击回调


this.textColor,//按钮文字颜色


this.disabledTextColor,//按钮禁用时的文字颜色


this.color,//按钮背景颜色 this.disabledColor,//按钮禁用时的背景颜色 this.highlightColor,//按钮按下时的背景颜色


this.splashColor,//点击时,水波动画中水波的颜色 this.colorBrightness,//按钮主题,默认是浅色主题


this.padding,//按钮的填充


this.shape,//外形


@required this.child,//按钮的内容})FlatButton( onPressed: () => {},child: Text("Raised"),


//蓝色 color: Colors.blue,


//水波 splashColor: Colors.yellow,


//深色主题,这样文字颜色会变成白色 colorBrightness: Brightness.dark,


//圆角按钮 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)


),)


而 RaisedButton,默认配置有阴影,因此在配置 RaisedButton 时,拥有一系列 elevation 属性的配置


const RaisedButton({


...


this.elevation = 2.0,//正常状态下的阴影 this.highlightElevation = 8.0,//按下时的阴影 this.disabledElevation = 0.0,// 禁用时的阴影...}

输入框

import 'package:flutter/material.dart';void main() => runApp(Demo1());class Demo1 extends StatelessWidget {


@overrideWidget build(BuildContext context) {return MaterialApp(title: "Demo1",home: Scaffold(appBar: AppBar(title: Text("登录"),


),//线性布局,垂直方向 body: Column(children: <Widget>[


TextField(


//自动获得焦点 autofocus: true,decoration: InputDecoration(labelText: "用户名",hintText: "用户名或邮箱",prefixIcon: Icon(Icons.person)),),TextField(

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
Flutter中的widget