Search code examples
flutterdartflutter-layoutflutter-riverpod

Why suffixIcon does not work with river_pod?


I'm preparing password-field with TextFormFieldand riverpod on flutter as followings. When the suffixIcon is tapped, the icon would change from solidEye to solidEyeSlash, accorging to the bool result of mask. Actually, the bool result is toggled correctly as checked at //here, however those icons never change as expected.

How should I fix my code below to let it works?

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

final mask = StateProvider<bool>((ref) => false);

class TextFieldPassword extends ConsumerWidget {

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Container(
        margin: const EdgeInsets.only(bottom: 10),
        child: TextFormField(
          style: const TextStyle(
            fontSize: 13,
          ),
          obscureText: true,
          decoration: InputDecoration(
            labelText: "password",//** 
            suffixIcon: IconButton(//** 
            icon: Icon(
              ref.read(mask.notifier).state // false
                ? FontAwesomeIcons.solidEye
                : FontAwesomeIcons.solidEyeSlash
                ),
            onPressed: () {
            ref.read(mask.notifier).update((state)=>!ref.read(mask.notifier).state);
            print(ref.read(mask.notifier).state);//here
            },
          ),
            labelStyle: const TextStyle(
              fontSize: 15,
              color: Color.fromARGB(255, 219, 219, 219),
            ),
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(2),
              borderSide: const BorderSide(
                color: Color.fromARGB(255, 219, 219, 219), 
                width: 1.0,
              ),
            ),
            focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(2),
                borderSide: const BorderSide(
                  color: Color.fromARGB(255, 219, 219, 219), 
                  width: 1.0, 
                )),
          ),
        ));
  }
}

Solution

  • You like to change the icondata, therefore you need to watch the state instead of read. Icon(ref.watch(mask)

    icon: Icon(ref.watch(mask)  
        ? FontAwesomeIcons.solidEye
        : FontAwesomeIcons.solidEyeSlash),
    

    And to update data onPressed

    onPressed: () {
      final bool isVisible = ref.read(mask);
      ref.read(mask.notifier).update((state) => !isVisible);
    },
    
    class TextFieldPassword extends ConsumerWidget {
      const TextFieldPassword({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        return Container(
            margin: const EdgeInsets.only(bottom: 10),
            child: TextFormField(
              style: const TextStyle(
                fontSize: 13,
              ),
              obscureText: !ref.watch(mask),
              decoration: InputDecoration(
                labelText: "password", //**
                suffixIcon: IconButton(
                  icon: Icon(ref.watch(mask) // false
                      ? FontAwesomeIcons.solidEye
                      : FontAwesomeIcons.solidEyeSlash),
                  onPressed: () {
                    final bool isVisible = ref.read(mask);
                    ref.read(mask.notifier).update((state) => !isVisible);
                  },
                ),
                labelStyle: const TextStyle(
                  fontSize: 15,
                  color: Color.fromARGB(255, 219, 219, 219),
                ),
                enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(2),
                  borderSide: const BorderSide(
                    color: Color.fromARGB(255, 219, 219, 219),
                    width: 1.0,
                  ),
                ),
                focusedBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(2),
                    borderSide: const BorderSide(
                      color: Color.fromARGB(255, 219, 219, 219),
                      width: 1.0,
                    )),
              ),
            ));
      }
    }