I'm home automation project and I want to select between to paddings, so, for example, there's one that has the 'On' and 'Off', and have another one, which has 'Lock' and 'Unlock'. I tried to make a function so I call each one of them in different occasions, but it didn't work, unfortunately.
I have a function which creates CustomCards, I call these function inside my main file, so I can create cards with the same face.
Here's my code:

class CustomCard extends StatelessWidget {
final bool isActive;
final String text;
final IconData iconData;
final VoidCallback onTap;

const CustomCard({
this.isActive,
this.text,
this.iconData,
this.onTap,
});

@override
Widget build(BuildContext context) {
return InkWell(
  onTap: onTap,
  child: Container(
    height: 100,
    width: 100,
    child: Card(
      color: isActive ? Colors.white : Colors.grey[800],
      semanticContainer: true,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
      ),
      margin: new EdgeInsets.all(0),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Row(
            children: <Widget>[
              Padding(
                padding: EdgeInsets.only(left: 4,top: 7, right: 30, bottom: 10),
                child: Icon(
                  iconData,
                  color: isActive ? Colors.black : Colors.white,
                  size: 35,
                ),
              ),
              Padding(
                padding:
                EdgeInsets.only(top: 0, right: 0, bottom: 20, left: 0),
                child: new Text(
                  isActive ? 'On' : 'Off',
                  style: TextStyle(
                      color: isActive ? Colors.black : Colors.white),
                ),
              ),
            ],
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: Padding(
              padding: EdgeInsets.only(top: 8, left: 5),
              child: Text(
                text,
                style: TextStyle(
                    color: isActive ? Colors.black : Colors.white,
                    fontSize: 13),
              ),
            ),
          ),
        ],
      ),
    ),
  ),
  );
 }
 }

In this widget, I want to able to select when I need to use On and Off, and when I need, Lock and Unlock:

Padding(
                padding:
                EdgeInsets.only(top: 0, right: 0, bottom: 20, left: 0),
                child: new Text(
                  isActive ? 'On' : 'Off',
                  style: TextStyle(
                      color: isActive ? Colors.black : Colors.white),
                ),
              ),

Here is how I call them in my main function, these fisrt custombutton Would need a Lock and unlock, but the second one would need a On and Off. The list is where I track if it is on or off:

 List<bool> cardsValue = [false, false, false, false];

 CustomCard(
                    iconData: cardsValue[0] ? OMIcons.lock : OMIcons.lockOpen,
                    text: 'Front\nDoor Lock',
                    isActive: cardsValue[0],
                    onTap: () {
                      setState(() {
                        cardsValue[0] = !cardsValue[0];
                      });
                    },
                  ),
                  SizedBox(width: 30.0),
                  CustomCard(
                    iconData: Icons.lightbulb_outline,
                    text: 'Lâmpada 2 Schuma',
                    isActive: cardsValue[1],
                    onTap: () {
                      setState(() {
                        cardsValue[1] = !cardsValue[1];
                      });
                    },
                  ),


Solution 1: darkness

Try to change the CustomCard to stateFull Widget.


Solution 2: NoobN3rd

If I got it right, You are looking for having same widgets with different label(sometimes 'on/off' and sometimes 'lock/unlock').

You can have two different variable to define these labels. I did it like this:

import 'package:flutter/material.dart';

