Composing region changed by the framework. Restarting the input method in Flutter - flutter

First time I'm able to send the message and get the response but second time it's not giving me the response as showing error as Composing region changed by the framework. Restarting the input method. Also sometimes not even the single time showing me the response.
It is working on the web perfectly but the issue on the we is it is giving me response once in the first time, twice in second time, thrice in third time.
import 'chatmessage.dart';
import 'threedots.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({super.key});
#override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _controller = TextEditingController();
final List<ChatMessage> _messages = [];
Chat? chat;
bool _isImageSearch = false;
StreamSubscription? _subscription;
bool _isTyping = false;
#override
void initState() {
super.initState();
chat = Chat.instance.builder(
"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",
);
}
#override
void dispose() {
chat!.genImgClose();
_subscription?.cancel();
super.dispose();
}
void _sendMessage() {
if (_controller.text.isEmpty) return;
ChatMessage message = ChatMessage(
text: _controller.text,
sender: "Me",
isImage: false,
);
setState(() {
_messages.insert(0, message);
_isTyping = true;
});
_controller.clear();
if (_isImageSearch) {
final request = GenerateImage(message.text, 1, size: "256x256");
_subscription = chat!
.generateImageStream(request)
.asBroadcastStream()
.listen((response) {
Vx.log(response.data!.last!.url!);
insertNewData(response.data!.last!.url!, isImage: true);
});
} else {
final request = CompleteReq(
prompt: message.text, model: kTranslateModelV3, max_tokens: 200);
_subscription = chat!
.onCompleteStream(request: request)
.asBroadcastStream()
.listen((response) {
Vx.log(response!.choices[0].text);
insertNewData(response.choices[0].text, isImage: false);
});
}
}
void insertNewData(String response, {bool isImage = false}) {
ChatMessage botMessage = ChatMessage(
text: response,
sender: "AI Bot",
isImage: isImage,
);
setState(() {
_isTyping = false;
_messages.insert(0, botMessage);
});
}
Widget _buildTextComposer() {
return Row(
children: [
Expanded(
child: TextField(
controller: _controller,
onSubmitted: (value) => _sendMessage(),
decoration: const InputDecoration.collapsed(
hintText: "Question/Description"),
),
),
ButtonBar(
children: [
IconButton(
icon: const Icon(Icons.send),
onPressed: () {
_isImageSearch = false;
_sendMessage();
},
),
// TextButton(
// onPressed: () {
// _isImageSearch = true;
// _sendMessage();
// },
// child: const Text("Generate Image"))
],
),
],
).px16();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(
"Welcome To AI Bot",
textAlign: TextAlign.center,
),
backgroundColor: Color.fromARGB(202, 245, 235, 104),
),
body: SafeArea(
child: Column(
children: [
Flexible(
child: ListView.builder(
reverse: true,
padding: Vx.m8,
itemCount: _messages.length,
itemBuilder: (context, index) {
return _messages[index];
},
)),
if (_isTyping) const ThreeDots(),
const Divider(
height: 1.0,
),
Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.lightGreen,
),
child: _buildTextComposer(),
)
],
),
));
}
}

Related

Access data from custom widget created on different class in flutter

