简体   繁体   中英

Flutter : how to conditionally repeat a showDialog inside a ListView

I am using the flutter_reactive_ble_example to connect to my Bluetooth module by modifying the file device_list.dart.

and I wonder how do I re prompt the user if password is wrong.

I'm fairly new to flutter, please do ask more details if required.

here is the code snippet that I currently have:

Flexible(
child: ListView(
  children: widget.scannerState.discoveredDevices
      .map(
        (device) => ListTile(
          title: Text(tile.name),
          subtitle: Text("${tile.name}\n: ${tile.sub}"),
          leading: const ConnectIcon(),
          onTap: () async {
            //stop the scan
            widget.stopScan();
            //connect to the device
            await widget.deviceConn.connect(device.id);
            //prompt user for password              
            final inputData = await showDialog(
              context: context,
              barrierDismissible:
                  false, // prevent user from closing the dialog by pressing outside the dialog
              builder: (_) {
                String userData = "";
                return AlertDialog(
                  title: new Text("Enter Password"),
                  content: new TextField(
                    onChanged: (value) {
                      userData = value;
                    },
                  ),
                  actions: <Widget>[
                    ElevatedButton(
                      child: Text('Ok'),
                      onPressed: () async {
                        //on press subscribe and send the password
                        response = await ble.subscribeToCharacteristic(characteristic);

                        //if data failure check, how do I reshow this showDialog??
                        response.listen((event) {
                            if(event == 1){
                              //if return 1, password correct 
                              Navigator.of(context).pop(userData);
                            }else{                                  
                              //if not reshow Dialog
                              //howw?
                            }                                                                
                        }
                        
                        //send password
                        ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
                      },
                    )
                  ],
                );
              },
            );

            Navigator.of(context).pop(
                inputData); // pass data back to the previous page
          },
        ),
      )
      .toList(),
),
),
      

You can use a recursion I think, here an example

Future _showPasswordDialog(){
 return showDialog(
              context: context,
              barrierDismissible:
                  false, // prevent user from closing the dialog by pressing outside the dialog
              builder: (_) {
                String userData = "";
                return AlertDialog(
                  title: new Text("Enter Password"),
                  content: new TextField(
                    onChanged: (value) {
                      userData = value;
                    },
                  ),
                  actions: <Widget>[
                    ElevatedButton(
                      child: Text('Ok'),
                      onPressed: () async {
                        //on press subscribe and send the password
                        response = await ble.subscribeToCharacteristic(characteristic);

                        //if data failure check, how do I reshow this showDialog??
                        response.listen((event) {
                            if(event == 1){
                              //if return 1, password correct 
                              Navigator.of(context).pop(userData);
                            }else{                                  
                              //if not reshow Dialog
                              //howw?
                             Navigator.of(context).pop();
                             _showPasswordDialog();
                           }                                                                
                        }
                        
                        //send password
                        ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
                      },
                    )
                  ],
                );
              },
            );
}

separate the the alert prompting as another function, and return user details if login success else return null.

Future<String> promptAlert(BuildContext context){

 return showDialog(
              context: context,
              barrierDismissible:
                  false, // prevent user from closing the dialog by pressing outside the dialog
              builder: (_) {
                String userData = "";
                return AlertDialog(
                  title: new Text("Enter Password"),
                  content: new TextField(
                    onChanged: (value) {
                      userData = value;
                    },
                  ),
                  actions: <Widget>[
                    ElevatedButton(
                      child: Text('Ok'),
                      onPressed: () async {
                        //on press subscribe and send the password
                        response = await ble.subscribeToCharacteristic(characteristic);

                        //if data failure check, how do I reshow this showDialog??
                        response.listen((event) {
                            if(event == 1){
                              //if return 1, password correct 
                              Navigator.of(context).pop(userData);
                            }else{                                  
                               Navigator.of(context).pop();
                            }                                                                
                        }
                        
                        //send password
                        ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
                      },
                    )
                  ],
                );
              },
            );

}

and check for the returned value is not null on the ListItem onTap

bool isLogin = (await promptAlert(context)) !=null;
while(isLogin ){
           ScaffoldMessenger.of(context).showSnackBar(SnackBar(
           duration: Duration(seconds: 2),
           content: Text('Login Failed Try again')));
           String user= await Future.delayed(
                  Duration(seconds: 2), () => promptAlert(context));
 isLogin =  user !=null;
}

If you want to show a snackbar and delayed alert,

                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    duration: Duration(seconds: 2),
                    content: Text('Login Failed Try again'),
                  ));
                  Future.delayed(
                      Duration(seconds: 2), () => promptAlert(context));
              

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM