设备上的 Flutter 保存按钮状态

Flutter Saving button state on device

我有一个搜索屏幕,用户可以在其中搜索一个县,并显示该县的 post 疫苗接种列表。有的县多有的少。

在疫苗接种列表 posts 中,有一个按钮,按下后该按钮将被禁用。到这里为止一切都很好,但是当我重新搜索同一个县时,曾经被禁用的按钮不再被禁用,这意味着它可以再次按下。我想避免这种情况。

我有一个布尔值列表,每次疫苗接种都为“真”post。按下按钮时,列表中的相应索引将更改为“false”,从而禁用该按钮。

问题:如何让按钮保持禁用状态? (是否重新搜索同一个县或重新打开应用程序)

import 'package:colour/colour.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
// import 'package:shared_preferences/shared_preferences.dart';

class VaccineCenterList extends StatefulWidget {
  const VaccineCenterList({key}) : super(key: key);
  static const String idScreen = "VaccineCenterList";

  @override
  _VaccineCenterListState createState() => _VaccineCenterListState();
}

class _VaccineCenterListState extends State<VaccineCenterList> {
  TextEditingController hospitalCountyEditingController =
      TextEditingController();
  final databaseReference = FirebaseDatabase.instance.reference();
  final firestoreInstance = FirebaseFirestore.instance;
  FirebaseAuth auth = FirebaseAuth.instance;
  List<Hospitals> driverList = [];

  List<bool> buttonPressed = [];
  // Map<String, List> buttonPressed = {};

  buttonControls(numOfLocations) {
    print(numOfLocations);
    int checker = 0;
    if (numOfLocations > buttonPressed.length) {
      try {
        while (numOfLocations >= checker) {
          buttonPressed.add(true);
          checker = checker + 1;
        }
      } catch (e) {
        print("$e");
      }
    } else {}
    print(buttonPressed);
  }

