我在 Flutter 中使用 2 个自定义开关。我希望当用户打开第一个开关时,第二个开关应该自动关闭。当用户关闭第一个时,第二个将自动打开。与第2个相同。这意味着只有一个开关被打开。我正在使用自定义开关,这就是为什么我在实现此目标时遇到问题的原因。 我能够按照上面所述正确更新变量的值,但切换/开关不会改变。这是因为我的自定义开关。如何在不删除自定义开关的情况下实现此目的?下面是我的代码。
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import '../CustomWidgets/CustomSwitch.dart';
class MenuScreen extends StatefulWidget {
const MenuScreen({super.key});
@override
State<MenuScreen> createState() => _MenuScreenState();
}
class _MenuScreenState extends State<MenuScreen> {
bool _Location = true;
bool OutAndAbout = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Row(
children: [
Container(
color: Colors.transparent,
width: 80,
height: 60,
child: Center(child: GestureDetector(onTap: () => Get.back(), child: Icon(Icons.arrow_back_ios, size: 18, color: Colors.white,)))),
Spacer(),
Text("Skip/Share", style: TextStyle(fontFamily: "Inter", fontSize: 16, fontWeight: FontWeight.w400, color: Color(0xffffffff))),
SizedBox(width: 20),
],
),
SizedBox(height: 30),
Padding(
padding: const EdgeInsets.only(left: 20, right: 10),
child: Row(
children: [
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
shape: BoxShape.circle
),
child: Icon(Icons.location_on, color: Colors.white, size: 16)
),
SizedBox(width: 15),
Text("Fixed Location", style: TextStyle(fontFamily: "Inter", fontSize: 14.5, fontWeight: FontWeight.w300, color: Color(0xffffffff))),
Spacer(),
Transform.scale(
scale: 0.6,
child: Builder(
builder: (context) {
return CustomSwitch(
activeColor: Colors.transparent,
value: _Location,
onChanged: (value) {
setState(() {
_Location = value;
if(_Location){
OutAndAbout = false;
print("Out & About is $OutAndAbout");
}
else{
OutAndAbout = true;
print("Out & About is $OutAndAbout");
}
});
},
);
},
),
),
],
),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 20, right: 10),
child: Row(
children: [
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
shape: BoxShape.circle
),
child: Center(child: Image.asset("assets/images/OutAndAboutIcon.png", width: 20, height: 20,))
),
SizedBox(width: 15),
Text("Out & About", style: TextStyle(fontFamily: "Inter", fontSize: 14.5, fontWeight: FontWeight.w300, color: Color(0xffffffff))),
Spacer(),
Transform.scale(
scale: 0.6,
child: Builder(
builder: (context) {
return CustomSwitch(
activeColor: Colors.transparent,
value: OutAndAbout,
onChanged: (value) {
setState(() {
OutAndAbout = value;
if(OutAndAbout){
_Location = false;
print("Location is $_Location");
}
else{
_Location = true;
print("Location is $_Location");
}
});
},
);
},
),
),
],
),
),
],
),
),
),
);
}
}
下面是自定义开关的代码
library custom_switch;
import 'package:flutter/material.dart';
class CustomSwitch extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
final Color activeColor;
final Color inactiveColor;
final String activeText;
final String inactiveText;
final Color activeTextColor;
final Color inactiveTextColor;
const CustomSwitch(
{
required this.value,
required this.onChanged,
required this.activeColor,
this.inactiveColor = Colors.grey,
this.activeText = '',
this.inactiveText = '',
this.activeTextColor = Colors.white70,
this.inactiveTextColor = Colors.white70});
@override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch>
with SingleTickerProviderStateMixin {
late Animation _circleAnimation;
late AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 60));
_circleAnimation = AlignmentTween(
begin: widget.value ? Alignment.centerRight : Alignment.centerLeft,
end: widget.value ? Alignment.centerLeft : Alignment.centerRight)
.animate(CurvedAnimation(
parent: _animationController, curve: Curves.linear));
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return GestureDetector(
onTap: () {
if (_animationController.isCompleted) {
_animationController.reverse();
} else {
_animationController.forward();
}
widget.value == false
? widget.onChanged(true)
: widget.onChanged(false);
},
child: Container(
width: 70.0,
height: 35.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
// Switch on & off color and gradient.
color: _circleAnimation.value == Alignment.centerLeft
? Color(0xffD4D4D4)
: null,
gradient: _circleAnimation.value == Alignment.centerRight ? LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xffFF5A5A),
Color(0x505AB0FF),
],
) : null,
),
child: Padding(
padding: const EdgeInsets.only(
top: 4.0, bottom: 4.0, right: 4.0, left: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_circleAnimation.value == Alignment.centerRight
? Padding(
padding: const EdgeInsets.only(left: 34.0, right: 0),
child: Text(
widget.activeText,
style: TextStyle(
color: widget.activeTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
Align(
alignment: _circleAnimation.value,
child: Container(
width: 25.0,
height: 25.0,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.white),
),
),
_circleAnimation.value == Alignment.centerLeft
? Padding(
padding: const EdgeInsets.only(left: 0, right: 34.0),
child: Text(
widget.inactiveText,
style: TextStyle(
color: widget.inactiveTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
],
),
),
),
);
},
);
}
}
应该可以,但是试试这个:
在
onChanged
的first switch
回调中,相应更新第二个开关的值,并调用setState触发UI的重建。
onChanged: (value) {
setState(() {
_location = value;
_outAndAbout = !value;
});
},
在
onChanged
的second switch
回调中,相应更新第一个开关的值,并调用setState来触发UI的重建。
onChanged: (value) {
setState(() {
_outAndAbout = value;
_location = !value;
});
},