【问题标题】:How do you create multiple buttons in a ListView that are independent of each other?如何在 ListView 中创建多个相互独立的按钮?
【发布时间】:2022-07-13 22:42:45
【问题描述】:

我已经设置了一个 Firestore 数据库,其中有一个集合“产品”。我使用 ListView 构建器将它们打印在 ListTiles 上。 我还创建了出现在所有 ListTiles 上的前导“复选标记”图标按钮。 我的目标是能够按下这些复选标记按钮中的任何一个并独立更改它们的颜色。目前,当您按下其中一个时,所有复选标记按钮都会改变颜色。 我不知道如何实现这一点,希望能得到一些帮助。

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

  @override
  State<HomeScreenProductList> createState() => _HomeScreenProductListState();
}

class _HomeScreenProductListState extends State<HomeScreenProductList> {
  final CollectionReference _productsCollection =
      FirebaseFirestore.instance.collection('products');

  final Stream<QuerySnapshot> _products = FirebaseFirestore.instance
      .collection('products')
      .orderBy('product-name')
      .snapshots();

  deleteProduct(id) async {
    await _productsCollection.doc(id).delete();
  }

  Color tileColor = const Color.fromARGB(100, 158, 158, 158);
  Color iconColor = Colors.red;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
        stream: _products,
        builder: (
          BuildContext context,
          AsyncSnapshot<QuerySnapshot> snapshot,
        ) {
          if (snapshot.hasError) {
            return const Text('Something went wrong');
          }
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Text('Loading data');
          }

          final productData = snapshot.requireData;

          return ListView.builder(
            padding: const EdgeInsets.only(top: 16.0),
            itemCount: productData.size,
            itemBuilder: (context, index) {
              return Card(
                child: ListTile(
                  leading: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: Icon(Icons.check, color: iconColor),
                        onPressed: () {
                          setState(() {
                            if (iconColor != Colors.green) {
                              iconColor = Colors.green;
                            } else {
                              iconColor = Colors.red;
                            }
                          });
                        },
                      )
                    ],
                  ),
                  tileColor: tileColor,
                  shape: const UnderlineInputBorder(
                      borderSide: BorderSide(
                          width: 1, color: Color.fromARGB(120, 220, 220, 220))),
                  title: Text('${productData.docs[index]['product-name']}'),
                  textColor: const Color.fromARGB(255, 0, 0, 0),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: const Icon(Icons.delete),
                        color: Colors.red,
                        padding: EdgeInsets.zero,
                        constraints: const BoxConstraints(),
                        onPressed: () {
                          print("Delete Button Pressed");
                          deleteProduct(snapshot.data?.docs[index].id);
                        },
                      )
                    ],
                  ),
                ),
              );
            },
          );
        });
  }
}

完整代码:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const ShoppingListApp());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomeScreen(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return HomeScreenAppBar();
  }
}

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

  final CollectionReference _products =
      FirebaseFirestore.instance.collection('products');

  final _controller = TextEditingController();

  String? _productName;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color.fromARGB(245, 244, 253, 255),
        appBar: AppBar(
          backgroundColor: Colors.amberAccent,
          leading: IconButton(
            icon: const Icon(Icons.settings),
            iconSize: 20,
            color: Colors.black,
            splashColor: Colors.white,
            onPressed: () {
              print("Settings Button Pressed");
            },
          ),
          title: TextFormField(
            style: const TextStyle(fontSize: 18, fontFamily: 'Raleway'),
            controller: _controller,
            decoration: const InputDecoration(
                enabledBorder: UnderlineInputBorder(
                    borderSide:
                        BorderSide(color: Color.fromARGB(245, 244, 253, 255))),
                focusedBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.black)),
                hintText: 'Enter product',
                hintStyle:
                    TextStyle(color: Color.fromARGB(200, 255, 255, 255))),
            onChanged: (value) {
              _productName = value;
            },
          ),
          actions: [
            IconButton(
              icon: const Icon(Icons.add),
              iconSize: 24,
              color: Colors.black,
              splashColor: Colors.white,
              onPressed: () {
                if (_controller.text == '') {
                  return;
                } else {
                  _products
                      .add({'product-name': _productName, 'isbought': false})
                      .then(
                          (value) => print('New Product "$_productName" Added'))
                      .catchError((error) => print(
                          'Failed To Add Product "$_productName": $error'));
                  _controller.clear();
                }
              },
            )
          ],
        ),
        body: const HomeScreenProductList());
  }
}

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

  @override
  State<HomeScreenProductList> createState() => _HomeScreenProductListState();
}