  @override
  void initState() {
    super.initState();
    print("I'm in the vaccine list search screen");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        backgroundColor: Colors.grey[100],
        centerTitle: true,
        elevation: 0,
        iconTheme: const IconThemeData(
          color: Colors.black,
        ),
        title: Text(
          "Pamoja",
          style: GoogleFonts.lexendMega(
            fontWeight: FontWeight.bold,
            color: Colors.black,
            fontSize: 35,
          ),
        ),
      ),
      body: GestureDetector(
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
        },
        child: SingleChildScrollView(
          child: Column(
            children: [
              Container(
                // textfield
                padding: const EdgeInsets.all(8.0),
                child: TextField(
                  controller: hospitalCountyEditingController,
                  keyboardType: TextInputType.text,
                  textCapitalization: TextCapitalization.words,
                  decoration: InputDecoration(
                    border: const OutlineInputBorder(
                      borderSide: BorderSide(
                        color: Colors.black,
                        style: BorderStyle.solid,
                        width: 1,
                      ),
                    ),
                    labelText: "Search County",
                    labelStyle: const TextStyle(
                      fontSize: 14.0,
                      color: Colors.blueGrey,
                    ),
                    hintStyle: GoogleFonts.lexendMega(
                      color: Colors.grey,
                      fontSize: 10,
                    ),
                  ),
                  style: GoogleFonts.lexendMega(
                    fontSize: 14,
                    color: Colors.black,
                  ),
                ),
              ),
              ElevatedButton(
                // search button
                onPressed: () {
                  setState(() {
                    FocusScope.of(context).requestFocus(
                      FocusNode(),
                    );
                    driverList.clear();
                    if (hospitalCountyEditingController.text == "" ||
                        hospitalCountyEditingController.text == " ") {
                      isTrueOrFalse = "False";
                    } else {
                      isTrueOrFalse = "True";
                    }
                  });
                  getHospitalDetails();
                },
                child: Text(
                  "Search",
                  style: GoogleFonts.lexendMega(
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
              SingleChildScrollView(
                child: Column(
                  children: [
                    SizedBox(
                      height: MediaQuery.of(context).size.height,
                      // height: 50,

                      // color: Colors.black,
                      child: Padding(
                        padding: const EdgeInsets.only(
                          right: 12.0,
                          left: 12.0,
                          bottom: 12.0,
                        ),
                        child: driverList.isEmpty
                            ? Center(
                                // child: CircularProgressIndicator(),
                                child: (isTrueOrFalse == "True")
                                    ? const CircularProgressIndicator()
                                    : Column(
                                        mainAxisAlignment:
                                            MainAxisAlignment.center,
                                        children: [
                                          Padding(
                                            padding: const EdgeInsets.all(8.0),
                                            child: Text(
                                                "Search for one of the counties below",
                                                style:
                                                    GoogleFonts.lexendMega()),
                                          ),
                                          Text(
                                            "Nairobi, Baringo, Busia, Bomet, Bungoma, Elgeyo Marakwet, Embu, Garissa, Homa Bay, Isiolo, Kajiado, Kakamega, Kericho, Kiambu, Kilifi, Kirinyaga, Kisii, Kisumu, Kitui, Kwale, Laikipia, Lamu, Machakos, Makueni, Mandera, Marsabit, Meru, Migori, Mombasa, Muranga, Nakuru, Nandi, Narok, Nyamira, Nyandarua, Nyeri, Samburu, Siaya County, Taita Taveta, Tana River County, Tharaka Nithi, Trans Nzoia, Turkana, Uasin Gishu, Vihiga, Wajir, West Pokot",
                                            textAlign: TextAlign.center,
                                            style: GoogleFonts.lexendMega(
                                              fontWeight: FontWeight.bold,
                                            ),
                                          ),
                                        ],
                                      ),
                              )
                            : ListView.builder(
                                itemCount: driverList.length,
                                itemBuilder: (context, index) {
                                  final Hospitals hospitals = driverList[index];
                                  final String hospitalLocaiton =
                                      hospitals.location;
                                  final String hospitalPhone = hospitals.phone;
                                  final String hospitalName = hospitals.name;

                                  positiveCount = hospitals.positiveCount;
                                  negativeCount = hospitals.negativeCount;

                                  final int setpercentage =
                                      calculatePositivePercentage(
                                          positiveCount, negativeCount);

                                  buttonControls(driverList.length);

                                  return Padding(
                                    padding: const EdgeInsets.all(8.0),
                                    child: Card(
                                      elevation: 0,
                                      child: ExpansionTile(
                                        title: Text(
                                          hospitalName.toUpperCase(),
                                          style: GoogleFonts.lexendMega(),
                                          textAlign: TextAlign.center,
                                        ),
                                        children: [
                                          Column(
                                            children: [
                                              Container(
                                                child: (hospitalPhone
                                                        .isNotEmpty)
                                                    ? ElevatedButton(
                                                        onPressed: () {
                                                          Clipboard.setData(
                                                            ClipboardData(
                                                              text:
                                                                  hospitalPhone,
                                                            ),
                                                          );
                                                          ScaffoldMessenger.of(
                                                                  context)
                                                              .showSnackBar(
                                                            const SnackBar(
                                                              backgroundColor:
                                                                  Colors.green,
                                                              content: Text(
                                                                "Number Copied",
                                                                textAlign:
                                                                    TextAlign
                                                                        .center,
                                                              ),
                                                            ),
                                                          );
                                                        },
                                                        child: Text(
                                                          hospitalPhone,
                                                          textAlign:
                                                              TextAlign.center,
                                                          style: GoogleFonts
                                                              .lexendMega(
                                                                  fontSize: 13),
                                                        ),
                                                        style: ElevatedButton
                                                            .styleFrom(
                                                          elevation: 0,
                                                        ),
                                                      )
                                                    : const Text(""),
                                              ),
                                              const SizedBox(
                                                height: 5,
                                              ),
                                              hospitalLocaiton.isNotEmpty
                                                  ? Container(
                                                      padding:
                                                          const EdgeInsets.all(
                                                              8),
                                                      decoration: BoxDecoration(
                                                        border: Border.all(
                                                          color: Colors.black,
                                                        ),
                                                        borderRadius:
                                                            BorderRadius
                                                                .circular(10),
                                                      ),
                                                      child: Text(
                                                        hospitalLocaiton,
                                                        textAlign:
                                                            TextAlign.center,
                                                        style: GoogleFonts
                                                            .lexendMega(
                                                          fontSize: 12,
                                                        ),
                                                      ),
                                                    )
                                                  : Text(
                                                      hospitalLocaiton,
                                                      textAlign:
                                                          TextAlign.center,
                                                      style: GoogleFonts
                                                          .lexendMega(
                                                        fontSize: 12,
                                                      ),
                                                    ),
                                              const SizedBox(
                                                height: 10,
                                              ),
                                              Text(
                                                "$setpercentage% (percent) of voters say this hospital administer vaccines.",
                                                textAlign: TextAlign.center,
                                                style: GoogleFonts.lexendMega(
                                                  fontWeight: FontWeight.bold,
                                                  fontSize: 12,
                                                  color: Colors.deepPurple[400],
                                                ),
                                              ),
                                              const SizedBox(
                                                height: 10,
                                              ),
                                              const Divider(
                                                // thickness: 1,
                                                indent: 20,
                                                endIndent: 20,
                                                color: Colors.black87,
                                              ),
                                              const SizedBox(
                                                height: 10,
                                              ),
                                              Text(
                                                "Does this Hospital administer Vaccines?\n(To help the public, please vote only if you know.)",
                                                textAlign: TextAlign.center,
                                                style: GoogleFonts.lexendMega(
                                                  fontSize: 12,
                                                  fontWeight: FontWeight.bold,
                                                ),
                                              ),
                                              Column(
                                                children: [
                                                  Row(
                                                    mainAxisAlignment:
                                                        MainAxisAlignment
                                                            .spaceEvenly,
                                                    children: [
                                                      ElevatedButton(
                                                        onPressed:
                                                            buttonPressed[index]
                                                                ? () {
                                                                    positiveIncrement(
                                                                        hospitalName,
                                                                        index);
                                                                    buttonPressed[
                                                                            index] =
                                                                        false;
                                                                    ScaffoldMessenger.of(
                                                                            context)
                                                                        .showSnackBar(
                                                                      const SnackBar(
                                                                        backgroundColor:
                                                                            Colors.redAccent,
                                                                        content:
                                                                            Text(
                                                                          "Voted",
                                                                          textAlign:
                                                                              TextAlign.center,
                                                                        ),
                                                                      ),
                                                                    );
                                                                  }
                                                                : null,
                                                        child: Text(
                                                          "Yes",
                                                          style: GoogleFonts
                                                              .lexendMega(),
                                                        ),
                                                        style: ElevatedButton
                                                            .styleFrom(
                                                          primary:
                                                              Colour("#87D68D"),
                                                        ),
                                                      ),
                                                      ElevatedButton(
                                                        onPressed:
                                                            buttonPressed[index]
                                                                ? () {
                                                                    negativeIncrement(
                                                                        hospitalName,
                                                                        index);
                                                                    buttonPressed[
                                                                            index] =
                                                                        false;
                                                                    ScaffoldMessenger.of(
                                                                            context)
                                                                        .showSnackBar(
                                                                      const SnackBar(
                                                                        backgroundColor:
                                                                            Colors.redAccent,
                                                                        content:
                                                                            Text(
                                                                          "Voted",
                                                                          textAlign:
                                                                              TextAlign.center,
                                                                        ),
                                                                      ),
                                                                    );
                                                                  }
                                                                : null,
                                                        child: Text(
                                                          "No",
                                                          style: GoogleFonts
                                                              .lexendMega(),
                                                        ),
                                                        style: ElevatedButton
                                                            .styleFrom(
                                                          primary:
                                                              Colour("#E3655B"),
                                                        ),
                                                      ),
                                                    ],
                                                  ),
                                                  const SizedBox(
                                                    height: 10,
                                                  ),
                                                  Text(
                                                    "1 - To vote, tap once\n2 - To Undo vote, tap and hold",
                                                    style:
                                                        GoogleFonts.lexendMega(
                                                      fontSize: 12,
                                                    ),
                                                    textAlign: TextAlign.start,
                                                  ),
                                                  const SizedBox(
                                                    height: 10,
                                                  ),
                                                ],
                                              ),
                                            ],
                                          ),
                                        ],
                                      ),
                                    ),
                                  );
                                },
                              ),
                      ),
                    ),
                    // SizedBox(height: 40),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Hospitals {
  final String name;
  final String phone;
  final String location;
  // final String county;
  final int positiveCount;
  final int negativeCount;
  // final int intPercentage;
  // final int totalVotes;

  Hospitals({
    required this.name,
    required this.phone,
    required this.location,
    // required this.county,
    required this.positiveCount,
    required this.negativeCount,
    // required this.intPercentage,
    // required this.totalVotes,
  });

  static Hospitals fromJson(Map<String, dynamic> json) {
    return Hospitals(
      name: json['HospitalName'],
      phone: json['HospitalPhone'],
      // county: json['county'],
      location: json['HospitalAddres'],
      positiveCount: json['poitiveCount'],
      negativeCount: json['negativeCount'],
      // intPercentage: json['intPercentage'],
      // totalVotes: json['totalVotes']
    );
  }
}

我是这样做的:使用provider设置值,使boolean

 late bool isMyButtonEnabled;

//in initState

setState(() {
      isMyButtonEnabled=
          myProvider.checkIfButtonShouldBeEnabled(widget.Id);
    }

//in build

ElevatedButton(
                              child: Text('SUBMIT'),
                              onPressed: !isMyButtonEnabled
                                  ? null
                                  : () async => {
//some code

                                   }

通过这种方式,您的 boolean 将使用 Provider 包保存并在应用程序中随处可用(那里也可以使用其他更高级的 Provider 类似物)