Flutter 自定义组件:Switch 切换实现
在 Flutter 中,你可以通过多种方式创建自定义的 Switch 切换组件。下面我将介绍几种实现方法,包括基础实现、自定义样式和完全自定义的 Switch 组件。
- 使用 Flutter 自带的 Switch 组件
最简单的方法是使用 Flutter 提供的 Switch 组件:
dart
bool _switchValue = false;
Switch(
value: _switchValue,
onChanged: (bool value) {
setState(() {
_switchValue = value;
});
},
activeColor: Colors.blue, // 开启时的颜色
activeTrackColor: Colors.blue[200], // 开启时轨道颜色
inactiveThumbColor: Colors.grey, // 关闭时滑块颜色
inactiveTrackColor: Colors.grey[300], // 关闭时轨道颜色
)
- 使用 CupertinoSwitch (iOS 风格)
如果你想要 iOS 风格的 Switch,可以使用 CupertinoSwitch:
dart
bool _cupertinoSwitchValue = false;
CupertinoSwitch(
value: _cupertinoSwitchValue,
onChanged: (bool value) {
setState(() {
_cupertinoSwitchValue = value;
});
},
activeColor: Colors.blue,
)
- 完全自定义 Switch 组件
如果你想完全控制 Switch 的外观和行为,可以创建一个自定义组件:
自定义 Switch 实现
dart
class CustomSwitch extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
final Color activeColor;
final Color inactiveColor;
final double width;
final double height;
const CustomSwitch({
Key? key,
required this.value,
required this.onChanged,
this.activeColor = Colors.blue,
this.inactiveColor = Colors.grey,
this.width = 50.0,
this.height = 30.0,
}) : super(key: key);
@override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
widget.onChanged(!widget.value);
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(widget.height),
color: widget.value ? widget.activeColor : widget.inactiveColor,
),
child: Stack(
children: [
AnimatedPositioned(
duration: const Duration(milliseconds: 200),
left: widget.value ? widget.width - widget.height : 0,
child: Container(
width: widget.height,
height: widget.height,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
),
),
],
),
),
);
}
}
使用自定义 Switch
dart
bool _customSwitchValue = false;
CustomSwitch(
value: _customSwitchValue,
onChanged: (value) {
setState(() {
_customSwitchValue = value;
});
},
activeColor: Colors.green,
inactiveColor: Colors.red[200],
width: 60,
height: 35,
)
- 带图标和文本的自定义 Switch
dart
class IconSwitch extends StatelessWidget {
final bool value;
final ValueChanged<bool> onChanged;
final IconData activeIcon;
final IconData inactiveIcon;
final String activeText;
final String inactiveText;
final Color activeColor;
final Color inactiveColor;
const IconSwitch({
Key? key,
required this.value,
required this.onChanged,
this.activeIcon = Icons.check,
this.inactiveIcon = Icons.close,
this.activeText = 'ON',
this.inactiveText = 'OFF',
this.activeColor = Colors.green,
this.inactiveColor = Colors.red,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => onChanged(!value),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: value ? activeColor : inactiveColor,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
value ? activeIcon : inactiveIcon,
color: Colors.white,
size: 16,
),
const SizedBox(width: 4),
Text(
value ? activeText : inactiveText,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
}
- 动画增强版自定义 Switch
dart
class AnimatedToggleSwitch extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
final Duration animationDuration;
final Color activeColor;
final Color inactiveColor;
const AnimatedToggleSwitch({
Key? key,
required this.value,
required this.onChanged,
this.animationDuration = const Duration(milliseconds: 300),
this.activeColor = Colors.blue,
this.inactiveColor = Colors.grey,
}) : super(key: key);
@override
_AnimatedToggleSwitchState createState() => _AnimatedToggleSwitchState();
}
class _AnimatedToggleSwitchState extends State<AnimatedToggleSwitch>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: widget.animationDuration,
);
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
if (widget.value) {
_controller.value = 1.0;
}
}
@override
void didUpdateWidget(AnimatedToggleSwitch oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.value != oldWidget.value) {
if (widget.value) {
_controller.forward();
} else {
_controller.reverse();
}
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
widget.onChanged(!widget.value);
},
child: Container(
width: 60,
height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Color.lerp(
widget.inactiveColor,
widget.activeColor,
_animation.value,
),
),
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Stack(
children: [
Positioned(
left: _animation.value * 30,
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
),
),
],
);
},
),
),
);
}
}
使用示例
dart
class SwitchExamplePage extends StatefulWidget {
const SwitchExamplePage({Key? key}) : super(key: key);
@override
_SwitchExamplePageState createState() => _SwitchExamplePageState();
}
class _SwitchExamplePageState extends State<SwitchExamplePage> {
bool _basicSwitch = false;
bool _cupertinoSwitch = false;
bool _customSwitch = false;
bool _iconSwitch = false;
bool _animatedSwitch = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Switch Examples')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
ListTile(
title: const Text('Basic Switch'),
trailing: Switch(
value: _basicSwitch,
onChanged: (value) {
setState(() {
_basicSwitch = value;
});
},
),
),
ListTile(
title: const Text('Cupertino Switch'),
trailing: CupertinoSwitch(
value: _cupertinoSwitch,
onChanged: (value) {
setState(() {
_cupertinoSwitch = value;
});
},
),
),
ListTile(
title: const Text('Custom Switch'),
trailing: CustomSwitch(
value: _customSwitch,
onChanged: (value) {
setState(() {
_customSwitch = value;
});
},
),
),
ListTile(
title: const Text('Icon Switch'),
trailing: IconSwitch(
value: _iconSwitch,
onChanged: (value) {
setState(() {
_iconSwitch = value;
});
},
),
),
ListTile(
title: const Text('Animated Switch'),
trailing: AnimatedToggleSwitch(
value: _animatedSwitch,
onChanged: (value) {
setState(() {
_animatedSwitch = value;
});
},
),
),
],
),
),
);
}
}
这些示例展示了从简单到复杂的各种 Switch 实现方式。你可以根据自己的需求选择合适的方法,或者在这些基础上进一步自定义。