void main() {
  runApp(Home());
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  List<bool> cardsValue = [false, false, false, false];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CustomCard(
              activeLabel: 'Lock',
              inActiveLabel: 'Unlock',
              iconData: cardsValue[0] ? Icons.lock : Icons.lock_open,
              text: 'Front\nDoor Lock',
              isActive: cardsValue[0],
              onTap: () {
                setState(() {
                  cardsValue[0] = !cardsValue[0];
                });
              },
            ),
            SizedBox(width: 30.0),
            CustomCard(
              activeLabel: 'On',
              inActiveLabel: 'Off',
              iconData: Icons.lightbulb_outline,
              text: 'Lâmpada 2 Schuma',
              isActive: cardsValue[1],
              onTap: () {
                setState(() {
                  cardsValue[1] = !cardsValue[1];
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class CustomCard extends StatelessWidget {
  final bool isActive;
  final String text;
  final String activeLabel;
  final String inActiveLabel;
  final IconData iconData;
  final VoidCallback onTap;

  const CustomCard({
    this.isActive,
    this.text,
    this.iconData,
    this.onTap,
    this.activeLabel,
    this.inActiveLabel,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        height: 100,
        width: 120,
        child: Card(
          color: isActive ? Colors.white : Colors.grey[800],
          semanticContainer: true,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          margin: new EdgeInsets.all(0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Row(
                children: <Widget>[
                  Padding(
                    padding:
                        EdgeInsets.only(left: 4, top: 7, right: 30, bottom: 10),
                    child: Icon(
                      iconData,
                      color: isActive ? Colors.black : Colors.white,
                      size: 35,
                    ),
                  ),
                  Padding(
                    padding:
                        EdgeInsets.only(top: 0, right: 0, bottom: 20, left: 0),
                    child: new Text(
                      isActive ? activeLabel : inActiveLabel,
                      style: TextStyle(
                          color: isActive ? Colors.black : Colors.white),
                    ),
                  ),
                ],
              ),
              Align(
                alignment: Alignment.bottomLeft,
                child: Padding(
                  padding: EdgeInsets.only(top: 8, left: 5),
                  child: Text(
                    text,
                    style: TextStyle(
                        color: isActive ? Colors.black : Colors.white,
                        fontSize: 13),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Edits based on the comment:

If You only need to change the padding around the label you can also define a padding option for the widget like this:

import 'package:flutter/material.dart';

void main() {
  runApp(Home());
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  List<bool> cardsValue = [false, false, false, false];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CustomCard(
              padding: EdgeInsets.only(top: 0, right: 0, bottom: 10, left: 0),
              activeLabel: 'Lock',
              inActiveLabel: 'Unlock',
              iconData: cardsValue[0] ? Icons.lock : Icons.lock_open,
              text: 'Front\nDoor Lock',
              isActive: cardsValue[0],
              onTap: () {
                setState(() {
                  cardsValue[0] = !cardsValue[0];
                });
              },
            ),
            SizedBox(width: 30.0),
            CustomCard(
              padding: EdgeInsets.only(top: 0, right: 0, bottom: 20, left: 0),
              activeLabel: 'On',
              inActiveLabel: 'Off',
              iconData: Icons.lightbulb_outline,
              text: 'Lâmpada 2 Schuma',
              isActive: cardsValue[1],
              onTap: () {
                setState(() {
                  cardsValue[1] = !cardsValue[1];
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class CustomCard extends StatelessWidget {
  final bool isActive;
  final String text;
  final String activeLabel;
  final String inActiveLabel;
  final IconData iconData;
  final EdgeInsetsGeometry padding;
  final VoidCallback onTap;

  const CustomCard({
    this.isActive,
    this.text,
    this.padding,
    this.iconData,
    this.onTap,
    this.activeLabel,
    this.inActiveLabel,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        height: 100,
        width: 120,
        child: Card(
          color: isActive ? Colors.white : Colors.grey[800],
          semanticContainer: true,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          margin: new EdgeInsets.all(0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Row(
                children: <Widget>[
                  Padding(
                    padding:
                        EdgeInsets.only(left: 4, top: 7, right: 30, bottom: 10),
                    child: Icon(
                      iconData,
                      color: isActive ? Colors.black : Colors.white,
                      size: 35,
                    ),
                  ),
                  Padding(
                    padding: padding,
                    child: new Text(
                      isActive ? activeLabel : inActiveLabel,
                      style: TextStyle(
                          color: isActive ? Colors.black : Colors.white),
                    ),
                  ),
                ],
              ),
              Align(
                alignment: Alignment.bottomLeft,
                child: Padding(
                  padding: EdgeInsets.only(top: 8, left: 5),
                  child: Text(
                    text,
                    style: TextStyle(
                        color: isActive ? Colors.black : Colors.white,
                        fontSize: 13),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

But You can also define a child and icon as widget, so for each of these widgets you can do whatever config you want.


import 'package:flutter/material.dart';

void main() {
  runApp(Home());
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  List<bool> cardsValue = [false, false, false, false];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CustomCard(
              icon: Padding(
                padding: EdgeInsets.only(
                  left: 4,
                  top: 7,
                  right: 30,
                  bottom: 10,
                ),
                child: Icon(
                  cardsValue[0] ? Icons.lock : Icons.lock_open,
                  color: cardsValue[0] ? Colors.black : Colors.white,
                  size: 35,
                ),
              ),
              child: Padding(
                padding: EdgeInsets.only(
                  left: 0,
                  top: 7,
                  right: 0,
                  bottom: 10,
                ),
                child: new Text(
                  cardsValue[0] ? 'Lock' : 'Unlock',
                  style: TextStyle(
                    color: cardsValue[0] ? Colors.black : Colors.white,
                  ),
                ),
              ),
              label: 'Front\nDoor Lock',
              isActive: cardsValue[0],
              onTap: () {
                setState(() {
                  cardsValue[0] = !cardsValue[0];
                });
              },
            ),
            SizedBox(width: 30.0),
            CustomCard(
              icon: Padding(
                padding: EdgeInsets.only(
                  left: 4,
                  top: 7,
                  right: 30,
                  bottom: 10,
                ),
                child: Icon(
                  Icons.lightbulb_outline,
                  color: cardsValue[1] ? Colors.black : Colors.white,
                  size: 35,
                ),
              ),
              child: Padding(
                padding: EdgeInsets.only(
                  left: 4,
                  top: 7,
                  right: 20,
                  bottom: 10,
                ),
                child: new Text(
                  cardsValue[1] ? 'On' : 'Off',
                  style: TextStyle(
                    color: cardsValue[1] ? Colors.black : Colors.white,
                  ),
                ),
              ),
              label: 'Lâmpada 2 Schuma',
              isActive: cardsValue[1],
              onTap: () {
                setState(() {
                  cardsValue[1] = !cardsValue[1];
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class CustomCard extends StatelessWidget {
  final bool isActive;
  final Widget child;
  final String label;
  final Widget icon;
  final VoidCallback onTap;

  const CustomCard({
    this.isActive,
    this.child,
    this.label,
    this.icon,
    this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        height: 100,
        width: 120,
        child: Card(
          color: isActive ? Colors.white : Colors.grey[800],
          semanticContainer: true,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          margin: new EdgeInsets.all(0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Row(
                children: <Widget>[icon, child],
              ),
              Align(
                alignment: Alignment.bottomLeft,
                child: Padding(
                  padding: EdgeInsets.only(top: 8, left: 5),
                  child: Text(
                    label,
                    style: TextStyle(
                        color: isActive ? Colors.black : Colors.white,
                        fontSize: 13),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}


Solution 3: vb10

You can do this but you should think "which one needs it?"

  1. If your card change state on parent view, you can use the stateless widget and rebuild new state like this code. You don't forget to declare this function parent page so wrap your full card and rebuild the state. (Not recommended look at 2)

    void changeSwitchButton() { setState(() { isActiveOnView = !isActiveOnView; }); }

You want is here: https://gist.github.com/0ec9fca4bd246b21276505ae87cd815b

  1. You make a stateful widget on the full card because your card widget needs state(rebuild options). If the card has own state, card widget self-change on view not need any parent changes. This method is more correct way other situation.

    Widget build(BuildContext context) { return InkWell( onTap: onTapCard, child: buildContainerCard(), ); } void onTapCard() { setState(() { isActive = !isActive; }); widget.onTap(); }

More detail look this repo.(lib/switch-on)

Switcher