Flutter 自定义开关无法正常工作

问题描述 投票:0回答:1

我在 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(),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}
flutter dart flutter-animation
1个回答
0
投票

应该可以,但是试试这个:

  • onChanged
    first switch
    回调中,相应更新第二个开关的值,并调用setState触发UI的重建。

    onChanged: (value) {
       setState(() {
          _location = value;
          _outAndAbout = !value;
        });
    },
    
  • onChanged
    second switch
    回调中,相应更新第一个开关的值,并调用setState来触发UI的重建。

    onChanged: (value) {
        setState(() {
           _outAndAbout = value;
           _location = !value;
       });
    },
    
© www.soinside.com 2019 - 2024. All rights reserved.