I new to Flutter and i was trying to find a solution for the below issue for several hours. I have searched and every solution provided does not work form me.
I have page where one of the widgets is the autocomplete text input. I have created this autocomplete widget on different class. I have added this widget as StatefulBuilder within my main widget. it is working fine however, i am not able to access its value so I can store it with other fields.
My code look like
class ItemDetails extends StatefulWidget {
const ItemDetails({Key? key}) : super(key: key);
static const routeName = '/item_details';
#override
State<ItemDetails> createState() => _ItemDetails();
}
class _ItemDetails extends State<ItemDetails> {
late TextEditingController labelController;
late TextEditingController valueController;
late TextEditingController notesController;
bool _submitted = false;
late var args;
String _itemLabel2 = "";
// var labelAutoComp = LabelSugg();
#override
void initState() {
super.initState();
labelController = TextEditingController();
valueController = TextEditingController();
notesController = TextEditingController();
}
#override
void dispose() {
labelController.dispose();
valueController.dispose();
notesController.dispose();
// Hive.close();
super.dispose();
}
String? _labelErrorText(context) {
final text = labelController.value.text;
if (text.isEmpty) {
// return 'Can\'t be empty';
return AppLocalizations.of(context)!.noEmpty;
}
}
String? _valueErrorText(context) {
final text = valueController.value.text;
if (text.isEmpty) {
// return 'Can\'t be empty';
return AppLocalizations.of(context)!.noEmpty;
}
}
#override
Widget build(BuildContext context) {
try {
args = ModalRoute.of(context)!.settings.arguments as Map;
} on Exception catch (e) {
// print(e);
}
// print(args);
return Scaffold(
appBar: AppBar(
title: Text(args['title']),
),
body: Container(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20),
child: Column(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
LabelSugg(getLabelText: (String val) {
print(val);
_itemLabel2 = val;
}),
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.label,
hintText: AppLocalizations.of(context)!.labelHint,
errorText:
_submitted ? _labelErrorText(context) : null,
),
controller: labelController,
onChanged: (_) => setState(() {}),
),
const SizedBox(height: 5),
TextField(
autofocus: false,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.value,
hintText: AppLocalizations.of(context)!.valueHint,
errorText:
_submitted ? _valueErrorText(context) : null,
),
controller: valueController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true, signed: false),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r"[0-9.]")),
TextInputFormatter.withFunction(
(oldValue, newValue) {
try {
final text = newValue.text;
if (text.isNotEmpty) double.parse(text);
return newValue;
} catch (e) {}
return oldValue;
}),
], // Only numbers can be entered
onChanged: (_) => setState(() {}),
),
const SizedBox(height: 5),
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!.notes,
hintText: AppLocalizations.of(context)!.noteHint,
),
controller: notesController,
onChanged: (_) => setState(() {}),
),
]),
// ],
),
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () {
setState(() => _submitted = true);
if (_labelErrorText(context) == null &&
_valueErrorText(context) == null) {
//insert
var localLabel = labelController.value.text;
var _localValue = 0.0;
if (valueController.value.text != '') {
_localValue =
double.parse(valueController.value.text);
} else {
_localValue = 0.0;
}
var localNotes = notesController.value.text;
addItemToList(
localLabel, _localValue, localNotes);
Navigator.of(context).pop();
labelController.clear();
valueController.clear();
notesController.clear();
}
},
label: Text(AppLocalizations.of(context)!.add),
icon: const Icon(Icons.save, size: 18),
),
const SizedBox(width: 10),
ElevatedButton.icon(
onPressed: () => {Navigator.pop(context)},
label: Text(AppLocalizations.of(context)!.cancel),
icon: const Icon(Icons.cancel, size: 18),
),
],
)),
),
// )
],
)));
}
void addItemToList(String localLabel, double localValue, String localNotes) {
var _item = YearItems()..yearID = args['year'];
_item.itemLabel = localLabel;
_item.itemValue = localValue;
_item.itemNote = localNotes;
print(_itemLabel2);
final itemsBox = ItemsBoxes.getTransactions();
itemsBox.add(_item);
}
}
my labelAutoComp widget code look like
class LabelSugg extends StatefulWidget {
final ValueChanged<String> getLabelText;
const LabelSugg({Key? key, required this.getLabelText}) : super(key: key);
#override
State<LabelSugg> createState() => _LabelSugg();
}
class _LabelSugg extends State<LabelSugg> {
late TextEditingController fieldTextEditingController2;
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
getLabel() {
return widget.getLabelText(fieldTextEditingController2.text);
}
#override
Widget build(BuildContext context) {
List<LabelsAc> labelOptions = <LabelsAc>[
LabelsAc(label: AppLocalizations.of(context)!.labelClothes),
LabelsAc(label: AppLocalizations.of(context)!.labelFood),
LabelsAc(label: AppLocalizations.of(context)!.labelPerfumes),
LabelsAc(label: AppLocalizations.of(context)!.labelCapital),
];
return Autocomplete<LabelsAc>(
optionsBuilder: (TextEditingValue textEditingValue) {
return labelOptions
.where((LabelsAc _label) => _label.label
.toLowerCase()
.startsWith(textEditingValue.text.toLowerCase()))
.toList();
},
displayStringForOption: (LabelsAc option) => option.label,
fieldViewBuilder: (BuildContext context,
TextEditingController fieldTextEditingController,
// fieldTextEditingController,
FocusNode fieldFocusNode,
VoidCallback onFieldSubmitted) {
return TextField(
controller: fieldTextEditingController,
focusNode: fieldFocusNode,
style: const TextStyle(fontWeight: FontWeight.bold),
// onChanged: getLabel(),
onChanged: (String val) {
fieldTextEditingController2 = fieldTextEditingController;
getLabel();
});
},
onSelected: (LabelsAc selection) {
fieldTextEditingController2 =
TextEditingController(text: selection.label);
getLabel();
},
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<LabelsAc> onSelected,
Iterable<LabelsAc> options) {
return Align(
alignment: Alignment.topLeft,
child: Material(
child: Container(
// width: 350,
// color: Colors.cyan,
child: ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final LabelsAc option = options.elementAt(index);
return GestureDetector(
onTap: () {
onSelected(option);
},
child: ListTile(
title: Text(option.label,
style: const TextStyle(color: Colors.black)),
),
);
},
),
),
),
);
},
);
// ),
// );
}
}
class LabelsAc {
LabelsAc({required this.label});
String label;
}
first is redundant when you wrap your class that extend StatefullWidget with StatefullBuilder. LabelSugg is a component Widget. you can use it like other widget.
benefit to separate widget with StatefullWidget class is, we can update the value inside the class without re-build the current page. which is good for performance. that's why developer recomend to separete with class insted compared to make local method.
as you see, when you create LabelSugg extend StatefullWidget class , we will have _LabelSugg . underscore means that: all variable only accessible on current file.
thats why we can't call getLabel() or other variable from different file.
its used for handle the State in 'LabelSugg` widget.
now how to pass the value from LabelSugg is by created variable outside the state. here you are:
class LabelSugg extends StatefulWidget {
// use this to pass any changes when we use LabelSugg
final ValueChanged<String> getLabelText;
const LabelSugg({Key? key, required this.getLabelText}) : super(key: key);
#override
State<LabelSugg> createState() => _LabelSugg();
}
then we can call the onChaged inside _LabelSugg state. because its Statefull widget, we can acces by : widget.getLabelText()
class _LabelSugg extends State<LabelSugg> {
late TextEditingController fieldTextEditingController;
.....
getLabel() {
return widget.getLabelText(fieldTextEditingController.text);
}
then in other class we call LabelSugg like common widget
import 'package:../labelsug.dart';
class ItemDetails extends StatefulWidget {
.....
return Scaffold(
appBar: AppBar(
title: Text(args['title']),
),
body: Container(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
// now use it like a widget
LabelSug(
getLabelText: (String val){
print(val);
}
:)

Flutter Barcode Scan Result Is'nt Listed

My application is to search through the list of books. Two different variables (book name or barcode) can be used while searching. There is no problem when searching by name. but when searching with barcode scanning, no results are listed. When I type the barcode manually, the application still works without any problems.
Can u help me?
Manually entered barcode: https://i.stack.imgur.com/njtLA.png
Barcode scan result : https://i.stack.imgur.com/ZsGot.png
My code here..
import 'package:fff/book_tile.dart';
import 'package:flutter/material.dart';
import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:fff/book_model.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController _controller = new TextEditingController();
List<Book> _booksForDisplay = [];
List<Book> _books = [];
#override
void initState() {
super.initState();
fetchBooks().then((value) {
setState(() {
_books.addAll(value);
_booksForDisplay = _books;
print(_booksForDisplay.length);
});
});
}
Future _scan(BuildContext context) async {
String barcode = await FlutterBarcodeScanner.scanBarcode(
'#ff0000',
'İptal',
true,
ScanMode.BARCODE
);
_controller.text = barcode;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 80,
title: Padding(
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40)
),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 12),
child: TextFormField(
textAlignVertical: TextAlignVertical.center,
controller: _controller,
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(Icons.search),
suffixIcon: IconButton(
icon: Icon(FontAwesomeIcons.barcode),
onPressed: (){
_scan(context);
},
)
),
onChanged: (string){
string = string.toLowerCase();
setState(() {
_booksForDisplay = _books.where((b){
var bName = b.name!.toLowerCase();
var bBarcode = b.barcode!.toLowerCase();
return bName.startsWith(string) || bBarcode.startsWith(string);
}).toList();
});
},
),
),
),
),
),
body: SafeArea(
child: Container(
child: _controller.text.isNotEmpty ? new ListView.builder(
itemCount: _booksForDisplay.length,
itemBuilder: (context, index){
return BookTile(book: this._booksForDisplay[index]);
},
)
:
Center(
child: Text('Searching..'),
)
),
)
);
}
}
I think you only need a listener for your TextEditingController. And you should write your onChanged method inside that listener.
#override
void initState() {
super.initState();
fetchBooks().then((value) {
setState(() {
_books.addAll(value);
_booksForDisplay = _books;
print(_booksForDisplay.length);
});
});
_controller.addListener(() {
print(_controller.text);
var string = _controller.text.toLowerCase();
setState(() {
_booksForDisplay = _books.where((b){
var bName = b.name!.toLowerCase();
var bBarcode = b.barcode!.toLowerCase();
return bName.startsWith(string) ||
bBarcode.startsWith(string);
}).toList();
});
});
}

