Search code examples
androidflutterdartcontainers

How to Create a List of Categories using Containers


so i wanted to create a list of categories (Day-Week-Month) and i achieved it just fine using a

listView.builder but it isn't centered on the horizontal axis so i had the idea to do it with containers.

https://im3.ezgif.com/tmp/ezgif-3-aba2cbc290ae.gif

so using only containers as the gif shows when i press it stays active even if i press on another one

which is something i dont want obviously.

https://im3.ezgif.com/tmp/ezgif-3-e1e304256aaf.gif

my code :

class DWM extends StatefulWidget {
  @override
  _DWMState createState() => _DWMState();
}

class _DWMState extends State<DWM> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 20),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          TextDWM(
            text: "Day",
          ),
          TextDWM(
            text: "Week",
          ),
          TextDWM(
            text: "Month",
          ),
        ],
      ),
    );
  }
}

class TextDWM extends StatefulWidget {
  final String text;
    bool isActive;
  TextDWM({this.text,this.isActive = false});

  @override
  _TextDWMState createState() => _TextDWMState();
}

class _TextDWMState extends State<TextDWM> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        GestureDetector(
          onTap: (){
            setState(() {
              widget.isActive = true;
            });
    },
          child: Text(
            widget.text,
            style: TextStyle(
              color: widget.isActive ? Colors.white : Colors.grey,
            ),
          ),
        ),
        SizedBox(height: 5,),
        Container(
          height: 2,
          width: 40,
          color: widget.isActive  ? Colors.deepOrange : Colors.transparent,
        )
      ],
    );
  }
}


Solution

  • Please check out the code below to learn one of the ways this could be done. However it is advisable to use something like Inherited widget or Provider to pass data down the widget tree.

    import 'package:flutter/material.dart';
    
    final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
    
    void main() {
      runApp(MaterialApp(
          theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
          home: MyApp()));
    }
    
    class MyApp extends StatelessWidget {
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text("Flutter Demo"),
          ),
          body: DWM(),
        );
      }
    }
    
    class DWM extends StatefulWidget {
      @override
      _DWMState createState() => _DWMState();
    }
    
    class _DWMState extends State<DWM> {
      final List<String> _items = ["Day", "Week", "Month"];
      List<bool> _active = []; //[true,false,false];
    
      @override
      void initState() {
        super.initState();
        _active = List.filled(_items.length, false);
      }
    
      void setActive(int active) {
        setState(() {
          _active = List.filled(_items.length, false);
          _active[active] = true;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: List.generate(
              _items.length,
              (index) => TextDWM(
                text: _items[index],
                isActive: _active[index],
                setActive: () => setActive(index),
              ),
            ),
          ),
        );
      }
    }
    
    class TextDWM extends StatelessWidget {
      final String text;
      final bool isActive;
      final Function setActive;
      const TextDWM({this.text, this.isActive, this.setActive});
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            GestureDetector(
              onTap: () {
                setActive();
              },
              child: Text(
                text,
                style: TextStyle(
                  color: isActive ? Colors.white : Colors.grey,
                ),
              ),
            ),
            const SizedBox(
              height: 5,
            ),
            Container(
              height: 2,
              width: 40,
              color: isActive ? Colors.deepOrange : Colors.transparent,
            )
          ],
        );
      }
    }