How to change the color of an Icon through Boolean Return in Flutter?

Asked

Viewed 1,836 times

0

I have a method that queries books that are favorite in the Firestore database, the book page has a star icon in black color, use isFavorite method to query whether the open book is preferred by the user or not, if it is true it should return and change the color of the icon to yellow but the change does not happen.

The updateFavorite method works perfectly by adding and removing the favorite book from the bank when touching the icon, only the color of it that I can’t configure.

       InkWell(
          child: Icon(
            Icons.star,
            size: 30,
            color: isFavorite == true ? Colors.yellow
            : Colors.black,
          ),
          onTap: (){

            model.updateFavorite(model.getUserId(), document.documentID);
          },
        ),

==============

Future<bool> isFavorite() async{

            firebaseUser = await _auth.currentUser();

            DocumentSnapshot favoritesRef = await Firestore.instance.collection("users")
                .document(firebaseUser.uid).get();

            if(favoritesRef.data["favorites"].contains(document.documentID)){
              print("SIM");
              return true;
            }
            else {
              print("NÃO");
              return false;
            }

          }

==============

      Future<bool> updateFavorite(Future<DocumentReference> uid, String bookId) async{

        firebaseUser = await _auth.currentUser();

        DocumentReference favoritesRef = Firestore.instance.collection("users")
            .document(firebaseUser.uid);

        return Firestore.instance.runTransaction((Transaction tx) async{

          DocumentSnapshot postSnapshot = await tx.get(favoritesRef);
          if(postSnapshot.exists){

            if(!postSnapshot.data["favorites"].contains(bookId)){
              await tx.update(favoritesRef, <String, dynamic>{
                "favorites": FieldValue.arrayUnion([bookId])

              });
              // Delete de bookId from Favorites
            } else {
              await tx.update(favoritesRef, <String, dynamic>{
                "favorites": FieldValue.arrayRemove([bookId])
              });

            }

          }

        }).then((result){
          print(firebaseUser.uid);
          print(bookId);
          return true;

        }).catchError((error){
          print("Error: $error");
          print("DEU RUIM");
          return false;
        });

      }
  • 2

    Hello you ever tried to put inside a setState I’m not seeing state control

  • 1

    As @Jameson said, I didn’t see any state control in the code. Try to do a treatment so that after you get the data of the information you will use on your screen, you can make the call some state control method. "Setstate" is the simplest of them. The moment it is called the Flutter will build the component again, thus drawing the correct color.

1 answer

2


Well, as already commented, apparently you are not controlling the state of your application correctly, so after the execution of your method updateFavorite() you are not warning Flutter that it should render its Icon again.

I noticed that you use 2 Futures, 1 to update the favorite, and another on the icon to actually check whether or not it is a favorite to render the color. In this case you can also use a Futurebuilder, Nice widget that always updates when Future has its result. I created an example for you to get an idea of how it works and adapt it to your use.

main.Dart

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  YourBusiness yourBusiness = new YourBusiness();

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
          body: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  FutureBuilder(
                    future: yourBusiness.isFavorite(''),
                    builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
                      bool isFavorite = false;
                      if(snapshot.hasData) { // Verificar se o Future possui dado
                        isFavorite = snapshot.data;
                      }

                      return Icon(Icons.ac_unit,
                        size: 160.0,
                        color: isFavorite ? Colors.greenAccent: Colors.black,
                      );
                    }
                  ),
                  RaisedButton(
                    child: Text('CHANGE COLOR'),
                    onPressed: () {
                      yourBusiness.updateFavorite('').then((bool) {
                        setState(() {});
                      });
                    },
                  ),
                  RaisedButton(
                    child: Text('SET STATE'),
                    onPressed: () {
                      setState(() {});
                    },
                  )
                ],
              )
            ],
          ),
        )
    );
  }
}

your_business.Dart

class YourBusiness {

  bool _isFavorite = false;

  Future<bool> isFavorite(String yourParams) async {
    await Future.delayed(Duration(seconds: 1));

    // DO YOUR STUFF HERE

    return _isFavorite;
  }

  Future<bool> updateFavorite(String yourParams) async {
    await Future.delayed(Duration(seconds: 1));

    // DO YOUR STUFF HERE

    _isFavorite = true;
    return _isFavorite;
  }

}

Upshot

Resultado

Take into account that every time you update the status of this Widget, the Future of the Icon will run again, which is not a good idea, but you can define other strategies, so it goes from the logic you want to mount in your App.

I advise using some standard for application status control, such as Bloc.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.