Obtain coordinates from an address flutter

Could someone guide me to get the coordinates of an address in flutter?
I need to enter addresses in a text box and get the longitude and latitude of that address
You can copy paste run full code below
You can use package https://pub.dev/packages/geocoder
code snippet
import 'package:geocoder/geocoder.dart';
// From a query
final query = "1600 Amphiteatre Parkway, Mountain View";
var addresses = await Geocoder.local.findAddressesFromQuery(query);
var first = addresses.first;
print("${first.featureName} : ${first.coordinates}");
working demo, last line is coordinates
full code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geocoder/geocoder.dart';
import 'package:geocoder/services/base.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class AppState extends InheritedWidget {
const AppState({
Key key,
this.mode,
Widget child,
}) : assert(mode != null),
assert(child != null),
super(key: key, child: child);
final Geocoding mode;
static AppState of(BuildContext context) {
return context.inheritFromWidgetOfExactType(AppState);
}
#override
bool updateShouldNotify(AppState old) => mode != old.mode;
}
class GeocodeView extends StatefulWidget {
GeocodeView();
#override
_GeocodeViewState createState() => new _GeocodeViewState();
}
class _GeocodeViewState extends State<GeocodeView> {
_GeocodeViewState();
final TextEditingController _controller = new TextEditingController();
List<Address> results = [];
bool isLoading = false;
Future search() async {
this.setState(() {
this.isLoading = true;
});
try {
var geocoding = AppState.of(context).mode;
var results = await geocoding.findAddressesFromQuery(_controller.text);
this.setState(() {
this.results = results;
});
} catch (e) {
print("Error occured: $e");
} finally {
this.setState(() {
this.isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return new Column(children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Row(
children: <Widget>[
new Expanded(
child: new TextField(
controller: _controller,
decoration: new InputDecoration(hintText: "Enter an address"),
),
),
new IconButton(
icon: new Icon(Icons.search), onPressed: () => search())
],
),
),
),
new Expanded(child: new AddressListView(this.isLoading, this.results)),
]);
}
}
class ReverseGeocodeView extends StatefulWidget {
ReverseGeocodeView();
#override
_ReverseGeocodeViewState createState() => new _ReverseGeocodeViewState();
}
class _ReverseGeocodeViewState extends State<ReverseGeocodeView> {
final TextEditingController _controllerLongitude =
new TextEditingController();
final TextEditingController _controllerLatitude = new TextEditingController();
_ReverseGeocodeViewState();
List<Address> results = [];
bool isLoading = false;
Future search() async {
this.setState(() {
this.isLoading = true;
});
try {
var geocoding = AppState.of(context).mode;
var longitude = double.parse(_controllerLongitude.text);
var latitude = double.parse(_controllerLatitude.text);
var results = await geocoding
.findAddressesFromCoordinates(new Coordinates(latitude, longitude));
this.setState(() {
this.results = results;
});
} catch (e) {
print("Error occured: $e");
} finally {
this.setState(() {
this.isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return new Column(children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Row(
children: <Widget>[
new Expanded(
child: new Column(
children: <Widget>[
new TextField(
controller: _controllerLatitude,
decoration: new InputDecoration(hintText: "Latitude"),
),
new TextField(
controller: _controllerLongitude,
decoration: new InputDecoration(hintText: "Longitude"),
),
],
),
),
new IconButton(
icon: new Icon(Icons.search), onPressed: () => search())
],
),
),
),
new Expanded(child: new AddressListView(this.isLoading, this.results)),
]);
}
}
class _MyAppState extends State<MyApp> {
Geocoding geocoding = Geocoder.local;
final Map<String, Geocoding> modes = {
"Local": Geocoder.local,
"Google (distant)": Geocoder.google("<API-KEY>"),
};
void _changeMode(Geocoding mode) {
this.setState(() {
geocoding = mode;
});
}
#override
Widget build(BuildContext context) {
return new AppState(
mode: this.geocoding,
child: new MaterialApp(
home: new DefaultTabController(
length: 2,
child: new Scaffold(
appBar: new AppBar(
title: new Text('Geocoder'),
actions: <Widget>[
new PopupMenuButton<Geocoding>(
// overflow menu
onSelected: _changeMode,
itemBuilder: (BuildContext context) {
return modes.keys.map((String mode) {
return new CheckedPopupMenuItem<Geocoding>(
checked: modes[mode] == this.geocoding,
value: modes[mode],
child: new Text(mode),
);
}).toList();
},
),
],
bottom: new TabBar(
tabs: [
new Tab(
text: "Query",
icon: new Icon(Icons.search),
),
new Tab(
text: "Coordinates",
icon: new Icon(Icons.pin_drop),
),
],
),
),
body: new TabBarView(children: <Widget>[
new GeocodeView(),
new ReverseGeocodeView(),
]),
),
),
),
);
}
}
class AddressTile extends StatelessWidget {
final Address address;
AddressTile(this.address);
final titleStyle =
const TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold);
#override
Widget build(BuildContext context) {
return new Padding(
padding: const EdgeInsets.all(10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new ErrorLabel(
"feature name",
this.address.featureName,
fontSize: 15.0,
isBold: true,
),
new ErrorLabel("address lines", this.address.addressLine),
new ErrorLabel("country name", this.address.countryName),
new ErrorLabel("locality", this.address.locality),
new ErrorLabel("sub-locality", this.address.subLocality),
new ErrorLabel("admin-area", this.address.adminArea),
new ErrorLabel("sub-admin-area", this.address.subAdminArea),
new ErrorLabel("thoroughfare", this.address.thoroughfare),
new ErrorLabel("sub-thoroughfare", this.address.subThoroughfare),
new ErrorLabel("postal code", this.address.postalCode),
this.address.coordinates != null
? new ErrorLabel("", this.address.coordinates.toString())
: new ErrorLabel("coordinates", null),
]),
);
}
}
class AddressListView extends StatelessWidget {
final List<Address> addresses;
final bool isLoading;
AddressListView(this.isLoading, this.addresses);
#override
Widget build(BuildContext context) {
if (this.isLoading) {
return new Center(child: new CircularProgressIndicator());
}
return new ListView.builder(
itemCount: this.addresses.length,
itemBuilder: (c, i) => new AddressTile(this.addresses[i]),
);
}
}
class ErrorLabel extends StatelessWidget {
final String name, text;
final TextStyle descriptionStyle;
ErrorLabel(this.name, String text,
{double fontSize = 9.0, bool isBold = false})
: this.text = text ?? "Unknown $name",
this.descriptionStyle = new TextStyle(
fontSize: fontSize,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
color: text == null ? Colors.red : Colors.black);
#override
Widget build(BuildContext context) {
return new Text(this.text, style: descriptionStyle);
}
}
Here created an Input Text Widget and when user taps on it. This takes to google autocomplete screen, where user inputs the location.
TextFormField(
decoration: new InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(left: 15),
hintText: Strings.enter_your_house_number_street_etc,
hintStyle: TextStyle(
fontSize: 14,
color: AppColor.grey,
fontFamily: "Open Sans",
fontWeight: FontWeight.normal
)),
maxLines: 1,
controller: _address,
onTap: ()async{
// then get the Prediction selected
Prediction p = await PlacesAutocomplete.show(
context: context, apiKey: kGoogleApiKey,
onError: onError);
displayPrediction(p);
},
)
Here it is getting the lat and long of entered location.
Future<Null> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail = await _places.getDetailsByPlaceId(p.placeId);
var placeId = p.placeId;
lat = detail.result.geometry.location.lat;
long = detail.result.geometry.location.lng;
var address =detail.result.formattedAddress;
print(lat);
print(long);
print(address);
setState(() {
_address.text = address;
});
}
}
import 'package:flutter_google_places/flutter_google_places.dart';
We can use the Geo Coder plugin which will use to get lat and lng from a given address.
import 'package:geocoding/geocoding.dart';
List<Location> locations = await locationFromAddress("Gronausestraat 710, Enschede");

