79828692

Date: 2025-11-24 13:34:43
Score: 1.5
Natty:
Report link

Based on @Bibek Saha's answer I am providing here another solution which makes the open/close state private to the CardCloseable class. There are one and a "half" disadvantages with this method versus a big advantage of blackboxing the CardCloseable's state and not needing to keep it with N variables for N Cards (or a Map) in the Dialog's onPressed():

  1. I am now using a StatefulWidget instead of state-less, so less efficient.
  2. When the Card has been closed the CardCloseable class still rebuilds! But it builds an "invisible" SizedBox.shrink() widget and not a Card (see the logic in its build method). This can be improved if anyone can suggest what's the practice here because I could not find a way to return back from build a null widget, indicating not to bother with this widget. I am new to flutter.

Here is my solution based on @Bibek Saha's:

import 'package:flutter/material.dart';

/// Flutter code sample for [Card].

void main() => runApp(const CardExampleApp());

class CardExampleApp extends StatelessWidget {
  const CardExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Card Sample')),
        body: MyExample(),
      ),
    );
  }
}

class MyExample extends StatelessWidget {
  const MyExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      child: Text("press to show dialog"),
      onPressed: () {
        showDialog(
          barrierDismissible: true,
          barrierColor: Colors.red.withAlpha(90),
          context: context,
          builder: (BuildContext ctx) {
            return Container(
              decoration: BoxDecoration(
                border: Border.all(color: Colors.blueAccent, width: 2),
                borderRadius: BorderRadius.circular(8.0),
              ),
              child: Column(
                children: [
                  CardCloseable(text: "item"),
                  CardCloseable(text: "another item"),
                  CardCloseable(text: "another item"),
                ],
              ),
            );
          },
        );
      },
    );
  }
}

class CardCloseable extends StatefulWidget {
  final String text;
  final double width;

  // optionally, creator can supply extra callback for when closing
  final VoidCallback? onClose;

  const CardCloseable({
    super.key,
    required this.text,
    this.onClose,
    this.width = 200,
  });

  @override
  State<CardCloseable> createState() => _CardCloseableState();
}

class _CardCloseableState extends State<CardCloseable> {
  bool isOpen = true;

  @override
  void initState() {
    isOpen = true;
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return isOpen
        ? SizedBox(
            width: 200,
            child: Card(
              color: Color(0xFFCCAAAA),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  // TODO: this closes the whole map!!!
                  Align(
                    alignment: Alignment.topRight,
                    child: IconButton(
                      icon: Icon(Icons.close, color: Colors.red),
                      onPressed: () {
                        setState(() {
                          isOpen = false;
                        });
                        if (widget.onClose != null) {
                          widget.onClose!();
                        }
                      },
                      ),
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(horizontal: 10),
                    child: Text(widget.text),
                  ),
                ],
              ),
            ),
          )
        // if we are in a closed state, then return this:
        // this is bad design
        : SizedBox.shrink();
  }
}

class MyCard extends StatelessWidget {
  final String text;

  const MyCard({super.key, required this.text});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[CloseButton(), Text("the contents: $text")],
        ),
      ),
    );
  }
}
Reasons:
  • RegEx Blacklisted phrase (1.5): I am new
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Bibek
  • User mentioned (0): @Bibek
  • Self-answer (0.5):
Posted by: bliako