Home > Software design >  How to use Reusable SwitchListTile Data on his Main class Flutter
How to use Reusable SwitchListTile Data on his Main class Flutter

Time:11-05

I have created reusable SwitchListTile and i am simply calling them whenever i want to use any. for example I have a custom SwitchListTile like this :

import 'package:flutter/material.dart';

class FitterItem extends StatefulWidget {
  FitterItem(
      {super.key,
      required this.fitterValue,
      required this.fitterTittle,
      required this.fitterSubTit,
      required this.onChange});

  bool fitterValue;
  final String fitterTittle;
  final String fitterSubTit;
  final void Function(bool newValue) onChange;

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _FitterItemState();
  }
}

class _FitterItemState extends State<FitterItem> {
  @override
  Widget build(context) {
    // TODO: implement build
    return SwitchListTile(
      value: widget.fitterValue,
      onChanged: (newValue) {
        setState(() {
          widget.fitterValue = newValue;
        });
      },
      title: Text(
        widget.fitterTittle,
        style: Theme.of(context)
            .textTheme
            .titleLarge!
            .copyWith(color: Theme.of(context).colorScheme.primaryContainer),
      ),
      subtitle: Text(
        widget.fitterSubTit,
        style: Theme.of(context)
            .textTheme
            .labelLarge!
            .copyWith(color: Theme.of(context).colorScheme.primary),
      ),
    );
  }
}

And I have the Parent Class Like below:

import 'package:flutter/material.dart';
import 'package:meals/widgets/fitter_item.dart';

enum Fitter {
  GlutenFree,
  LactoseFree,
  Vegan,
  Vegetarian,
}

class FitterScreen extends StatefulWidget {
  const FitterScreen({super.key});

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _FitterScreenState();
  }
}

class _FitterScreenState extends State<FitterScreen> {
  @override
  Widget build(context) {
    var _glutenFitter = false;
    var _lactoseFitter = false;
    var _vegeterianFitter = false;
    var _veganFitter = false;

    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: const Text("Fitter"),
      ),
      body: WillPopScope(
        onWillPop: () async {
          Navigator.of(context).pop({
            Fitter.GlutenFree: _glutenFitter,
            Fitter.LactoseFree: _lactoseFitter,
            Fitter.Vegan: _veganFitter,
            Fitter.Vegetarian: _vegeterianFitter,
          });
          return false;
        },
        child: Column(
          children: [
            FitterItem(
                fitterValue: _glutenFitter,
                onChange: (bool newValue) {
                  setState(() {
                    _glutenFitter = newValue;
                  });
                },
                fitterTittle: "Gluten free",
                fitterSubTit: "Only include Gluten free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _lactoseFitter,
                onChange: (newValue) {
                  setState(() {
                    _lactoseFitter = newValue;
                  });
                },
                fitterTittle: "Lactose free",
                fitterSubTit: "Only include Lactose free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _veganFitter,
                onChange: (newValue) {
                  setState(() {
                    _veganFitter = newValue;
                  });
                },
                fitterTittle: "Vegan free",
                fitterSubTit: "Only include Vegan free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _vegeterianFitter,
                onChange: (newValue) {
                  setState(() {
                    _vegeterianFitter = newValue;
                  });
                },
                fitterTittle: "Vegeterian free",
                fitterSubTit: "Only include Vegeterian free meals"),
          ],
        ),
      ),
    );
  }
}

But I can't use the Updated value on the Parent class. It takes the Intilze value as false. Custom SwitchListTile changed his status well.

WillPopScope(
        onWillPop: () async {
          Navigator.of(context).pop({
            Fitter.GlutenFree: _glutenFitter,
            Fitter.LactoseFree: _lactoseFitter,
            Fitter.Vegan: _veganFitter,
            Fitter.Vegetarian: _vegeterianFitter,
          });
          return false;
        },

CodePudding user response:

The problem is setting value within the state of the child FitterItem widget, as well as having the vars below the build method of FitterScreen which sets them to false each time it builds.

  1. FitterItem may be a StatelessWidget
  2. onChanged method of the SwitchListTile should take the function passed from the parent, so it may run the function within the parent.
// this
onChanged: (newValue) {
   setState(() {
     widget.fitterValue = newValue;
   });
 },
// should be
onChanged: onChange,
  1. Move the variable in FitterScreen above the build method.
var _glutenFitter = false;
var _lactoseFitter = false;
var _vegeterianFitter = false;
var _veganFitter = false;

@override
Widget build(context) {
// ...

Full code

// start enum
enum Fitter {
  GlutenFree,
  LactoseFree,
  Vegan,
  Vegetarian,
}
/// end enum

// start FitterItem
class FitterItem extends StatelessWidget {
  const FitterItem({
    super.key,
    required this.fitterValue,
    required this.fitterTittle,
    required this.fitterSubTit,
    required this.onChange,
  });

  final bool fitterValue;
  final String fitterTittle;
  final String fitterSubTit;
  final void Function(bool newValue) onChange;

  @override
  Widget build(context) {
    return SwitchListTile(
      value: fitterValue,
      onChanged: onChange,
      title: Text(
        fitterTittle,
        style: Theme.of(context)
            .textTheme
            .titleLarge!
            .copyWith(color: Theme.of(context).colorScheme.primaryContainer),
      ),
      subtitle: Text(
        fitterSubTit,
        style: Theme.of(context)
            .textTheme
            .labelLarge!
            .copyWith(color: Theme.of(context).colorScheme.primary),
      ),
    );
  }
}
/// end FitterItem

// start FitterScreen
class FitterScreen extends StatefulWidget {
  const FitterScreen({super.key});

  @override
  State<StatefulWidget> createState() => _FitterScreenState();
}

class _FitterScreenState extends State<FitterScreen> {
  var _glutenFitter = false;
  var _lactoseFitter = false;
  var _vegeterianFitter = false;
  var _veganFitter = false;
  @override
  Widget build(context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Fitter"),
      ),
      body: WillPopScope(
        onWillPop: () async {
          Navigator.of(context).pop({
            Fitter.GlutenFree: _glutenFitter,
            Fitter.LactoseFree: _lactoseFitter,
            Fitter.Vegan: _veganFitter,
            Fitter.Vegetarian: _vegeterianFitter,
          });
          return false;
        },
        child: Column(
          children: [
            ElevatedButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('pop')),
            FitterItem(
                fitterValue: _glutenFitter,
                onChange: (bool newValue) {
                  setState(() {
                    _glutenFitter = newValue;
                  });
                },
                fitterTittle: "Gluten free",
                fitterSubTit: "Only include Gluten free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _lactoseFitter,
                onChange: (newValue) {
                  setState(() {
                    _lactoseFitter = newValue;
                  });
                },
                fitterTittle: "Lactose free",
                fitterSubTit: "Only include Lactose free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _veganFitter,
                onChange: (newValue) {
                  setState(() {
                    _veganFitter = newValue;
                  });
                },
                fitterTittle: "Vegan free",
                fitterSubTit: "Only include Vegan free meals"),
            const SizedBox(
              height: 5,
            ),
            FitterItem(
                fitterValue: _vegeterianFitter,
                onChange: (newValue) {
                  setState(() {
                    _vegeterianFitter = newValue;
                  });
                },
                fitterTittle: "Vegeterian free",
                fitterSubTit: "Only include Vegeterian free meals"),
          ],
        ),
      ),
    );
  }
}
/// end FitterScreen
  • Related