Here are some ideas that might help.
Your widget needs to be Stateful. You are trying to keep track of the color that will change over time. Stateless widgets only allow final properties - i.e. you can only initiate their value on creation.
Your variable isGreen and method changeColor() should be part of the state object. Your build() method will also go there.
Next - when you call your method you should call:
void changeColor() {
setState(() {isGreen = !isGreen;});
}
I think in your code you are not flipping the value (=!!iGreen is same as =isGreen). But more importantly - you are not telling the framework that your widget should be rebuilt.
You can test this for your self: click once (after you corrected '!!'). Nothing will happen. If you force refresh in the emulator - you should see that the color did change. This is because you manually refreshed it. setState() does it for you: it will run the code you provided, and then call Flutter to tell it to refresh your widget. See - flutter does not have a magic trigger, and does not observe your code to decide when to refresh your widget. setState() tells it to do so.
As a general rule: your application state - i.e. the data shared with multiple widgets (or pages) should be 'lifted up' the widget tree, and kept in Provider classes.
Stateful widgets should keep only the data directly related to them and only to them. Typically this is the data that helps render the provider data. For example:
-Provider will keep the list of items that you show. Your statefull widget will keep track on currently selected item
-Provider keeps the text to be displayed. Your Stateful widget keeps the font size, font color etc., allowing the user to change it on that specific widget, but not on all the widgets that use the same data.
In your example - you cloud have multiple Login widgets on the screen (for some reason). In that case:
-If you want all of your login widget to change color - keep the isGreen in your provider class. In that case, your widget can be stateless.
-If you want only the widget that you clicked to change the color - this belongs to your stateful widget since no one else cares about this value.
Let me update this with the code that should do what you want. Connecting the widget to the store works the same way for Stateful and Steteless widgets.
Note - I commented out your code connecting to the store, just to show how your widget will change the color. Uncomment the store code, and you should be good to go.
You can run this quickly in https://dartpad.dev/, just copy/paste the code.
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(),
);
}
}
class LoginPage extends StatefulWidget {
final String TAG = "LoginPage";
LoginPage({Key key}) : super(key: key);
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool isGreen = false;
void changeColor() {
setState(() {
isGreen = !isGreen;
});
}
@override
Widget build(BuildContext context) {
/// [StoreConnector] is used to convert store data (using the fromStore)
/// into a ViewModel suitable for the page.
//return StoreConnector<AppState, LoginPageViewModel>(
//builder: (context, viewModel) {
return Scaffold(
body: Column(
children: <Widget>[
Container(),
Text(
'viewModel.some_value_from_the_store',
style: TextStyle(color: isGreen ? Colors.green : Colors.red),
),
ElevatedButton(
onPressed: () => changeColor(),
child: Text('Press to change color'),
)
],
));
//},
//converter: LoginPageViewModel.fromStore);
//}
}
}