以下是 Flutter UI 组件高级应用的详细教学,包含代码示例和关键概念说明:
一、高级布局技巧
1. 复杂布局组合
dart
Scaffold(
body: Column(
children: [
// 顶部导航栏
Container(height: 50, color: Colors.blue),
// 主内容区域
Expanded(
child: Row(
children: [
// 侧边栏
Container(width: 100, color: Colors.grey[200]),
// 内容区
Expanded(
child: Stack(
children: [
ListView.builder(
itemCount: 20,
itemBuilder: (ctx, i) => ListTile(title: Text('Item $i')),
),
Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton(onPressed: () {}),
)
],
),
),
],
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
items: [/*...*/],
),
)
2. 响应式布局
dart
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 600) {
return _buildWideLayout();
} else {
return _buildMobileLayout();
}
},
)
二、事件处理进阶
1. 手势识别
dart
GestureDetector(
onTap: () => print('Tapped'),
onDoubleTap: () => print('Double tapped'),
onLongPress: () => showDialog(/*...*/),
onVerticalDragUpdate: (details) {
// 处理垂直滑动
},
child: Container(color: Colors.amber),
)
2. 自定义手势冲突处理
dart
RawGestureDetector(
gestures: {
AllowMultipleGestureRecognizer:
GestureRecognizerFactoryWithHandlers<AllowMultipleGestureRecognizer>(
() => AllowMultipleGestureRecognizer(),
(instance) {
instance.onTap = () => print('允许同时识别多个手势');
},
),
},
child: Text('多手势支持'),
)
三、动画实现
1. 隐式动画
dart
AnimatedContainer(
duration: Duration(seconds: 1),
width: _selected ? 200 : 100,
height: _selected ? 100 : 200,
decoration: BoxDecoration(
color: _selected ? Colors.red : Colors.blue,
borderRadius: BorderRadius.circular(_selected ? 20 : 0),
),
)
2. 显式动画
dart
class _AnimatedLogoState extends State<AnimatedLogo>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Offset> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
)..repeat(reverse: true);
_animation = Tween<Offset>(
begin: Offset.zero,
end: Offset(0, 0.5),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
}
@override
Widget build(BuildContext context) {
return SlideTransition(
position: _animation,
child: FlutterLogo(size: 100),
);
}
}
四、弹窗实现
1. 标准弹窗
dart
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('提示'),
content: Text('确定要删除吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('取消'),
),
TextButton(
onPressed: () {
// 执行删除操作
Navigator.pop(context);
},
child: Text('确定'),
),
],
),
);
2. 自定义弹窗
dart
void showCustomDialog(BuildContext context) {
showGeneralDialog(
context: context,
pageBuilder: (_, __, ___) => Center(
child: Material(
child: Container(
width: 300,
height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
child: Column(
children: [
// 自定义内容
Expanded(child: ListView(...)),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('关闭'),
)
],
),
),
),
),
transitionBuilder: (_, anim, __, child) {
return ScaleTransition(
scale: anim,
child: child,
);
},
);
}
五、综合示例:带动画的交互界面
dart
class InteractiveList extends StatefulWidget {
@override
_InteractiveListState createState() => _InteractiveListState();
}
class _InteractiveListState extends State<InteractiveList> {
final List<String> _items = [];
bool _showAddButton = true;
void _addItem() {
setState(() {
_items.insert(0, 'Item ${_items.length + 1}');
});
}
void _showAddDialog() {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
content: TextField(
autofocus: true,
decoration: InputDecoration(hintText: '输入新项目'),
onSubmitted: (text) {
_addItem();
Navigator.pop(ctx);
},
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: AnimatedOpacity(
duration: Duration(milliseconds: 300),
opacity: _showAddButton ? 1 : 0,
child: FloatingActionButton(
onPressed: _showAddDialog,
child: Icon(Icons.add),
),
),
body: NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollUpdateNotification) {
setState(() {
_showAddButton = notification.metrics.pixels < 100;
});
}
return true;
},
child: AnimatedList(
initialItemCount: _items.length,
itemBuilder: (context, index, animation) {
return SizeTransition(
sizeFactor: animation,
child: ListTile(
title: Text(_items[index]),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => setState(() => _items.removeAt(index)),
),
),
);
},
),
),
);
}
}
关键点说明:
- 布局嵌套:通过合理组合Row/Column/Stack/Expanded实现复杂布局
- 响应式设计:使用LayoutBuilder和MediaQuery适配不同屏幕
- 手势控制:区分不同手势类型并处理冲突
- 动画优化 :
- 使用AnimatedWidget分离动画逻辑
- 注意控制器dispose
- 优先使用隐式动画简化代码
- 弹窗最佳实践 :
- 通过Context正确管理弹窗层级
- 使用Hero动画实现跨页面过渡
- 自定义弹窗时注意圆角和阴影效果