skip to Main Content

I am working on flutter app, where I am generating QR code for payment. When user click on Generate QR code button, it will call an API which return svg.
My problem is that when I receive this svg from API, I update state. In my code, I have condition that if this state is null, display button, else display svg. However, I click on button, state is updated but my UI is not updated. I need to click on for example text input to see this image. How can I fix this problem, so that after button click it will update UI without me needing to click somewhere?
I also tried to add spinner until API request is completed, but again, state was updated (I printed everything), but spinner was spinning infinitely.

Here is how I declare svg image variable

String? paymentQrCode;

Here is my function, which is getting svg from API and updating state.

handleQrCodePaymentMethod() async {
    try {
      final authService = AuthenticationService();
      final dioClient = DioClient(authService);
      ApiClient apiClient =
          ApiClient(baseUrl: Env.apiUrl, dioClient: dioClient);

      String endpoint = 'funds/generate-payment';

      Map<String, String> data = {
        'paymentType': 'qrCode',
        'iban': _iban,
        'bic': _swift,
        'bank': _bankName,
        'paymentIdentification': widget.accountId,
        'amount': _priceController.text,
        'currency': _selectedFundsCurrency.toString(),
      };

      var response = await apiClient.performPostRequest(endpoint, data);

      if (response['response'] == 'OK') {
        setState(() {
          paymentQrCode = response['qrCode'];
        });
      }
    } catch (e) {
      print('Catch error: $e');
    }
  }

And here is my how I call my dialog and also dialog it self.

PopupMenuButton<String>(
                            icon: const Icon(Icons.more_vert,
                                color: Color.fromRGBO(235, 235, 245, 0.6)),
                            shape: const RoundedRectangleBorder(
                              borderRadius:
                                  BorderRadius.all(Radius.circular(16.0)),
                            ),
                            color: Colors.white,
                            onSelected: (String value) {
                              if (value == 'settings') {
                                _settings(context, widget.name,
                                    widget.investmentTarget);
                              } else if (value == 'addFunds') {
                                _addFunds(context);
                              } else if (value == 'accountStatement') {
                                _accountStatement(context);
                              } else if (value == 'taxAccountStatement') {
                                _taxAccountStatement(context);
                              }
                            },

AddFunds dialog:

Future<bool> _addFunds(BuildContext context) {
    bool isDepositInfoVisible = false;

    return showDialog<bool>(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setStateDialog) {
            return AlertDialog(
              contentPadding:
                  const EdgeInsets.symmetric(horizontal: 12, vertical: 20),
              insetPadding:
                  const EdgeInsets.symmetric(horizontal: 12, vertical: 20),
              title: Row(
                children: [

….

paymentQrCode == null
                                                      ? ElevatedButton(
                                                          onPressed: () =>
                                                              handleQrCodePaymentMethod(),
                                                          style: ElevatedButton
                                                              .styleFrom(
                                                            minimumSize:
                                                                const Size(
                                                                    200, 50),
                                                            padding:
                                                                const EdgeInsets
                                                                    .symmetric(
                                                                    vertical:
                                                                        14.0,
                                                                    horizontal:
                                                                        20.0),
                                                            backgroundColor:
                                                                const Color
                                                                    .fromRGBO(
                                                                    0,
                                                                    122,
                                                                    255,
                                                                    1),
                                                            foregroundColor:
                                                                Colors.white,
                                                          ),
                                                          child: Text(
                                                            AppLocalizations.of(
                                                                    context)!
                                                                .detailsGenerateButton,
                                                          ),
                                                        )
                                                      : Padding(
                                                          padding:
                                                              const EdgeInsets
                                                                  .only(
                                                                  bottom: 65.0),
                                                          child:
                                                              SvgPicture.string(
                                                            paymentQrCode
                                                                .toString(),
                                                            key: ValueKey<
                                                                    String>(
                                                                paymentQrCode
                                                                    .toString()),
                                                            height: 330,
                                                            width: 330,
                                                          ),
                                                        )            

   

So as you can see, there is part where I check if paymentQrCode is null, then I display button, else I display svg image itself.

Thanks for any advices!

2

Answers


  1. Chosen as BEST ANSWER

    I managed to get it working.

    In my addFunds dialog I am declaring 'StateSetter setStateDialog'.

     Future<bool> _addFunds(BuildContext context) {
        bool isDepositInfoVisible = false;
    
        return showDialog<bool>(
          barrierDismissible: false,
          context: context,
          builder: (BuildContext context) {
            return StatefulBuilder(
              builder: (BuildContext context, StateSetter setStateDialog) {
                return AlertDialog(
    

    I tried to pass it as a parameter to function, where I am saving state.

    onPressed: () => handleQrCodePaymentMethod(setStateDialog),
    

    And then, instead of setState, I called this parameter setStateDialog

    if (response['response'] == 'OK') {
            setStateDialog(() {
              paymentQrCode = response['qrCode'];
            });
          }
    

    And now, my QR code displays after I click on generate :)


  2. Use flutter_svg: ^2.0.10+1. It provides an option to fetch SVG images from the internet via a URL and display a placeholder until the image loads.

    Use below code to show network svg using flutter_svg package

    SvgPicture.network(
      'https://site-that-takes-a-while.com/image.svg',
      semanticsLabel: 'A shark?!',
      placeholderBuilder: (BuildContext context) => Container(
          padding: const EdgeInsets.all(30.0),
          child: const CircularProgressIndicator()),
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search