Widget简介
Flutter中的组件Widget,它类似于Android中View的概念。其中Widget又包括StatefulWidget和StatelessWidegt,有状态的和无状态的。为了避免初学Flutter的JY不知道什么是状态,我简单提一嘴。你可以理解为使用变量来保存视图的参数,通过改变变量值,也就是我们所说的状态,来达到修改界面的目的。
dart
class MyCounter extends StatefulWidget {
@override
_MyCounterState createState() => _MyCounterState();
}
class _MyCounterState extends State<MyCounter> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $count'),
ElevatedButton(
onPressed: () {
setState(() {
count++;
});
},
child: Text('Add'),
),
],
);
}
}
比如以上就是一个简单的官方Demo来演示带状态组件的使用。那么无状态组件就更简洁了。
dart
class MyText extends StatelessWidget {
final String title;
MyText(this.title);
@override
Widget build(BuildContext context) {
return Text(title);
}
}
常用的组件
学习完基础的常用组件,就可以开发大部分的界面了,所以下面的内容非常重要,基础中的基础。
我会介绍以下组件。
- 布局类 :
Container
、Row
、Column
、Stack
、Expanded
、Positioned
、Padding
、SizedBox
- 交互类 :
GestureDetector
、InkWell
、ElevatedButton
、IconButton
、TextField
- 显示类 :
Text
、RichText
、Image
、ListView
、Scaffold
建议按照我给的顺序,循序渐进学习。
Scaffold
Scaffold翻译成脚手架,你可以理解成一个界面大致的组成部分,即页面大体框架。
dart
Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(child: Text('Welcome to Flutter')),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
)
这里提供了AppBar、Drawer、BottomNavigationBar等标准页面结构。整体是通过嵌套方式进行布局。
dart
BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
],
currentIndex: 0,
onTap: (index) {
// Handle tab switch
},
)
再简单了解下BottomNavigationBar。
Container
Container
是最常用的布局容器,支持设置宽高、边距、边框、背景颜色等。
dart
Container(
width: 200,
height: 100,
padding: EdgeInsets.all(16),
margin: EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
),
child: Text('Hello Flutter', style: TextStyle(color: Colors.white)),
)
EdgeInsets用于设置margin和padding。 常用的构造方法有:
dart
EdgeInsets.all(double value)
EdgeInsets.symmetric({horizontal, vertical})
EdgeInsets.only({left, top, right, bottom})
EdgeInsets.fromLTRB(left, top, right, bottom)
使用方式如下:
dart
padding: EdgeInsets.all(16) // 所有值相同
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10) // 水平或垂直相同
padding: EdgeInsets.only(left: 10, top: 5) // 可以指定特定的一个或多个
padding: EdgeInsets.fromLTRB(10, 20, 10, 5) // 完整指定
SizedBox
它是一个固定尺寸/占位组件,常用于设置固定宽高,或者作为空白间距。
dart
SizedBox(height: 20), // 垂直间距
SizedBox(width: 10), // 水平间距
SizedBox(
width: 100,
height: 50,
child: ElevatedButton(onPressed: () {}, child: Text('Button')),
)
Column、Row和Stack
这几个我为什么会放在一起来讲,因为这样比较好类比理解。Column代表垂直排列组件,Row代表水平排列组件,类似于我们Android中的LinearLayout。
dart
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Title', style: TextStyle(fontSize: 20)),
Text('Subtitle'),
],
)
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(Icons.star, color: Colors.orange),
Icon(Icons.star, color: Colors.orange),
Icon(Icons.star, color: Colors.orange),
],
)
mainAxisAlignment和crossAxisAlignment,代表主轴和交叉轴的对齐方式。顾名思义,如果为Column,即垂直排列,那么主轴的方向就是y轴,即垂直方向。它的交叉轴就是水平方向,CrossAxisAlignment.start表示水平方向左对齐。其它的类似,我这里就不多赘述。
dart
Stack(
alignment: Alignment.center,
children: [
Image.asset('assets/images/bg.png'),
Text('Overlay Text', style: TextStyle(fontSize: 24, color: Colors.white)),
],
)
另外,Stack也是一个常用的布局方式,类似于我们Android中的FrameLayout,即允许多个子组件堆叠显示,适合用于浮层、背景叠加等场景。
Text
Text是一个文本显示组件,类似于我们Android中的TextView
。
dart
Text(
'Hello, Flutter!',
style: TextStyle(
fontSize: 24,
color: Colors.black87,
fontWeight: FontWeight.bold,
),
)
Image
Image是一个图片显示组件,类似于我们Android中的ImageView
,它支持加载网络图片、本地资源图片。
dart
Image.network('https://example.com/image.png')
Image.asset('assets/images/logo.png')
my_flutter_project/
├── assets/
│ ├── images/
│ │ ├── logo.png
│ │ ├── bg.jpg
├── pubspec.yaml
你可以随便命名文件夹,常见的命名有 assets/
, assets/images/
, images/
等。需要注意的是,图片添加到对应文件夹还不够,还需要在pubspec.yaml文件中注册。
yaml
flutter:
assets:
- assets/images/logo.png
- assets/images/bg.jpg
或者你省略成
yaml
flutter:
assets:
- assets/images/
缩进采用两字符缩进。
ElevatedButton
按钮组件,类似于我们Android中的Button
。
dart
ElevatedButton(
onPressed: () {
print('Button pressed');
},
child: Text('Click Me'),
)
IconButton
带图标的按钮组件,类似于我们Android中的ImageButton
,在Icons中提供了很多系统的icon,常用的icon有很多。
dart
IconButton(
icon: Icon(Icons.favorite),
color: Colors.red,
onPressed: () {
print('Favorited');
},
)
TextField
输入框组件,类似于我们Android中的EditText
。
dart
TextField(
decoration: InputDecoration(
labelText: 'Enter your name',
border: OutlineInputBorder(),
),
)
它的输入监听就需要结合状态了。
dart
class MyTextInputPage extends StatefulWidget {
@override
_MyTextInputPageState createState() => _MyTextInputPageState();
}
class _MyTextInputPageState extends State<MyTextInputPage> {
final TextEditingController _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TextEditingController 示例')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _controller,
decoration: InputDecoration(labelText: '请输入'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
print('你输入的是:${_controller.text}');
},
child: Text('打印输入内容'),
)
],
),
),
);
}
}
GestureDetector
慢慢的,我们开始有交互了。使用GestureDetector手势探测器可以给组件添加点击、长按事件。
dart
GestureDetector(
onTap: () {
print('Container tapped');
},
child: Container(
color: Colors.red,
padding: EdgeInsets.all(20),
child: Text('Tap me'),
),
)
InkWell
点击反馈组件,带有水波纹效果。
dart
InkWell(
onTap: () {
print('Tapped');
},
child: Padding(
padding: EdgeInsets.all(12),
child: Text('Click Me'),
),
)
Android中的实现为给布局容器添加以下属性。
xml
android:clickable="true"
android:foreground="?selectableItemBackground"
Expanded
弹性填充组件。常用于 Row
或 Column
中,自动填满剩余空间。
dart
Row(
children: [
Icon(Icons.star),
Expanded(
child: Text('This is a very long text that will expand.'),
),
],
)
Positioned
Positioned
通常配合 Stack
使用,允许你指定子组件在父容器中的精确位置。
dart
Stack(
children: [
Container(width: 200, height: 200, color: Colors.grey),
Positioned(
top: 10,
left: 10,
child: Text('Top Left', style: TextStyle(color: Colors.white)),
),
],
)
Padding
内边距组件。
dart
Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text('With Padding'),
)
RichText
常用的还有富文本组件,Android中类似的概念有Spannable
。
dart
RichText(
text: TextSpan(
text: 'Hello ',
style: TextStyle(fontSize: 18, color: Colors.black),
children: [
TextSpan(
text: 'Flutter',
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
),
TextSpan(text: '!'),
],
),
)
ListView
列表组件,类似于我们Android中的RecyclerView
、ListView
。
dart
ListView(
children: List.generate(10, (index) => ListTile(title: Text('Item $index'))),
)
或者使用ListView.builder
dart
ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
总结
我们复习下刚才讲过的内容,来对知识点进行梳理,以加深印象。复习完后,趁热打铁,动手实践一下学习效果更佳哦。
✅ Flutter Widget 简介
-
Widget 是 Flutter 的基本构建单位,一切UI都是Widget。
-
分为两类:
StatelessWidget
:无状态(固定不变的 UI)StatefulWidget
:有状态(可以随用户操作更新)
✅ 常用 Widget 简要汇总
组件名 | 作用说明 |
---|---|
Container |
万能容器(可设置大小、颜色、边框等) |
Text |
显示文字 |
Row / Column |
横向 / 纵向布局 |
ListView |
可滚动列表 |
Scaffold |
页面基础结构(AppBar、body 等) |
Padding |
添加内边距 |
SizedBox |
固定宽高 / 空白间隔 |
Stack |
子组件重叠显示 |
Positioned |
Stack 中定位子组件 |
Expanded |
撑满剩余空间 |
IconButton |
带图标的按钮 |
InkWell |
带水波纹点击效果 |
RichText |
富文本(多样式文字组合) |
✅ EdgeInsets(边距设置)
用于设置 padding(内边距)或 margin(外边距) 的类:
EdgeInsets.all(10)
:四边都是 10EdgeInsets.symmetric(horizontal: 20, vertical: 10)
:左右 20,上下 10EdgeInsets.only(left: 5, top: 10)
:单独设置某几边
✅ Image 资源注册
- 图片放入
assets/images/
文件夹 - 在
pubspec.yaml
注册:
yaml
flutter:
assets:
- assets/images/
- 使用图片:
dart
Image.asset('assets/images/logo.png')
✅ TextEditingController(输入框控制器)
-
用于控制、监听
TextField
的内容 -
常用方法:
.text
:获取或设置值.addListener()
:监听变化.dispose()
:释放资源