抽取Widget
上篇文章我们在写ListView
的时候,所有的代码都写在main.dart
文件内容,这样的话就比较臃肿,下面进行拆分优化
- 新建
listview_demo.dart
文件,把_itemForRow
抽出来
import 'package:flutter/material.dart';
import 'model/Car.dart';
class ListViewDemo extends StatelessWidget {
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Colors.white,
margin: const EdgeInsets.all(10),
child: Column(
children: <Widget>[
Image.network(datas[index].imageUrl!),
const SizedBox(
height: 10,
),
Text(
datas[index].name!,
style: const TextStyle(
fontWeight: FontWeight.w800,
fontSize: 18.0,
fontStyle: FontStyle.italic,
),
),
],
));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
title: const Text('FlutterDemo'),
),
body: ListView.builder(
itemBuilder: _itemForRow,
itemCount: datas.length,
),
);
}
}
- 抽取
main.dart
文件中的数据源,放入Car.dart
文件
class Car {
const Car({this.name, this.imageUrl});
final String? name;
final String? imageUrl;
}
final List<Car> datas = [
const Car(
name: '保时捷918 Spyder',
imageUrl:
'https://img.haomeiwen.com/i2990730/7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '兰博基尼Aventador',
imageUrl:
'https://img.haomeiwen.com/i2990730/e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '法拉利Enzo',
imageUrl:
'https://img.haomeiwen.com/i2990730/a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: 'Zenvo ST1',
imageUrl:
'https://img.haomeiwen.com/i2990730/bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '迈凯伦F1',
imageUrl:
'https://img.haomeiwen.com/i2990730/5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '萨林S7',
imageUrl:
'https://img.haomeiwen.com/i2990730/2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '科尼赛克CCR',
imageUrl:
'https://img.haomeiwen.com/i2990730/01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '布加迪Chiron',
imageUrl:
'https://img.haomeiwen.com/i2990730/7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '轩尼诗Venom GT',
imageUrl:
'https://img.haomeiwen.com/i2990730/d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '西贝尔Tuatara',
imageUrl:
'https://img.haomeiwen.com/i2990730/3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
)
];
-
main.dart
文件内容如下
import 'package:flutter/material.dart';
import 'package:hello_flutter/listview_demo.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ListViewDemo(),
);
}
}
运行效果
常用Widget
富文本RichText
小部件练习
- 新建
base_widget.dart
文件
// base_widget.dart文件内容
import 'package:flutter/material.dart';
class RichTextDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
-
main.dart
文件引入RichTextDemo
import 'package:flutter/material.dart';
import 'package:hello_flutter/base_widget.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
title: const Text('BaseDemo'),
),
body: RichTextDemo()
)
);
}
}
-
base_widget.dart
开始编写练习
-
Text()
定义style
的两种方式
// 方式一
class RichTextDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
'flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.orange),
);
}
}
// 方式二
class RichTextDemo extends StatelessWidget {
final TextStyle _textStyle = TextStyle(color: Colors.orange);
@override
Widget build(BuildContext context) {
return Text(
'flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习',
textAlign: TextAlign.center,
style: _textStyle,
);
}
}
- 字符串拼接展示
class RichTextDemo extends StatelessWidget {
final TextStyle _textStyle = TextStyle(color: Colors.orange);
final String _str1 = 'hello';
@override
Widget build(BuildContext context) {
return Text(
// 使用$拼接字符串_str1
'$_str1 flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习flutter学习',
textAlign: TextAlign.center,
style: _textStyle,
// 最大行数
maxLines: 3,
// 超过3行显示...
overflow: TextOverflow.ellipsis,
);
}
}
-
RichText
练习
class RichTextDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// RichText表示富文本
return RichText(
// 使用TextSpan可以有多个子部件
text: const TextSpan(
text: '《Flutter高级学习》',
style: TextStyle(
fontSize: 30,
color: Colors.black,
),
children: [
TextSpan(
text: '--',
style: TextStyle(
fontSize: 20,
color: Colors.red,
)),
TextSpan(
text: 'HK',
style: TextStyle(fontSize: 16, color: Colors.blue)),
]),
);
}
}
运行效果
Container小部件练习
class RichTextDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 父部件Container会随着子部件变化
return Container(
color: Colors.yellow,
child: Row(
children: <Widget>[
// 注意⚠️ Container 不能被 const修饰
Container(
color: Colors.red,
// 添加子部件Icon,有了子部件 父视图Container才能够显示出来
child: Icon(
Icons.add,
size: 45,
),
padding: EdgeInsets.all(20), //内边距
margin: EdgeInsets.all(20), //外边距
height: 200,
),
],
),
);
}
}
运行效果
Flutter布局之Row&Column&Stack
-
Row
:在水平方向上
排列子widget的列表,主轴方向向右
-
Column
:在垂直方向上
排列子widget的列表,主轴方向向下
-
Stack
:多层 -> 层叠样式,主轴方向向外
常用的属性有:
MainAxisAlignment
:主轴方向上的对齐方式,会对child的位置起作用,默认是start。
其中MainAxisAlignment
枚举值:
center
:将children放置在主轴的中心
end
:将children放置在主轴的末尾
spaceAround
:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2
spaceBetween
:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙
spaceEvenly
:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child
start
:将children放置在主轴的起点
交叉轴CrossAxisAlignment
枚举值:
start
:将子控件放在交叉轴的起始位置
end
:将子控件放在交叉轴的结束位置
center
:将子控件放在交叉轴的中间位置
stretch
:使子控件填满交叉轴
baseline
:将子控件放在交叉轴的上,并且与基线相匹配(不常用)
Expanded
填充布局
-
在主轴方向不会剩下间隙
。将被Expanded
包装的部件进行拉伸和压缩 -
主轴横向
,宽度设置没有意义 -
主轴纵向
,高度设置没有意义 - 当
Text
被Expanded
包装后,文字可以自动换行,这也被称作灵活布局
。
- 新建
layout_demo.dart
文件
import 'package:flutter/material.dart';
class LayoutDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 这里的Container就是mian.dart中的body小部件
return Container(
color: Colors.yellow,
// 设置子部件Row放置在中心点,值的区间 -1 ~ 1,x值不能影响Row y值不能影响Column
alignment: Alignment(0.0, 0.0),
child: Row(
//spaceBetween: 剩下的空间平均分布到小部件之间!!
//spaceAround: 剩下的空间平均分布到小部件周围!!
//spaceEvenly:剩下的空间和小部件一起平均分!!
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //主轴
// crossAxisAlignment与textBaseline配合使用,主要用来设置文本对齐
crossAxisAlignment: CrossAxisAlignment.baseline, //交叉轴
//CrossAxisAlignment.baseline需要结合textBaseline一起使用
//alphabetic是设置英文字符,ideographic设置中文字符
textBaseline: TextBaseline.alphabetic,
children: [
//Expanded:在主轴方向不会剩下间隙。将被Expanded拉伸。
//Expanded用于自适应拉伸
Expanded(
child: Container(
child: Text(
'你好hello',
style: TextStyle(fontSize: 15),
),
color: Colors.red)),
Expanded(
child: Container(
child: Text(
'哎aiyo',
style: TextStyle(fontSize: 30),
),
color: Colors.blue)),
Expanded(
child: Container(
child: Text(
'哎aiyo',
style: TextStyle(fontSize: 60),
),
color: Colors.white)),
],
),
);
}
}
Row横向布局
Column纵向布局
Stack层叠布局
Row
添加textDirection: TextDirection.rtl,
属性,可以让子部件从右向左
排列。在Row
布局中能够改变主轴方向
return Container(
color: Colors.yellow,
// 设置子部件Row放置在中心点,值的区间 -1 ~ 1,x值不能影响Row y值不能影响Column
alignment: Alignment(0.0, 0.0),
child: Row(
// 添加排列方向
textDirection: TextDirection.rtl,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //主轴
crossAxisAlignment: CrossAxisAlignment.baseline, //交叉轴
textBaseline: TextBaseline.alphabetic,
children: [
//Expanded:在主轴方向不会剩下间隙。将被Expanded拉伸。
//Expanded用于自适应拉伸
Expanded(
child: Container(
child: Text(
'你好hello',
style: TextStyle(fontSize: 15),
),
color: Colors.red)),
Expanded(
child: Container(
child: Text(
'哎aiyo',
style: TextStyle(fontSize: 30),
),
color: Colors.blue)),
Expanded(
child: Container(
child: Text(
'哎aiyo',
style: TextStyle(fontSize: 60),
),
color: Colors.white)),
],
),
);
运行效果
网友评论