Flutter item not updating in widget when delete need to come back to see changes - flutter

I have a simple cart page I am showing products on the cart page. The issue is when I am deleting an item it's deleting but in the widget, it's not deleting I need to go back and come again to show the changes. I try to rise setState also but not working.
My code
class _CartPageState extends State<CartPage> {
num amount = 0;
bool checkLogin = false;
void navigateToAddressPage() {
Get.to(AddressPage());
}
check() async {
final storage = new FlutterSecureStorage();
String imi = await storage.read(key: "imei");
print(imi);
if (imi == "loginhuavaha") {
setState(() {
this._query();
checkLogin = true;
});
}
}
#override
void initState() {
setState(() {
this.check();
});
}
List<Widget> textWidgetList = List<Widget>();
void _query() async {
print('cart');
final dbHelper = DatabaseHelper.instance;
final allRows = await dbHelper.queryAllRows();
allRows.forEach((row) {
amount += double.parse(row['price']);
print(amount);
print(row);
});
for (int i = 0; i < allRows.length; i++) {
textWidgetList.add(Card(
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
margin: EdgeInsets.symmetric(vertical: 8.0),
child: Container(
width: double.infinity,
height: 120.0,
padding: EdgeInsets.all(12.0),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12.0),
child: Image.network(allRows[i]['image'],
width: 100, height: 100)),
SizedBox(width: 12.0),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
allRows[i]['title'],
textAlign: TextAlign.start,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(width: 5.0),
Row(
children: [
GestureDetector(
onTap: () async {
print('delete');
final id = await dbHelper.queryRowCount();
print(id);
final rowsDeleted = await dbHelper.delete(
id, allRows[i]['id']);
print('deleted $rowsDeleted row(s): row $id');
setState(() {
});
},
child: Icon(
FlutterIcons.delete_outline_mco,
),
)
],
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
allRows[i]['price'],
),
),
// Counter(),
],
),
],
),
),
)
],
),
),
));
}
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppBar(context),
body: checkLogin
? Container(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(children: textWidgetList),
],
),
),
)
: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(child: Text('Your are not login')),
SizedBox(height: 10),
SizedBox(
width: 85.0,
height: 50.0,
child: RaisedButton(
color: Theme.of(context).primaryColor,
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Text(
'LOGIN',
style: Theme.of(context).textTheme.button,
).tr(),
onPressed: () {
Get.offAll(SignInPage());
},
),
),
])),
),
);
}
You can see I have added a comment in my code I delete the product and it actually deleted from database but state isn't changing of widget -_-

I think what you need here is the Provider package. Provider makes state management easier a lot. Just define a model class that extends ChangeNotifier and then wrap your widgets with ChangeNotifierProvider<Model_class_name>. To access the fields Use Provider.of(context).var or Provider.of(context).function

First of all you need to put textWidgetList in the setState since you manipulate those Widgets I guess. Secondly you have to put a key to those Widgets due to how Flutter handles elements in a list on the UI.Have a look at this page https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d

Its Simple Man
Once the item is removed
use setState((){})
setState(() {
//Inside setState Clear the allrows list
allrows.clear();
//Then get the allrows again so that the deleted data will not be shown
allRows = await dbHelper.queryAllRows();
});
setState rebuilds your widgets

Related

Customize agora video call UI in flutter

