📅  最后修改于: 2023-12-03 15:08:04.017000             🧑  作者: Mango
你是否曾经在设计用户界面时遇到过这样的需求:当用户单击一个颜色卡片时,在颤动(或 "震动")动画中显示它的选中状态,以便用户直观地了解自己的选择?
在这篇文章中,我们将介绍如何使用 Dart 编写一个简单的程序,以实现在点击时颤动切换色卡的功能。
ColorCard
Widget,该 Widget 包含在点击时切换颜色卡片状态的逻辑。在 ColorCard
内部,我们可以使用 Flutter 动画库中的 AnimatedContainer
Widget 和 GestureDetector
Widget 来实现这个功能。import 'package:flutter/material.dart';
class ColorCard extends StatefulWidget {
final Color color;
final bool isSelected;
ColorCard({Key key, this.color, this.isSelected}) : super(key: key);
@override
_ColorCardState createState() => _ColorCardState();
}
class _ColorCardState extends State<ColorCard>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
bool _isCardSelected;
@override
void initState() {
super.initState();
_isCardSelected = widget.isSelected;
_controller = AnimationController(
duration: const Duration(milliseconds: 75),
vsync: this,
);
_animation = Tween<double>(begin: 1, end: 0.8).animate(_controller);
}
@override
void didUpdateWidget(ColorCard oldWidget) {
super.didUpdateWidget(oldWidget);
_isCardSelected = widget.isSelected;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) {
_controller.forward();
},
onTapUp: (_) {
_controller.reverse();
setState(() {
_isCardSelected = !_isCardSelected;
});
},
onTapCancel: () {
_controller.reverse();
},
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Stack(
children: [
Positioned(
top: 16,
left: 16,
child: Text(
widget.color.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
if (_isCardSelected)
Center(
child: ScaleTransition(
scale: _animation,
child: Icon(
Icons.check,
color: Colors.white,
size: 32,
),
),
),
],
),
),
);
}
}
上面的代码中,我们定义了一个 ColorCard
Widget,它接受一个 color
参数和一个 isSelected
参数作为输入。 isSelected
参数确定颜色卡片是否处于选中状态。在 _ColorCardState
中,我们定义了 _controller
和 _animation
变量来控制点击事件时颤动动画的实现。_isCardSelected
变量记录着颜色卡片的当前选中状态,并在点击事件中进行了更改。
在 build()
方法中,我们使用 GestureDetector
Widget 来包装 Container
Widget,以便监听点击事件。我们将 onTapDown
回调函数设置为在用户按下颜色卡片时启动颤动动画,而将 onTapUp
回调函数设置为在用户松开颜色卡片时停止动画并切换颜色卡片状态。我们还在 Stack
Widget 中嵌套了一个 ScaleTransition
Widget 来实现颤动动画,并使用 if
语句来根据 _isCardSelected
变量的值决定是否显示选中状态的 Icon
。
ColorCard
Widget 添加到一个 GridView
Widget 中,以便显示多个颜色卡片。我们可以通过 GestureDetector
Widget 的 onTapDown
回调函数来通知父 Widget 子 Widget 点击事件已经发生。在 GridView
中添加 ShakeSwitchColorCardBehaviour
Widget 来处理颤动逻辑。以下是完整的代码:
import 'package:flutter/material.dart';
class ShakeSwitchColorCardBehaviour extends StatefulWidget {
final List<Color> initialColors;
final ValueChanged<int> onSelectedIndexChanged;
ShakeSwitchColorCardBehaviour({
Key key,
this.initialColors = const [],
this.onSelectedIndexChanged,
}) : super(key: key);
@override
_ShakeSwitchColorCardBehaviourState createState() =>
_ShakeSwitchColorCardBehaviourState();
}
class _ShakeSwitchColorCardBehaviourState
extends State<ShakeSwitchColorCardBehaviour> {
int _selectedColorIndex = -1;
@override
void initState() {
super.initState();
_selectedColorIndex = widget.initialColors.length > 0 ? 0 : -1;
}
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 2,
children: List.generate(
widget.initialColors.length,
(index) => GestureDetector(
onTapDown: (_) {
setState(() {
_selectedColorIndex = index;
});
},
child: ColorCard(
color: widget.initialColors[index],
isSelected: _selectedColorIndex == index,
),
),
),
);
}
}
class ColorCard extends StatefulWidget {
final Color color;
final bool isSelected;
ColorCard({Key key, this.color, this.isSelected}) : super(key: key);
@override
_ColorCardState createState() => _ColorCardState();
}
class _ColorCardState extends State<ColorCard>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
bool _isCardSelected;
@override
void initState() {
super.initState();
_isCardSelected = widget.isSelected;
_controller = AnimationController(
duration: const Duration(milliseconds: 75),
vsync: this,
);
_animation = Tween<double>(begin: 1, end: 0.8).animate(_controller);
}
@override
void didUpdateWidget(ColorCard oldWidget) {
super.didUpdateWidget(oldWidget);
_isCardSelected = widget.isSelected;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) {
_controller.forward();
},
onTapUp: (_) {
_controller.reverse();
setState(() {
_isCardSelected = !_isCardSelected;
});
},
onTapCancel: () {
_controller.reverse();
},
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Stack(
children: [
Positioned(
top: 16,
left: 16,
child: Text(
widget.color.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
if (_isCardSelected)
Center(
child: ScaleTransition(
scale: _animation,
child: Icon(
Icons.check,
color: Colors.white,
size: 32,
),
),
),
],
),
),
);
}
}
在这篇文章中,我们介绍了如何使用 Dart 编写一个简单的程序,以实现在点击时颤动切换色卡的功能。请根据您的实际需求进行更改和修改。