Flutter dont reload a image when i take a picture

i'm studying flutter and im trying to create a person register. In this page i hava a normal register with basic data and person photo.
But im having some issue with update a Image, when i take the picture the component Image dont change to taked image;
I tried find some controller to Image or Image Provider but unsuccessful.
This is my code:
class _RegisterForm extends State<RegisterForm> {
final TextEditingController _textEditingControllerPassword =
new TextEditingController();
final TextEditingController _textEditingControllerComparePassword =
new TextEditingController();
final TextEditingController _textEditingControllerEmail =
new TextEditingController();
final TextEditingController _textEditingControllerFullName =
new TextEditingController();
final _formKey = GlobalKey<FormState>();
User _user = null;
Image _image = null;
#override
void setState(VoidCallback fn) {
super.initState();
this._user = new User(
_textEditingControllerPassword.text,
_textEditingControllerFullName.text,
_textEditingControllerEmail.text,
_textEditingControllerComparePassword.text,
_image,
);
this.build(context);
}
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.fromLTRB(23, 0, 23, 0),
child: Column(children: <Widget>[
GestureDetector(
child: CircleAvatarImage(_image),
onTap: getImage,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Tire sua foto!"),
),
InputString(
"Como gostaria ",
hint: "Marianx Silva",
maxLenght: 100,
controller: this._textEditingControllerFullName,
onChanged: (context) => {
setState(() {
_user = null;
}),
},
),
InputString(
"E-mail",
maxLenght: 100,
controller: this._textEditingControllerEmail,
onChanged: (context) => {
setState(() {
_user = null;
}),
},
),
InputString(
"Senha",
controller: this._textEditingControllerPassword,
maxLenght: 12,
obscureText: true,
onChanged: (context) => {
setState(() {
_user = null;
}),
},
),
InputString(
"Confime a senha",
controller: this._textEditingControllerComparePassword,
maxLenght: 12,
obscureText: true,
onChanged: (context) => {
setState(() {
_user = null;
}),
},
),
RegisterUserInFirebaseButton(
"Continuar",
_formKey,
_user,
// edgeInsets: EdgeInsets.fromLTRB(0, 40, 0, 0),
),
]),
));
}
Future getImage() async {
File image = await ImagePicker.pickImage(source: ImageSource.camera);
this._image = Image.file(image);
setState(() {
_user = null;
});
}
}
This is my "CircleAvatarImage" component:
import 'package:flutter/material.dart';
const AssetImage _defaultImage = AssetImage("assets/images/default_image.png");
class CircleAvatarImage extends StatefulWidget {
Image image;
CircleAvatarImage(this.image);
#override
State<StatefulWidget> createState() {
return __CircleAvatarImageState();
}
}
class __CircleAvatarImageState extends State<CircleAvatarImage> {
AnimationController _controller;
#override
Widget build(BuildContext context) {
return CircleAvatar(
radius: 62,
backgroundColor: Colors.blue,
child: CircleAvatar(
radius: 60.0,
child: Padding(
padding: const EdgeInsets.only(top: 90),
child: Icon(
Icons.camera_enhance,
color: Colors.white,
),
),
backgroundImage:
widget.image == null ? _defaultImage : widget.image.image,
),
);
}
}
You didn't use setState. So, there's no way Widget would no that it has to udpate. Try :
setState() => this._image = Image.file(image);