my video call output
when logged another person to this video call then shows like this.But I want when someone logged to video call then my video should be small.
like this.
and also when click my video then my video should be big and another person's video should be small. how to do that ? I couldn't find the any documentation how to do that
Code video call ui
// video view
Widget _viewRows() {
final views = _getRenderViews();
switch (views.length) {
case 1:
return Column(
children: <Widget>[_videoView(views[0])],
);
case 2:
return Column(
children: <Widget>[
_expandedVideoRow([views[0]]),
_expandedVideoRow([views[1]])
],
);
case 3:
return Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 3))
],
);
case 4:
return Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 4))
],
);
default:
}
return Container();
}
How customize the video UI like as I mentioned?
error
To create the layout which you want, edit _viewRow(CallNotifier notifier) and _expandedVideoRow(List views) function with following code : -
Widget _viewRows(CallNotifier notifier) : -
case 2:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Stack(
children: [
_expandedVideoRow([views[secondScreen]]),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 10),
child: GestureDetector(
onTap: () {
tempSwap = firstScreen;
firstScreen = secondScreen;
secondScreen = tempSwap;
setState(() {});
},
child: SizedBox(
height: 200,
width: 100,
child: _expandedVideoRow([views[firstScreen]])),
),
),
),
],
));
Above code contains _expandedVideoRow([views[secondScreen]]), which is just a simple Expandable Container and we are passing the index of the screen as a parameter. In our case, there are 2 screens hence 2 index that is 0 and 1. I have declared three integer variables here, int firstScreen = 0, int secondScreen = 1 and int tempSwap = 0. The second _expandedVideoRow([views[firstScreen]]) is wrapped by GesutreDector, so when the user taps on that screen the indexes of the variable are swapped which results in swapping the screens, SizedBox to reduce its width and height and Align widget to give the desired position to the second screen.
Widget _expandedVideoRow(List views) : -
Widget _expandedVideoRow(List<Widget> views) {
final wrappedViews = views.map<Widget>(_videoView).toList();
return Row(
children: wrappedViews,
);
}
Remove the Expanded widget that wraps the row like the above code because we can't use the Expanded under the Stack widget.
If you wish to change the bottom icons, then change _toolbar(CallNotifier notifier) function according to your need.
Widget _toolbar(CallNotifier notifier) {
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {
_onToggleMute(notifier);
setState(() {
isMute = !isMute;
});
},
child: Icon(
isMute ? Icons.mic_off : Icons.mic,
color: isMute ? Colors.white : Colors.teal,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: isMute ? Colors.teal : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: () => _onCallEnd(context),
child: Icon(
Icons.call_end,
color: Colors.white,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.redAccent,
padding: const EdgeInsets.all(15.0),
),
],
),
);
}
Code which I use in my app, full code : -
class _CallScreenState extends State<CallScreen> {
double globalHeight;
int firstScreen = 0;
int secondScreen = 1;
int tempSwap = 0;
bool isMute = false;
void initState() {
super.initState();
}
List<Widget> _getRenderViews(CallNotifier model) {
final List<StatefulWidget> list = [];
list.add(RtcLocalView.SurfaceView());
model.users
.forEach((int uid) => list.add(RtcRemoteView.SurfaceView(uid: uid)));
return list;
}
Widget _videoView(view) {
return Expanded(child: Container(child: view));
}
Widget _expandedVideoRow(List<Widget> views) {
final wrappedViews = views.map<Widget>(_videoView).toList();
return Row(
children: wrappedViews,
);
}
Widget _viewRows(CallNotifier notifier) {
final views = _getRenderViews(notifier);
switch (views.length) {
case 1:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Column(
children: <Widget>[_videoView(views[0])],
));
case 2:
return Container(
margin: EdgeInsets.only(top: 100, bottom: 100),
child: Stack(
children: [
_expandedVideoRow([views[secondScreen]]),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 10),
child: GestureDetector(
onTap: () {
tempSwap = firstScreen;
firstScreen = secondScreen;
secondScreen = tempSwap;
setState(() {});
},
child: SizedBox(
height: 200,
width: 100,
child: _expandedVideoRow([views[firstScreen]])),
),
),
),
],
));
default:
}
return Container();
}
Widget _toolbar(CallNotifier notifier) {
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: () {
_onToggleMute(notifier);
setState(() {
isMute = !isMute;
});
},
child: Icon(
isMute ? Icons.mic_off : Icons.mic,
color: isMute ? Colors.white : Colors.teal,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: isMute ? Colors.teal : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: () => _onCallEnd(context),
child: Icon(
Icons.call_end,
color: Colors.white,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.redAccent,
padding: const EdgeInsets.all(15.0),
),
],
),
);
}
void _onCallEnd(BuildContext context) {
Navigator.pop(context);
}
void _onToggleMute(CallNotifier notifier) {
notifier.isMuted = notifier.isMuted;
notifier.engine.muteLocalAudioStream(notifier.isMuted);
}
#override
Widget build(BuildContext context) {
return BaseWidget<CallNotifier>(
model: CallNotifier(),
onModelReady: (model) => model.init(widget.channelName, widget.token),
builder: (context, notifier, child) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Stack(
children: <Widget>[
_viewRows(notifier),
Align(
alignment: Alignment.bottomCenter,
child: _toolbar(notifier)),
],
),
),
);
});
}
}