class _HomeScreenProductListState extends State<HomeScreenProductList> {
  final CollectionReference _productsCollection =
      FirebaseFirestore.instance.collection('products');

  final Stream<QuerySnapshot> _products = FirebaseFirestore.instance
      .collection('products')
      .orderBy('product-name')
      .snapshots();

  deleteProduct(id) async {
    await _productsCollection.doc(id).delete();
  }

  Color tileColor = const Color.fromARGB(100, 158, 158, 158);
  Color iconColor = Colors.red;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
        stream: _products,
        builder: (
          BuildContext context,
          AsyncSnapshot<QuerySnapshot> snapshot,
        ) {
          if (snapshot.hasError) {
            return const Text('Something went wrong');
          }
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Text('Loading data');
          }

          final productData = snapshot.requireData;

          return ListView.builder(
            padding: const EdgeInsets.only(top: 16.0),
            itemCount: productData.size,
            itemBuilder: (context, index) {
              return Card(
                child: ListTile(
                  leading: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: Icon(Icons.check, color: iconColor),
                        onPressed: () {
                          setState(() {
                            if (iconColor != Colors.green) {
                              iconColor = Colors.green;
                            } else {
                              iconColor = Colors.red;
                            }
                          });
                        },
                      )
                    ],
                  ),
                  tileColor: tileColor,
                  shape: const UnderlineInputBorder(
                      borderSide: BorderSide(
                          width: 1, color: Color.fromARGB(120, 220, 220, 220))),
                  title: Text('${productData.docs[index]['product-name']}'),
                  textColor: const Color.fromARGB(255, 0, 0, 0),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: const Icon(Icons.delete),
                        color: Colors.red,
                        padding: EdgeInsets.zero,
                        constraints: const BoxConstraints(),
                        onPressed: () {
                          print("Delete Button Pressed");
                          deleteProduct(snapshot.data?.docs[index].id);
                        },
                      )
                    ],
                  ),
                ),
              );
            },
          );
        });
  }
}

    

    

【问题讨论】:

    标签: flutter firebase dart google-cloud-firestore


    【解决方案1】:

    这是因为您将 IconColor 用作单个全局变量。你可以做的是为ProductData中的每个数据创建一个布尔列表

    List<bool> iconColorList = List<bool>.filled(ProductData.size, false);
    

    在列表视图构建器中

                          IconButton(
                            icon: Icon(Icons.check, color: iconColorList[index] ? Colors.green : Colors.false),
                            onPressed: () {
                              setState(() {
                                if (iconColorList[index]) {
                                  iconColorList[index] = false;
                                } else {
                                  iconColorList[index] = true;
                                }
                              });
                            },
                          )
    

    【讨论】:

      【解决方案2】:

      您正在使用单个变量 iconColor 来更改所有项目。这就是为什么所有项目都会通过更改其中任何一个而受到影响。您可以创建一个List&lt;int&gt; 来保存选定的索引 , List&lt;YourModelClass&gt; 或在您的模型上创建另一个布尔变量 bool icChecked = false

      这种方法在状态类上保留选定的索引。

      在状态类(_HomeScreenProductListState) 上创建

      List<int> selectedIndex = []
      

      在项目点击事件上

      icon: Icon(Icons.check, color: selectedIndex.contains(index)?mySelectedColor:unSelectedColor)
      onPressed: () {
        if (selectedIndex.contains(index)) {
          selectedIndex.remove(index);
        } else {
          selectedIndex.add(index);
        }
      
        setState(() {});
      },
      

      mySelectedColorunSelectedColor 是两个 Color 对象,根据您的需要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多