how to refresh state on Navigator.Pop or Push in flutter

Here I have two pages first is called BSP_signup_terms page and the second is Bsp_Service_page. when I am on BSP_signup_terms on that page I have to select some checkbox based on the selected checkbox it will show me some data. but problem is that it will show me the complete data but when I get back to the BSP_signup_terms from Bsp_signup_page and I am changing the checkbox and then again when I am pressing next button it will not change the result it same as the previous result.
Here is the Image of Output Page
In this image I've attached both screen output when I am selecting only one checkbox it will render some value in service page and when I am back to the Terms and Condition page and select one more checkbox then it will not updating service page
Here is the code I've tried.
BSP_Signup_Terms_Page
class BspLicensedSignupTermsPage extends StatefulWidget {
static const String routeName = "/bspLicensedSignupTerms";
final BspSignupCommonModel bspSignupCommonModel;
BspLicensedSignupTermsPage({
Key key,
#required this.bspSignupCommonModel,
}) : super(key: key);
#override
_BspLicensedSignupTermsPageState createState() =>
_BspLicensedSignupTermsPageState();
}
class _BspLicensedSignupTermsPageState
extends State<BspLicensedSignupTermsPage> {
#override
void initState() {
super.initState();
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool _isWalkIn = false;
bool _isHome = false;
bool _isOnDemand = false;
Widget _buildselectcheckbox() {
return Text(
AppConstantsValue.appConst['bsplicensedsignupterms']['selectcheck']
['translation'],
);
}
// Walkin
_onCustomerWalkin(value) {
setState(() {
_isWalkIn = value;
});
}
Widget _buildCustomerWalkIn() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['bsplicensedsignupterms']
['CustomerWalkIn']['translation'],
onChanged: (value) {
print(value);
_onCustomerWalkin(value);
},
validate: false,
);
}
// Home
_onCustomerInHome(value) {
setState(() {
_isHome = value;
});
}
Widget _buildCustomerInHome() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['bsplicensedsignupterms']
['CustomerInHome']['translation'],
onChanged: (value) {
_onCustomerInHome(value);
},
validate: false,
);
}
Widget _buildCustomerInHomeHelp() {
return Text(
AppConstantsValue.appConst['bsplicensedsignupterms']['businesscheckhelp']
['translation'],
);
}
// On Demand
_onCustomerOnDemand(value) {
setState(() {
_isOnDemand = value;
});
}
Widget _buildBusinessOnDemand() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['bsplicensedsignupterms']
['BusinessOnDemand']['translation'],
onChanged: (value) {
_onCustomerOnDemand(value);
},
validate: false,
);
}
Widget _buildBusinessOnDemandHelp() {
return Text(AppConstantsValue.appConst['bsplicensedsignupterms']
['businessprovidehelp']['translation']);
}
#override
Widget build(BuildContext context) {
final appBar = AppBar(
title: Text("Bsp Licensed Signup Terms and Condition"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
centerTitle: true,
);
final bottomNavigationBar = Container(
height: 56,
//margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
_formKey.currentState.reset();
},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
textColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
if (_formKey.currentState.validate()) {
if (_isHome == false &&
_isOnDemand == false &&
_isWalkIn == false) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => ShowErrorDialog(
title: Text('Select Service'),
content: Text(
'Please select atleast one service type to proceed next',
),
));
} else {
BspSignupCommonModel model = widget.bspSignupCommonModel;
model.isWalkin = _isWalkIn;
model.isHome = _isHome;
model.isOnDemand = _isOnDemand;
print(model.toJson());
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
BspServicePage(bspSignupCommonModel: model),
),
);
}
}
},
),
],
),
);
return new Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
body: Container(
height: double.infinity,
width: double.infinity,
child: Stack(
children: <Widget>[
SingleChildScrollView(
child: SafeArea(
child: Form(
autovalidate: true,
key: _formKey,
child: Scrollbar(
child: SingleChildScrollView(
dragStartBehavior: DragStartBehavior.down,
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: new Container(
decoration: BoxDecoration(
borderRadius: new BorderRadius.circular(25)),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_buildselectcheckbox(),
_buildCustomerWalkIn(),
_buildCustomerInHome(),
_buildCustomerInHomeHelp(),
_buildBusinessOnDemand(),
_buildBusinessOnDemandHelp(),
],
),
),
),
),
),
),
),
],
),
),
);
}
}
BSP_Service_Page
class BspServicePage extends StatefulWidget {
static const String routeName = "/bspService";
final BspSignupCommonModel bspSignupCommonModel;
BspServicePage({
Key key,
#required this.bspSignupCommonModel,
}) : super(key: key);
#override
_BspServicePageState createState() => _BspServicePageState();
}
class _BspServicePageState extends State<BspServicePage> {
List<int> servicesIds = [];
Map<String, bool> selection = {};
List<BspServices.Service> selectedServices = [];
SearchBarController _controller = new SearchBarController();
String _searchText = '';
bool refreshservices = true;
#override
void initState() {
super.initState();
}
void _showErrorDialog(String message) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => ShowErrorDialog(
title: Text('An Error Occurred!'),
content: Text(message),
),
);
}
void refresh() {
setState(() {
refreshservices = !refreshservices;
});
}
#override
Widget build(BuildContext context) {
var _bspServiceBloc = new BspServiceBloc();
final appBar = SearchBar(
controller: _controller,
onQueryChanged: (String query) {
print('Search Query $query');
setState(() {
_searchText = query;
});
},
defaultBar: AppBar(
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
refresh();
NavigationHelper.navigatetoBack(context);
}),
title: Text('Select Services'),
),
);
final bottomNavigationBar = Container(
height: 56,
// margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
print('reseting the state');
setState(() {
selection = {};
servicesIds = [];
});
},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
textColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
BspSignupCommonModel model = widget.bspSignupCommonModel;
model.servicesIds = servicesIds;
model.services = selectedServices;
print('servicesIds at the next button');
print(servicesIds);
print(model.toJson());
if (servicesIds.length == 0) {
_showErrorDialog(
'You need to select at least one service to proceed next!');
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BusinessProfilePage(
bspSignupCommonModel: model,
),
),
);
}
},
),
],
),
);
return new Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
body: new BspServiceScreen(
bspServiceBloc: _bspServiceBloc,
bspSignupCommonModel: widget.bspSignupCommonModel,
servicesIds: servicesIds,
selection: selection,
searchQuery: _searchText,
selectedServices: selectedServices,
refresh: refresh,
),
);
}
}
Bsp_service_screen
class BspServiceScreen extends StatefulWidget {
final BspServiceBloc _bspServiceBloc;
final String searchQuery;
final List<int> servicesIds;
final Map<String, bool> selection;
final BspSignupCommonModel bspSignupCommonModel;
final List<BspServices.Service> selectedServices;
final Function refresh;
const BspServiceScreen({
Key key,
#required BspServiceBloc bspServiceBloc,
#required this.bspSignupCommonModel,
#required this.servicesIds,
#required this.selection,
#required this.selectedServices,
#required this.refresh,
this.searchQuery,
}) : _bspServiceBloc = bspServiceBloc,
super(key: key);
#override
BspServiceScreenState createState() {
return new BspServiceScreenState(_bspServiceBloc);
}
}
class BspServiceScreenState extends State<BspServiceScreen> {
final BspServiceBloc _bspServiceBloc;
BspServiceScreenState(this._bspServiceBloc);
// Map<String, bool> _selection = {};
#override
void initState() {
super.initState();
bool isHome = widget.bspSignupCommonModel.isHome;
bool isWalkIn = widget.bspSignupCommonModel.isWalkin;
bool isOnDemand = widget.bspSignupCommonModel.isOnDemand;
this._bspServiceBloc.dispatch(LoadBspServiceEvent(
countryId: 1,
isHome: isHome,
isOnDemand: isOnDemand,
isWalkin: isWalkIn,
));
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return BlocBuilder<BspServiceBloc, BspServiceState>(
bloc: widget._bspServiceBloc,
builder: (
BuildContext context,
BspServiceState currentState,
) {
if (currentState is UnBspServiceState) {
return Center(child: CircularProgressIndicator());
}
if (currentState is ErrorBspServiceState) {
return new Container(
child: new Center(
child: new Text(currentState.errorMessage ?? 'Error'),
),
);
}
if (currentState is InBspServiceState) {
// print(
// 'in bsp service state, ${currentState.bspServices.servicesByCountry.length}');
if (currentState.bspServices.servicesByCountry.length == 0) {
return Container(
child: Center(
child: Text("No Services available for this combination"),
),
);
} else {
return new Container(
child:
_renderServices(currentState.bspServices.servicesByCountry),
);
}
}
return Container();
},
);
}
List<ServicesByCountry> finalList = new List();
ListView _renderServices(List<ServicesByCountry> lovCountryServices) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (widget.searchQuery != '') {
finalList.clear();
lovCountryServices.forEach((ServicesByCountry data) {
if (data.name
.toLowerCase()
.contains(widget.searchQuery.toLowerCase())) {
setState(() {
finalList.add(data);
});
} else {
data.services.forEach((ServiceList.Service services) {
if (services.name
.toLowerCase()
.contains(widget.searchQuery.toLowerCase())) {
setState(() {
finalList.add(data);
});
}
});
}
});
} else {
setState(() {
finalList.clear();
finalList.addAll(lovCountryServices);
});
}
});
return ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(8.0),
itemCount: finalList.length,
itemBuilder: (BuildContext context, int index) {
ServicesByCountry item = finalList[index];
List itemsList = item.services;
return ExpansionTile(
title: Text(item.name),
children: List.generate(itemsList.length, (i) {
widget.selection[itemsList[i].name] =
widget.selection[itemsList[i].name] ?? itemsList[i].isSelected;
return CheckboxListTile(
title: Text(itemsList[i].name),
value: widget.selection[itemsList[i].name],
onChanged: (val) {
setState(() {
widget.selection[itemsList[i].name] = val;
if (val) {
widget.servicesIds.add(itemsList[i].id);
List<BspServices.Service> services =
widget.selectedServices.where((service) {
return service.mainCategory == item.name;
}).toList();
SubCategory subService = new SubCategory(
id: itemsList[i].id,
name: itemsList[i].name,
);
List<SubCategory> subCategories = [];
if (services.length == 0) {
subCategories.add(subService);
widget.selectedServices.add(
new BspServices.Service(
mainCategory: item.name,
mainCategoryId: item.id,
subCategory: subCategories,
),
);
} else {
print('services in else');
print(services[0].subCategory);
subCategories = services[0].subCategory;
subCategories.add(subService);
}
} else {
widget.servicesIds.removeWhere((service) {
return service == itemsList[i].id;
});
List<BspServices.Service> services =
widget.selectedServices.where((service) {
return service.mainCategory == item.name;
}).toList();
services[0].subCategory.removeWhere((subService) {
return subService.id == itemsList[i].id;
});
}
});
print('widget.servicesIds after set state');
print(widget.servicesIds);
},
);
}),
);
},
);
}
}
You can use setState() after return to the first page:
Navigator.push(context, MaterialPageRoute(builder: (context) => Page2())).then((value) {
setState(() {
// refresh state
});
});
Please try below code:-
First you add one method async method:-
void redirectToNextScreen() async {
final Route route = MaterialPageRoute(
builder: (context) => BspServicePage(bspSignupCommonModel: model));
final result = await Navigator.push(mContext, route);
try {
if (result != null) {
if (result) {
//Return callback here.
}
}
} catch (e) {
print(e.toString());
}
}
Then Next you can call this method in "BSP_Signup_Terms_Page" on Next button Pressed event.
Second you can add below line in "BspServicePage" screen Next and Cancel Events.
Navigator.pop(mContext, true); //true means refresh back page and false means not refresh.