Images don't displayed on screen

I have modified my code. I thought I could achieve what I am willing to do but I am still having an issue. The first image is fine, but when I am adding more images, they don't display to the screen. The idea is to allow the user to click on a button to select one or several images. Then, he can tap on a second button and add one pfd file, it is like adding attachment in email.Then, if the user wants he can tap on the first button and add an other image. The list of all the documents should be displayed on the screen. I though that maybe a set State is missing somewhere. Here is the code. I do not understand where is my mistake. Thank you in advance.
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
List<PlatformFile>? _paths;
List<String> filesGB =[];
bool _loadingPath = false;
String fileExtension='';
String _fileName='';
// To access the pictures
void _openPictureFileExplorer() async {
setState(() => _loadingPath = true);
try {
_paths = (await FilePicker.platform.pickFiles(
type: FileType.media,
allowMultiple: true,
))?.files;
if (_paths != null) {
_paths!.forEach((element) {
filesGB.add(element.path.toString());
print(filesGB);
print(filesGB.length);
});
setState(() {
});
}
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
if (!mounted) return;
setState(() {
_loadingPath = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('File Picker app'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: listOfCards(filesGB),
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> listOfCards(List<String> item){
List<Widget> list = <Widget>[];
ListView.builder(
itemCount: filesGB.length,
itemBuilder: (BuildContext ctxt, int index) {
return new Container(
height: 114,
child: GestureDetector(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113, width: 113,
child: Image.file(File(item[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(item[i]
.split('/')
.last),
),
),
],
),
),),
),
);
});
return list;
}
first of all, you don't need to use for loop for building your pictures list
just use ListView.builder
but about your problem, I think it happens because you set selected pictures in a row
then return that row as a child of your column
so your pictures align horizontally and column just show widgets in vertical aligns
in other words, your column just have one child, and its a Row
so column just show pictures as possible then you just see the first picture.
for solving this problem you should return a list of widgets in the listOfCards function
just do these simple changes and I hope your problem solved
change your function return parameter to List<Widget>
Widget listOfCards(List<String> item) {
to
List<Widget> listOfCards(List<String> item) {
then just return your list
return list;
and your column should look like this
Column(
children: listOfCards(filesGB),
)
I have find a working solution. It does what I was expecting with image. I still have a problem when I delete a record, the card is not removed. I do not find where I should use the setState. I will continue to investigate.
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
//#############
//Display card with button to select type of document
child: Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Attachement
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.attach_file),
Text('Attachment'),
],
)
),
onTap: () async {
fileExtension = 'pdf';
_openDocumentFileExplorer();
},
),
),
//Photo
FlatButton(
onPressed: () {},
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment
.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {
fileExtension = 'jpeg';
_openPictureFileExplorer();
},
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: filesGB.isNotEmpty ?
Column(
children: getList(),//[listOfCards(filesGB)],
)
:Text('Nothing to display'),
),
]),)))));
}
}
List<Widget> getList() {
List<Widget> childs = [];
for (var i = 0; i < filesGB.length; i++) {
childs.add(
GestureDetector(
onTap: (){
print ("Pressed");
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113,width: 113,
child: fileExtension == 'pdf'?
Image.asset('assets/logo_pdf.png',
// fit: BoxFit.fill,
// width: double.infinity,
):
Image.file(File(filesGB[i].toString()),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(filesGB[i].toString().split('/').last,//_nameOfFile,//name,
style: TextStyle(fontWeight: FontWeight.bold),),
),
),
Padding(
padding: const EdgeInsets.only(right:25.0),
child: IconButton(onPressed: (){
//delete a record and the card displaying this record
// Delete the selected image
// This function is called when a trash icon is pressed
if (filesGB.length > 1) {
filesGB.removeAt(i);
print(filesGB);
setState(() {});
}
},
icon:Icon (Icons.delete, color: Colors.red,),),
)
],
),
),
//subtitle: Text(path),
),
));}
return childs;
}

