Home > OS >  Flutter - How to change the visibility of a single widget in a widget list?
Flutter - How to change the visibility of a single widget in a widget list?

Time:07-27

I pull some variables in Firebase and I create a widget list with these variables. I want to control widget visibility when I click a widget. When I use the Visibility widget and set "visible: widgetVisibility" value, all widgets are changed at the same time. I only want the widget I clicked to change. How can I do that?

body: StreamBuilder<QuerySnapshot>(
        stream: _keyService.getKeys(),
        builder: (context, snapshot) {
          return !snapshot.hasData
              ? const Center(child: CircularProgressIndicator())
              : ListView.builder(
                  itemCount: snapshot.data!.docs.length,
                  itemBuilder: (context, index) {
                    DocumentSnapshot mypost = snapshot.data!.docs[index];

                    return Padding(
                      padding: EdgeInsets.all(size * 0.3),
                      child: InkWell(
                        onTap: () {
                          valueVisible = !valueVisible;
                        },
                  
                        child: Container(
                          decoration: BoxDecoration(
                              color: ColorItems.mainColor,
                              border: Border.all(width: 5, color: Colors.grey),
                              borderRadius: BorderRadius.all(Radius.circular(20))),
                          child: Padding(
                            padding: EdgeInsets.all(size),
                            child: Container(
                              child: Row(
                                children: [
                                  Expanded(
                                    child: Text(
                                      "${mypost['key']}",
                                      style: const TextStyle(
                                          color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
                                    ),
                                  ),
                                  const Text(
                                    ": ",
                                    style:
                                        TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
                                  ),
                                  const SizedBox(
                                    width: 20,
                                  ),
                                  Expanded(
                                      child: Visibility(
                                    visible: valueVisible,
                                    child: Text(
                                      "${mypost['value']}",
                                      style: const TextStyle(
                                          color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
                                    ),
                                  ))
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
                    );
                  },
                );
        })

Additionally, screenshots is here..

CodePudding user response:

This might not be the optimal solution, but I always create a List for that purpose:

instead of one valueVisible bool I create a List and add a bool for each item in the list.

...itemBuilder: (context, index) { valueVisibleList.add(true)...

and in the button I then use the current item index to change only the corresponding bool

 onTap: () { setState(({ 
               valueVisibleList[index]!valueVisibleList[index];
               })
             },

hope that helps :)

CodePudding user response:

Just use a Map<String, bool> where the keys are the post's key and the value its visibility. The visibility should default to true if the key is not present. And the state should only change inside a setState function.

It would be something like the following (Check out the Screenshot

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

final posts = [
  for (var i = 0; i < 100; i  ) {'key': 'key$i', 'value': '$i'}
];

class _MyHomePageState extends State<MyHomePage> {
  final valueVisible = <String, bool>{};

  @override
  Widget build(BuildContext context) {
    const size = 16.0;

    return Scaffold(
      body: ListView.builder(
        itemCount: posts.length,
        itemBuilder: (context, index) {
          final mypost = posts[index];

          return Padding(
            padding: const EdgeInsets.all(size * 0.3),
            child: InkWell(
              onTap: () {
                setState(() {
                  valueVisible[mypost['key']!] =
                      !(valueVisible[mypost['key']!] ?? true);
                });
              },
              child: Container(
                decoration: BoxDecoration(
                    color: const Color(0xffff9400),
                    border: Border.all(width: 5, color: Colors.grey),
                    borderRadius: const BorderRadius.all(Radius.circular(20))),
                child: Padding(
                  padding: const EdgeInsets.all(size),
                  child: Row(
                    children: [
                      Expanded(
                        child: Text(
                          "${mypost['key']}",
                          style: const TextStyle(
                              color: Colors.white,
                              fontSize: 24,
                              fontWeight: FontWeight.bold),
                        ),
                      ),
                      const Text(
                        ": ",
                        style: TextStyle(
                            color: Colors.white,
                            fontSize: 24,
                            fontWeight: FontWeight.bold),
                      ),
                      const SizedBox(
                        width: 20,
                      ),
                      Expanded(
                        child: Visibility(
                          visible: valueVisible[mypost['key']!] ?? true,
                          child: Text(
                            "${mypost['value']}",
                            style: const TextStyle(
                                color: Colors.white,
                                fontSize: 24,
                                fontWeight: FontWeight.bold),
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}
  • Related