文本
常用的配置
class TextTest extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: EdgeInsets.all(30), child: Column( children: <Widget>[ Text("hello "), //最大行数为一 ,TextOverflow.ellipsis :省略号代替 Text( "hello! I'm 345 " * 5, maxLines: 1, overflow: TextOverflow.ellipsis, ), //文本缩放因子 Text("hello 345", textScaleFactor: 2), // Text("hello 345", style: TextStyle( //颜色 color: Colors.red, //字号,默认 14 fontSize: 18, //粗细 fontWeight: FontWeight.w800, //斜体 fontStyle: FontStyle.italic, //underline:下划线,overline:上划线,lineThrough:删除线 decoration: TextDecoration.underline, decorationColor: Colors.black, //solid:实线,double:双线,dotted:点虚线,dashed:横虚线,wavy:波浪线 decorationStyle: TextDecorationStyle.wavy)) ], ), )); } }
textAlign:文本的对齐方式;可以选择左对齐、右对齐还是居中。注意,对齐的参考系是Text widget本身
DefaultTextStyle
在 widget 树中,文本的样式默认是可以继承的,因此,如果在 widget 树中的某一个节点设置一个默认的样式,那么该接口的子树中所有文本都会默认使用这个样式
Widget build(BuildContext context) { return Scaffold( body: Padding( padding: EdgeInsets.all(30), child: DefaultTextStyle( style: TextStyle( //颜色 color: Colors.red, //字号,默认 14 fontSize: 20, //粗细 fontWeight: FontWeight.w900, ), child: Column( children: [ Text("hello "), Text("hello! I'm 345 " * 5, maxLines: 1,overflow: TextOverflow.ellipsis,), //替换默认文本 Text("hello 345",style: TextStyle(fontSize: 25, color: Colors.black)) ], )))); }
TextSpan
如果需要对一个 Text 按照不同部分进行不同的显示,这个时候就可以使用 TextSpan,他代表文本中的一个片段
const TextSpan({ TextStyle style, Sting text, List children, GestureRecognizer recognizer, });
style 和 text 表示样式和内容,children 是一个数组,也就是说 TextSpan 可以包含其他的 TextSpan,recognizer 用于对该文本片段上用手势进行识别处理
```dart Widget _richText() { var textSpan = TextSpan(text: "hello", children: [ TextSpan(text: "3", style: TextStyle(color: Colors.blueAccent)), TextSpan(text: "4", style: TextStyle(color: Colors.black)), TextSpan(text: "5", style: TextStyle(color: Colors.green)) ]); return Text.rich(textSpan); }
上面使用 Text.rich 方法将 TextSpan 添加到 Text 中,之所以这样做,就是应为 Text 本身就是 RichText 的一个包装,而 RichText 是可以显示多种样式(富文本)的 widget
字体
在 flutter 中使用字体需要两个步骤,首先是在 pubspec.yaml文件中声明,然后通过 textStyle 属性使用字体
flutter: fonts: - family: Raleway fonts: - asset: assets/fonts/Raleway-Regular.ttf - asset: assets/fonts/Raleway-Medium.ttf weight: 500 - asset: assets/fonts/Raleway-SemiBold.ttf weight: 600 - family: AbrilFatface fonts: - asset: assets/fonts/abrilfatface/AbrilFatface-Regular.ttf
使用字体
// 声明文本样式 const textStyle = const TextStyle( fontFamily: 'Raleway', ); // 使用文本样式 var buttonText = const Text( "Use the font for this text", style: textStyle, );
按钮
Material 组件库中提供了很多按钮组件,如 RaisedButton,FlatButton,OutlineButton,等,他们都是间接或者直接对 RawMaterialButton 组件的包装定制,所以他们大多是属性都和 RawMaterialButton 一样
另外,所有的 Material 库中的按钮都有如下的相同点:
1,按下都会有 “水波纹动画”
2,都有一个 onPressed 属性来设置点击事件的回调,若没有该回调则按钮会处于禁用状态,禁用状态不响应用户点击
各种常见的按钮
class Button extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Padding( padding: EdgeInsets.all(20), child: Column( children: [ //漂浮按钮,默认有阴影和灰色背景 RaisedButton( child: Text("RaisedButton"), onPressed: () => print('RaisedButton'), ), //扁平按钮,默认背景透明不带阴影 FlatButton( child: Text("flatButton"), onPressed: () => print('flatButton'), ), //默认有一个边框,不带阴影且背景透明 OutlineButton( child: Text("OutlineButton"), onPressed: () => print('OutlineButton'), ), //可点击的 Icon IconButton( icon: Icon(Icons.thumb_up_alt), onPressed: () => print('点赞'), ), //带图标的按钮,通过 icon 构造函数创建带图标的按钮 RaisedButton.icon( icon: Icon(Icons.send), label: Text("发送"), onPressed: () => print('发送'), ), FlatButton.icon( icon: Icon(Icons.live_help), label: Text("疑问"), onPressed: () => print('疑问'), ) ], ), )); } }
有些按钮默认是由 icon 这个构造函数的,同个这个构造可以轻松创建出带图标的按钮,如 RaisedButton 等
自定义按钮外观
按钮的外观可以通过属性来定义,不同的按钮属性都大同小异,以 FlatButton 为例,看一下常用的按钮属性,详细的可以查看 api
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( color: Colors.blue, child: Text("提交"), splashColor: Colors.grey, highlightColor: Colors.red, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), onPressed: () => print('提交'), )
Flutter 中 没有提供去除背景的设置,如果需要去除背景,可通过将背景颜色设置为透明来实现,将 color: Colors.blue 替换为 color: Color(0x000000) 即可
FlatButton 是没有 阴影的,这样总会感觉差了点啥,如果需要阴影,可直接使用 RaisedButton 即可
const RaisedButton({ ... this.elevation = 2.0, //正常状态下的阴影 this.highlightElevation = 8.0,//按下时的阴影 this.disabledElevation = 0.0,// 禁用时的阴影 ... }
通过设置以上属性即可设置阴影,elevation 这个属性会在很多组件中见到,都是用来控制阴影的
图片
在 Flutter 中,我们可以通过 Image 组件来加载并显示图片,Image 的加载源可能是 asset,文件,内存,以及网络
ImageProvider
ImageProvider 是一个抽象类,主要定义了图片获取的接口 load , 从不同的数据源获取图片需要实现不同的 ImageProvider,如 AssetImage 就是实现了 Asset 中加载图片的 ImageProvider,而 NetWorkImage s实现了从网络加载图片的 ImageProvider。
Image
Image widget 有一个必选的参数,对应一个 ImageProvider
加载图片
加载图片等资源可参考此文章
1,加载 assets 中图片
Image( image: AssetImage("images/avatar.png"), width: 100.0 ); Image.asset("images/avatar.png", width: 100.0, )
2,加载网络图片
Image( image: NetworkImage( "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"), width: 100.0, ) Image.network( "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4", width: 100.0, )
3,加载本地图片文件
Image.file
4,加载内存图片
Image.memory
参数
const Image({ ... this.width, //图片的宽 this.height, //图片高度 this.color, //图片的混合色值 this.colorBlendMode, //混合模式 this.fit,//缩放模式 this.alignment = Alignment.center, //对齐方式 this.repeat = ImageRepeat.noRepeat, //重复方式 ... })
width ,height :设置图片的宽高,若不指定,图片图片会根据当前父容器的限制,尽可能的显示其原始大小,如果只设置了其中的一个,则另一个则会按比例缩放,但是可通过 fit 属性来适应规则
fit:用于在图片的显示空间和图片本身大小不同的时候指定图片的适应模式
color 和 colorBlendMode :在图片绘制时可以对每一个像素的颜色进行混合处理,color 指定混合色,colorBlenMode 指定混合模式
Image( image:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20357880f.jpeg&refer=http%3A%2F%2Fimg.houpao.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614828035&t=cf5430f8cc9a51b7000cde9c9cc30b5a"), width: 500, height: 300, fit: BoxFit.cover, color: Colors.red, colorBlendMode: BlendMode.difference, )
repeat:当图片本身大小小于显示空间时,指定图片的重复规则
Image 缓存
Flutter 框架对加载获得图片是有缓存的(内存),默认最大缓存数量是 1000,最大缓存空间为 100M
常用的图片组件
CircleAvatar CircleAvatar( backgroundImage:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20357880f.jpeg&refer=http%3A%2F%2Fimg.houpao.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614828035&t=cf5430f8cc9a51b7000cde9c9cc30b5a"), radius: 50, ),
圆形图片
FadeInImage FadeInImage( image: NetworkImage("https://gimg2.baidu.com/i......."), placeholder: AssetImage("images/icon.png"), )
如果直接从网络加载图片然后在显示会有些突兀,使用 FadeInImage 之后会在图片的加载过程中显示一个占位符,在图片加载完成之后显示淡入
ICON
在 Flutter 中,可以直接使用 字体图标,它是将图标做成字体文件,然后通过指定不同的字符而现实不同的图片
在字体文件中,每个字符都对应一个码,每个码对应一个显示字形,不同的字体就是指字形不同,及字符对应的字形是不同的。而在 iconfont 中,只是将位码对应的字形做成了图标,所以不同的字符最终就会渲染成不同的图标
在 Flutter 中,iconfont 和图片相比有如下优势
1,体积小
2,矢量的图标,放大不会影响清晰度
3,可以应用文本样式,可以像文本一样改变字体图标颜色,大小对齐等
4,可以通过 TextSpan 和文本混用
使用 Material Design 字体图标
Flutter 默认包含了一套 Material Design 的字体图标库,在 pubspec.yaml 文件中配置如下
flutter:
uses-material-design: true
看一个简单栗子
String icons = ""; icons += "\uE814"; icons += " \uE200"; icons += " \uE80D"; Text( icons, style: TextStyle( fontFamily: "MaterialIcons", fontSize: 40, color: Colors.green), )
通过上面可以看到,使用图标就像使用文本一样,但这种需要提供每个图标的码点,这点对开发者并不友好,所以 Flutter 封装了 IconData 和 Icon 来专门显示字体图标,上面栗子可使用如下方式实现
Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.accessible, color: Colors.green), Icon(Icons.error, color: Colors.green), Icon(Icons.fingerprint, color: Colors.green) ], )
使用自定义图标库
1,导入 ttf 文件
fonts: - family: myIcon #指定一个字体名 fonts: - asset: fonts/iconfont.ttf
2,自定义 icon 类,功能和上面的 Icons 一样,将字体文件中的所有文件都定义为静态变量
class MyIcons{ static const IconData book = const IconData( 0xe614, fontFamily: 'myIcon', matchTextDirection: true ); static const IconData wechat = const IconData( 0xec7d, fontFamily: 'myIcon', matchTextDirection: true ); }
3,使用
Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon(MyIcons.book,color: Colors.purple,), Icon(MyIcons.wechat,color: Colors.green,), ], )
单选按钮和复选框
Material 组件库中提供了单选开关 Switch 和 复选框 Checkbox,他们本身都是继承自 StatefulWidget ,他们本身不会保存当前选择状态,选中状态都是由父组件来管理的。
当 Switch 或者 CheckBox 被点击时,会触发 onChanged 回调,我们可以回调中改变逻辑
class SwitchAndCheckboxTest extends StatefulWidget { @override State<StatefulWidget> createState() { return _SwitchAndCheckboxTest(); } } class _SwitchAndCheckboxTest extends State<SwitchAndCheckboxTest> { bool _switchSelected = true; //单选状态 bool _checkboxSelected = true; //复选框状态 var groupValue = 0; //单选框,默认选中的值 @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("单选开关和复选框"), ), body: Column( children: [ Switch( value: _switchSelected, activeColor: Colors.red, onChanged: (value) { setState(() { _switchSelected = value; }); }, ), Checkbox( value: _checkboxSelected, activeColor: Colors.red, onChanged: (value) => setState(() => _checkboxSelected = value), ), Row( children: [ Radio( activeColor: Colors.red, //此单选框绑定的值 value: 0, //点击状态改变的回调 onChanged: (value) => setState(() => this.groupValue = value), //当前组件中选定的值 groupValue: groupValue, ), Radio( //此单选框绑定的值 activeColor: Colors.red, value: 1, //点击状态改变的回调 onChanged: (value) => setState(() => this.groupValue = value), //当前组件中选定的值 groupValue: groupValue, ), Radio( activeColor: Colors.red, //此单选框绑定的值 value: 2, //点击状态改变的回调 onChanged: (value) => setState(() => this.groupValue = value), //当前组件中选定的值 groupValue: groupValue, ) ], ) ], ), ); } }