values are null after calling network data

I am beginner in Flutter, I tried to call network data, but I used a parameter that comes from shared preferences in my function that calls the api data, and I put my function in initState but after I execute I find that the data are null, while there is data that came from internet call,
I am confused about the reason that made my data null, I mean here clubName, and points and fixture etc ...
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:footyappp/Fantazyy/club_json.dart';
import 'package:footyappp/Fantazyy/club_edit.dart';
import 'package:footyappp/Fantazyy/player_update_view.dart';
import 'package:footyappp/Fantazyy/styles.dart';
import 'package:footyappp/Fantazyy/player%20copy.dart';
import 'package:footyappp/Fantazyy/players_creation_details_view.dart';
import 'package:footyappp/Fantazyy/team_display_view.dart';
import 'package:footyappp/Key/Key.dart';
import 'package:http/http.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TeamDisplayView extends StatefulWidget {
List<Playerr> selectedPlayers;
TeamDisplayView({
Key key,
players,
selectedPlayers,
}) : selectedPlayers = (selectedPlayers == null) ? new List<Playerr>.generate(16, (int index) => null) : selectedPlayers;
#override
_TeamDisplayViewState createState() => _TeamDisplayViewState();
}
class _TeamDisplayViewState extends State<TeamDisplayView> {
getClubId() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
int clubid= prefs.getInt("clubID");
print(clubid);
makePostRequest(clubid);
}
Future<void> makePostRequest(int clubid) async {
// set up POST request arguments
String url = '${ApiKey.url}/api/questions/getclub';
Map<String, String> headers = {"Content-type": "application/json"};
String json = '{"clubid": "' + clubid.toString() + '}';
Response response = await post(url, headers: headers, body: json);
String res = response.body;
Map parsed = jsonDecode(res);
ClubEdit club = ClubEdit.fromJson(parsed);
setState((){
clubName=club.data.name;
budget=club.data.price;
points=club.data.points;
fixture=club.data.fixture;
});
print(clubName);
print(budget);
print(points);
print(fixture);
if((res != "Invalid email")||(res != "Invalid password")){
Fluttertoast.showToast(
msg: "login success",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0
);
}
else{
Fluttertoast.showToast(
msg: "Login failed",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
}
}
updateRequest(int userid, String email, int points,String fixtures,String password,String name, double price, List<Playerr> players) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
email=prefs.getString("userEmail");
password=prefs.getString("userPassword");
setState((){
userid=prefs.getInt("userID");
});
// set up POST request arguments
final url = Uri.parse('${ApiKey.url}/api/questions/updateQuestion');
Map<String, String> headers = {"Content-type": "application/json"};
List<Player> pl = [];
for(var item in players){
pl.add(Player(id:item.playerID,firstname:item.firstName.toString(),lastname:item.lastName.toString(),position:item.position.toString(),price:item.price,appearences:item.appearances,goals:item.goals,assists:item.assists,cleansheets:item.cleanSheets,redcards:item.redCards,yellowcards:item.yellowCards,image:item.image));
}
ClubJson club = ClubJson(userid: userid, email: email, password: password, name: name, price: price, players: pl );
var json = jsonEncode(club.toJson());
print(club.name);
print(club.name);
print(club.price);
for(var item in club.players){
print(item.price);
}
// make POST request
Response response = await post(url, headers: headers, body: json);
// check the status code for the result
int statusCode = response.statusCode;
// this API passes back the id of the new item added to the body
String body = response.body;
// var res = jsonDecode(response.body);
// if(res == "success"){
//
//Navigator.push(context, MaterialPageRoute(builder: (context)=>BodyFantasy(),),);
return response;
}
int clubid;
String clubName;
double budget;
int points;
String fixture;
double _budget = 150.0;
String _teamName = "";
Widget _saveChanges = Text("Press to save changes");
int userid;
String email;
String password;
#override
void initState() {
Map<int,int> teamCount = new Map<int, int>();
for (Playerr player in widget.selectedPlayers) {
if (player != null) {
_budget -= player.price;
}
}
super.initState();
this.getClubId();
}
emptyPlayer(int index) {
Playerr player = widget.selectedPlayers[index];
Widget playerView;
if (player == null) {
playerView = Image.asset("Assets/shirt_blank.png", fit: BoxFit.fitHeight,);
} else {
playerView = Column(
children: <Widget>[
Expanded(
child: Image.asset(player.image, fit: BoxFit.fitHeight,),
),
Container(
color: Colors.black,
child: Text(player.firstName.substring(0,1) + ". " + player.lastName, textAlign: TextAlign.center, softWrap: false, overflow: TextOverflow.fade,),
),
Container(
color: Colors.black,
child: Text("£${player.price}m", textAlign: TextAlign.center),
),
],
);
}
return Expanded(
child: InkWell(
onTap: () => Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {return PlayerUpdateView(selectedPlayers: widget.selectedPlayers, playerIndex: index,);})),
child: Padding(padding: EdgeInsets.only(left: 3.0, right: 3.0), child:playerView,)
),
);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(title: Text("Your team"),),
body: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
Positioned.fill(
child: Image.asset("Assets/pitch.jpg", fit: BoxFit.fitWidth, alignment: Alignment.topLeft,)
)
]
)
),
],
),
Column( //players
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 40.0, right: 40.0), child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(2, (index) => emptyPlayer(index)),
),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(5, (index) => emptyPlayer(index+2)),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(5, (index) => emptyPlayer(index+7)),
)
),
Expanded(
flex: 1,
child: Container()
),
Expanded(
flex: 6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(4, (index) => emptyPlayer(index+12)),
)
),
Expanded(
flex: 1,
child: Container()
),
Container(
color: Styles.colorAccentDark,
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Team Name", style: Styles.budgetLabel,),
),
Text("${clubName}", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Fixture", style: Styles.budgetLabel,),
),
Text("${fixture}", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Remaining Budget", style: Styles.budgetLabel,),
),
Text("£${budget}m", style: Styles.budgetLabel,)
],
),
),
Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text("Points", style: Styles.budgetLabel,),
),
Text("${points}", style: Styles.budgetLabel,)
],
),
),
/* Padding(
padding: EdgeInsets.only(top: 4.0, bottom: 4.0),
child: Column(
children: <Widget>[
Expanded(
child: Text("Next Fixture", style: Styles.budgetLabel,),
),
Text("yyy", style: Styles.budgetLabel,)
],
),
),*/
],
),
)
,
new MaterialButton(
height: 50.0,
minWidth: double.infinity,
color: Styles.colorButton,
splashColor: Colors.teal,
textColor: Colors.white,
child: _saveChanges,
onPressed: () {
if (widget.selectedPlayers.length ==16){
updateRequest(userid, "dhya#hotmail.com", 20, "22", "password", "name", 25.0, widget.selectedPlayers) ;
}
}
),
],
),
],
)
)
);
}
}
You need to call setState when you change your variables which you are trying to show in UI.
I believe you are trying to show one or more of these variables in your UI so wrap it in setState.
setState((){
clubName=club.data.name;
budget=club.data.price;
points=club.data.points;
fixture=club.data.fixture;
});
The reason being when you initialize your variables they are by default null.
And by the time makePostRequest() executes the build method is run and widgets are drawn on the screen with null data. but once the makePostRequest completes execution and you have your variables with your updated data you need to call setState this means when you call setState the build method will be called again to rebuild the widgets with the updated data.
I highly recommend you to play with the flutter counter app in the dartpad to understand how setState works.

