Search code examples
flutterdarte-commerce

How to Toggle between three Containers


i am working on a coffee shop app in which, I have an option to toggle between three cup sizes like the attached image.

enter image description here

I want the selected sizes to have full opacity and other to have half opacity. the code I have written changes opacity of the selected size but when i select different size, other size opacity does not revert back to half. opacity stays full like the attached image below

enter image description here

class code:

enum SizeType { small, medium, large }

class CupSize extends StatefulWidget {
  final String cupImage;
  final SizeType size;

  CupSize({
    Key key,
    this.cupImage,
    this.size,
  }) : super(key: key);
  @override
  _CupSizeState createState() => _CupSizeState();
}

class _CupSizeState extends State<CupSize> {
  double activeSizeOpacity = 1;
  double inActiveSizeOpacity = 0.5;
  double activeBorderOpacity = 1;
  double inActiveBorderOpacity = 0.0;
  SizeType selectedSize;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          selectedSize = widget.size;
        });
      },
      child: Opacity(
        opacity: selectedSize == widget.size
            ? activeSizeOpacity
            : inActiveSizeOpacity,
        child: Column(
          children: [
            Container(
              margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
              child: SvgPicture.asset(widget.cupImage),
            ),
            Opacity(
              opacity: selectedSize == widget.size
                  ? activeBorderOpacity
                  : inActiveBorderOpacity,
              child: Container(
                color: kSecondaryColor,
                height: 3,
                width: 14,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class construction:

Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    CupSize(
                      cupImage: 'assets/images/size_small.svg',
                      size: SizeType.small,
                    ),
                    CupSize(
                      cupImage: 'assets/images/size_medium.svg',
                      size: SizeType.medium,
                    ),
                    CupSize(
                      cupImage: 'assets/images/size_large.svg',
                      size: SizeType.large,
                    ),
                  ],
                )

Solution

  • The problem is that you save your state of the cups inside the CupSize class and not in the stateful widget in which you construct the CupSize instances. The following code uses callback and should work:

    class CupSize extends StatefulWidget {
      final String cupImage;
      final bool isSelected; 
      final Function onTapCallback;     //the variables are changed
    
      CupSize({
        Key key,
        this.cupImage,
        this.onTapCallback,
        this.isSelected,
      }) : super(key: key);
      @override
      _CupSizeState createState() => _CupSizeState();
    }
    
    class _CupSizeState extends State<CupSize> {
      double activeSizeOpacity = 1;
      double inActiveSizeOpacity = 0.5;
      double activeBorderOpacity = 1;
      double inActiveBorderOpacity = 0.0;
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: widget.onTapCallback(),    //This is changed
          child: Opacity(
            opacity: widget.isSelected    //This is changed
                ? activeSizeOpacity
                : inActiveSizeOpacity,
            child: Column(
              children: [
                Container(
                  margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
                  child: SvgPicture.asset(widget.cupImage),
                ),
                Opacity(
                  opacity: widget.isSelected      //This is changed
                      ? activeBorderOpacity
                      : inActiveBorderOpacity,
                  child: Container(
                    color: kSecondaryColor,
                    height: 3,
                    width: 14,
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

    //Add this in the State class 
    SizeType selectedSize;
    
    ....
    
    
    Row(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: [
    
                        //initalize the CupSizes with the new variables
                        CupSize(
                          isSelected: selectedSize == SizeType.small,
                          cupImage: 'assets/images/size_small.svg',
                          onTapCallback: (){
                                  setState((){
                                       selectedSize = SizeType.small
                                       });
                                    }
                        ),
                        CupSize(
                          isSelected: selectedSize == SizeType.medium,
                          cupImage: 'assets/images/size_medium.svg',
                          onTapCallback: (){
                                  setState((){
                                       selectedSize = SizeType.medium
                                       });
                                    }
                        ),
                        CupSize(
                          isSelected: selectedSize == SizeType.large,
                          cupImage: 'assets/images/size_large.svg',
                          onTapCallback: (){
                                  setState((){
                                       selectedSize = SizeType.large
                                       });
                                    }
                        ),
                      ],
                    )