IconButton with Row

I would like, in this code, to put the IconButton in the top right corner of each ItemView. The ItemDescription and the ItemTitle centered at the top. I try to put them in the same Row but I can't get them to fit together, either the IconButton sticks to the text or it's in the middle.
I think it is easy but I didn't find a solution.
Here is the code:
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:watch/constants.dart';
class ListViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new ListViewExampleState(
);
}
}
class ListViewExampleState extends State<ListViewExample>{
List<Container> _buildListItemsFromItems(){
int index = 0;
return item.map((item){
var container = Container(
decoration: index % 2 == 0?
new BoxDecoration(color: const Color(0xFFFFFFFF)):
new BoxDecoration(
color: const Color(0xFFFAFAF5)
),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
width: 200.0,
height: 100.0,
fit: BoxFit.cover,
),
),
Expanded(
child: Row(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0 ),
child: Text(
item.title,
style: kItemTitle,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child:Text(
item.description,
style: kItemDescription,
),
),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: IconButton(
icon: Icon(Icons.favorite_border, color: Colors.black,),
iconSize: 24.0,
onPressed: null
),
)
],)
]),
),
]),
);
index = index + 1;
return container;
}).toList();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil', style: kAppBarStyle,),
backgroundColor: Colors.white,
elevation: 0,
),
body: ListView(
children: _buildListItemsFromItems(),
),
);
}
}
Update : I have added a Spacer() and put all in the same row, and set CrossAxisAlignment to .center.
Put the Icon in the same row as the title and the description, with a Spacer() in between. That will then give you an overflow error, because the Spacer wants to take up as much space as physically possible, so with no restriction it goes on to infinity. To tell the Spacer that it is only allowed a finite amount of space, you have to set the mainAxisSize of the row to MainAxisSize.min
Here's the code, with a couple alterations so I was able to run it for myself.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ListViewExample(),
);
}
}
class ListViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new ListViewExampleState();
}
}
class ListViewExampleState extends State<ListViewExample> {
var items = [
Item(),
Item(),
Item(),
Item(),
];
List<Container> _buildListItemsFromItems() {
int index = 0;
return items.map(
(item) {
var container = Container(
decoration: index % 2 == 0
? new BoxDecoration(color: const Color(0xFFFFFFFF))
: new BoxDecoration(color: const Color(0xFFFAFAF5)),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new Container(
color: Colors.red,
width: 150.0,
height: 100.0,
),
),
Expanded(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0),
child: Text(
item.title,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
item.description,
),
),
Spacer(),
GestureDetector(
child: Icon(
Icons.favorite_border,
size: 14,
color: Colors.black,
),
onTap: null,
),
],
),
),
],
),
);
index = index + 1;
return container;
},
).toList();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil'),
backgroundColor: Colors.white,
elevation: 0,
),
body: ListView(
children: _buildListItemsFromItems(),
),
);
}
}
class Item {
final String title;
final String description;
Item({this.title = 'FooTitle', this.description = 'BarDescription'});
}

No Material widget found in flutter

this screenshot of an No Material widget found
I try to add stars RateBar as below code but i got an error no material widget found.
what i need to do is that when i pressed on this flatButton i got a window to rate the order and submit this rate, how can i do that through my code below, or to inform me how to handle it
this is the widget of StarRating
import 'package:flutter/material.dart';
typedef void RatingChangeCallback(double rating);
class StarRating extends StatelessWidget {
final int starCount;
final double rating;
final RatingChangeCallback onRatingchanged;
final Color color;
StarRating({this.starCount=5, this.rating = .0, this.onRatingchanged, this.color});
Widget buildStar(BuildContext context, int index){
Icon icon;
if (index >= rating) {
icon = Icon(
Icons.star_border,
color: Theme.of(context).buttonColor
);
}
else if(index > rating - 1 && index < rating){
icon = Icon(
Icons.star_half,
color: Theme.of(context).primaryColor,
);
}else{
icon = Icon(
Icons.stars,
color: Theme.of(context).primaryColor,
);
}
return InkResponse(
onTap: onRatingchanged==null ? null : ()=> onRatingchanged(index+1.0),
child: icon,
);
}
#override
Widget build(BuildContext context) {
return Row(
children: List.generate(starCount, (index)=>buildStar(context, index)),
);
}
}
and this is the Screen to view the starBar:
import 'package:felsaree/widgets/star.rating.dart';
import 'package:flutter/material.dart';
class StarRatingScreen extends StatefulWidget {
static const routeName = '/starRating';
#override
_StarRatingScreenState createState() => _StarRatingScreenState();
}
class _StarRatingScreenState extends State<StarRatingScreen> {
double rating =3.5;
#override
Widget build(BuildContext context) {
return StarRating(
rating: rating,
onRatingchanged: (rating) => setState(() => this.rating = rating),
);
}
}
and in orderDetails screen through the flatbutton i need to show this Star Rate:
import 'package:felsaree/providers/order_provider.dart';
import 'package:felsaree/screens/star_rating_screen.dart';
import 'package:felsaree/widgets/star.rating.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
class OrderDetails extends StatefulWidget {
static const routeName = '/orderDetails';
#override
_OrderDetailsState createState() => _OrderDetailsState();
}
class _OrderDetailsState extends State<OrderDetails> {
double rating = 3.5;
// Widget ratingChange(double rating){
// return StarRating(
// rating: rating,
// onRatingchanged: (rating)=>this.rating = rating,);
// }
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context).size.height;
final orderId = ModalRoute.of(context).settings.arguments as int;
final orderProvider = Provider.of<OrderProvider>(context, listen: false);
final order = orderProvider.findOrderById(orderId);
AppBar appBar = AppBar(title: Text(order.restaurantName),);
double _totalPrice =orderProvider.totalItemsPrice(order.orderItems);
bool _isAddress = orderProvider.checkUserAdress(order.address);
return Scaffold(
appBar: appBar,
body: Column(
children: <Widget>[
Card(
elevation: 4,
margin: EdgeInsets.all(10),
child: Padding(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Text(order.id.toString()),
SizedBox(height: 4,),
Text(order.restaurantName),
SizedBox(height: 4,),
Text(order.branchName),
SizedBox(height: 4,),
],
),
Column(
children: <Widget>[
Text(DateFormat.yMd().format(DateTime.now())),
SizedBox(height: 15,),
Text('InProgress'),
SizedBox(height: 15,)
],
)
],
),),
),
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.grey[100],
border: Border.all(width: 2, color: Colors.grey)
) ,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Price'),
Text('${_totalPrice}L.E'),
Text('Total: ${order.price}L.E')
],
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('PC Discount'),
Text('${order.discountValue}L.E'),
Text(''),
],
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('service Tax'),
Text('${order.serviceTax}L.E'),
Text(''),
],
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Delivery'),
Text('${order.delivery}L.E'),
Text(''),
],
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Vat'),
Text('${order.vatAmount}L.E'),
Text(''),
],
),
],
),
),
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.all(10),
margin: EdgeInsets.only(bottom: 20),
height: (mediaQuery
- appBar.preferredSize.height
- MediaQuery.of(context).padding.top)*0.30,
width: MediaQuery.of(context).size.width*.8,
child: ListView.builder(
itemCount: order.orderItems.length,
itemBuilder: (ctx, index){
final item = order.orderItems[index];
if(item.userComments == ''){
String userComment= 'no comment';
item.userComments = userComment;
}
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(item.image,),
),
title: Text(item.itemName),
subtitle: Text('count: ${item.count}'),
trailing: Text(item.userComments),
);
}
),
),
Container(
width: double.infinity,
margin: EdgeInsets.only(right: 10, left: 10),
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
color: Colors.grey[100],
child: Text('Delivery Address', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),),
),
SizedBox(height: 8),
Container(
width: double.infinity,
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[100])
),
child: _isAddress? Text(order.address) : Text('no address found'),
),
FlatButton(
onPressed: ()=>Navigator.of(context).pushNamed(StarRatingScreen.routeName),
child: Text('Rate The Order', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),))
],
),
);
}
}
This can be fixed by ensuring that your main includes MaterialApp() and Scaffold() as ancestors of your widgets as so:
void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: YourWidget(),
),
));
}
If, for whatever reason you don't want to use MaterialApp... you can use Material():
void main() {
runApp(
home: Scaffold(
appBar: AppBar(),
body: Material( child: YourWidget()),
),
);
}