I am new to flutter, I want to dismiss my dialog after the task completion. I've tried with:
Navigator.pop(context, true);
But my screen is getting black and dialog is still up there. here is my dialog code.
Dialog _dialog = new Dialog(
child: new Row(
mainAxisSize: MainAsixSize.min,
children: <Widget> [
new CircularProgressIndicator(),
new Text("Loading")]),
);
https://docs.flutter.io/flutter/material/showDialog.html says
The dialog route created by this method is pushed to the root navigator. If the application has multiple Navigator objects, it may be necessary to call Navigator.of(context, rootNavigator: true).pop(result) to close the dialog rather just Navigator.pop(context, result).
so I'd assume one of these two should do what you want.
This code works for me:
BuildContext dialogContext;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return Dialog(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: [
new CircularProgressIndicator(),
new Text("Loading"),
],
),
);
},
);
await _longOperation();
Navigator.pop(dialogContext);
If you don't want to return any result after showDialog is closed, you can use
Navigator.pop(context);
If you want to pass result call
Navigator.pop(context, result);
Example:
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text('Wanna Exit?'),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context, false), // passing false
child: Text('No'),
),
FlatButton(
onPressed: () => Navigator.pop(context, true), // passing true
child: Text('Yes'),
),
],
);
}).then((exit) {
if (exit == null) return;
if (exit) {
// user pressed Yes button
} else {
// user pressed No button
}
});
//it work conrrectly
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
},
Generally Navigator.pop(context); works.
But If the application has multiple Navigator objects and dialogBox doesn't close, then try this
Navigator.of(context, rootNavigator: true).pop();
If you want to pass result call, try
Navigator.pop(context,result);
OR
Navigator.of(context, rootNavigator: true).pop(result);
Better to use Completer, because if your operation is too short or the device is too slow, then the dialogContext variable will not be initialized and you can't close the dialog.
final dialogContextCompleter = Completer<BuildContext>();
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
if(!dialogContextCompleter.isCompleted) {
dialogContextCompleter.complete(dialogContext);
}
return AlertDialog(
content: CircularProgressIndicator(),
);
},
);
// Close progress dialog
final dialogContext = await dialogContextCompleter.future;
Navigator.pop(dialogContext);
This will close dialog/alert box
Navigator.of(context).pop();
showDialog(
context: context,
builder: (BuildContext context) => Center(
child: CircularProgressIndicator(),
),
);
await Future<int>.delayed(Duration(seconds: 3));
Navigator.of(context, rootNavigator: true).pop();
Add on to Günter's answers. If you need to dismiss it when the user clicks elsewhere
change this property to true
barrierDismissible: true,
Try this. It will definitely work. use the context of pageBuilder in Navigator to pop the dialog from screen.
showGeneralDialog(
context: context,
barrierLabel: "XYZ",
barrierDismissible: true,
barrierColor: Colors.black.withOpacity(0.7),
pageBuilder: (dialogContext, __, ___) {
return Center(
child: Container(
height: 240,
margin: const EdgeInsets.symmetric(horizontal: 15),
decoration: bd,
child: SizedBox.expand(
GestureDetector(
onTap: (){
Navigator.pop(dialogContext);
},
child: const Padding(
padding: EdgeInsets.fromLTRB(10,0,10,0),
child: Icon(Icons.close, size: 26, color:Colors.white),
),
),
)
)
);
}
);
Related
I have get an index here but I want display it from first to last in image : I want to display "hello" first then the rest
code:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groups")
.doc(groupId)
.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
var chats = snapshot.data?["chats"];
return ...)};
ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: chats.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text(chats[index]),
}),
Basically I want to display the recently added string first.
You have to reverse: ture in your listView,
like this:
ListView.builder(
reverse:true,
physics: const BouncingScrollPhysics(),
itemCount: chats.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return Text(chats[index]),
}),
I am new to Flutter development.
I want to retrieve data from a .json file (list of universities), and allow user to type the first letters so they can find their universities in the flutter drop down options.
The data I want to retrieve from the .json file is 'nom_court'.
My initial code is a textfield, and it's working perfectly :
TextFormField buildUniFormField() {
return TextFormField(
keyboardType: TextInputType.uni,
onSaved: (newValue) => uni = newValue,
onChanged: (value) {
if (value.isNotEmpty) {
removeError(error: kEmailNullError);
} else if (emailValidatorRegExp.hasMatch(value)) {
removeError(error: kInvalidEmailError);
}
return null;
},
validator: (value) {
if (value.isEmpty) {
addError(error: kEmailNullError);
return "";
} else if (!emailValidatorRegExp.hasMatch(value)) {
addError(error: kInvalidEmailError);
return "";
}
return null;
},
decoration: InputDecoration(
labelText: "University",
hintText: "Enter your university name",
floatingLabelBehavior: FloatingLabelBehavior.always,
suffixIcon: CustomSurffixIcon(svgIcon: "assets/icons/uni.svg"),
I am now trying to use a dropdownlist, using the .json file, and put this directly in the widget code :
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
buildEmailFormField(),
SizedBox(height: getProportionateScreenHeight(30)),
buildUniFormField(),
DropdownButton<String>(
items:list.map((Map val){
return DropdownMenuItem<String>(
value: val["Uniname"],
child: new Text(val["nom_court"]),
);).toList(),},
It's not working, I have an error on the 'Dropdown Button, saying 'The parameter Onchanged isn't defined'
Thanks :)
use autocomplete_textfield: ^1.6.4 package it would better option than a dropdown widget
https://medium.com/flutter-community/implementing-auto-complete-search-list-a8dd192bd5f6
So, it's just like your error message says, you haven't provided onChanged parameter to your DropdownButton.
You should create a state for current dropdown value and setState it in onChanged callback () for current dropdown value and setState it in onChanged callback:
class MyWidgetState extends State<MyWidget> {
String dropdownValue = // here specify the initial value for DropdownButton
Widget build(...) {
//...
DropdownButton(
value: dropdownValue,
onChanged: (value) => setState(() => dropdownValue = value),
items: list.map(...),
),
}
}
I assume you are already using StatefulWidget, if not please read the documentation
I did somehow managed to get the database contents to show via listview. However, its not doing it properly. As soon as i run the emulator the contents stored in the database should appear, but they don't. It also shows that the database is empty even though it clearly isn't. But once i add a new item to the database and click save, everything shows up (except the one i last added and it shows up on the next update). I have no clue how to fix this, i tried placing _listTodos() everywhere to see if it executes before the widgets but there wasn't any improvement. The issue is in the ListDisplay class I think, so you can just skip over the rest, I just have the entire code for convenience.
import 'package:flutter/material.dart';
import 'model/todo_model.dart';
import 'model/todo.dart';
class ListGradesPage extends StatefulWidget {
final String title;
ListGradesPage({this.title, Key key}) : super(key: key);
_ListGradesPageState createState() => _ListGradesPageState();
}
var _todoItem;
var _lastInsertedId = 0;
final _model = TodoModel();
Future<void> _deleteTodo() async {
_model.deleteAllTodo();
}
class _ListGradesPageState extends State<ListGradesPage> {
//final _model = TodoModel();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
print('editing...');
//_listTodos();
}),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
print('deleting all...');
setState(() {
_deleteTodo();
});
}),
],
),
body: ListDisplayPage(),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddGrade()),
);
},
child: Icon(Icons.add),
backgroundColor: Colors.blue,
),
);
}
}
class ListDisplayPage extends StatefulWidget {
ListDisplay createState() => ListDisplay();
}
class ListDisplay extends State<ListDisplayPage> {
int _selectedIndex;
List<Todo> todos = new List<Todo>();
Future<void> _listTodos() async {
todos = await _model.getAllTodos();
if (todos.isEmpty) {
print('it is empty-2.');
} else {
print("not empty-2");
}
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
}
_onSelected(int index) {
_selectedIndex = index;
}
#override
void initState() {
super.initState();
_listTodos();
// _listTodos() is not calling the function above for some reason, but executes everything below it
// In the database there are items stored however it says the databse is empty...
// until i add a new item and everything shows up except the item i recently added
if (todos.isEmpty) {
print('To Dos:');
for (Todo todo in todos) {
print(todo);
}
print('it is empty.');
} else {
print("not empty");
}
}
#override
Widget build(BuildContext context) {
//Color clr = Colors.transparent;
return todos.isEmpty
? Center(
child: Text(
'Nothing to show! Is it empty? ' + (todos.isEmpty).toString()))
: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return Card(
// <-- Card widget
child: Container(
color: _selectedIndex != null && _selectedIndex == index
? Colors.lightBlueAccent
: Colors.transparent,
child: ListTile(
leading: GestureDetector(
onTap: () {
setState(() {
_onSelected(index);
print(index);
});
},
child: Container(
width: MediaQuery.of(context).size.width / 2,
child:
Text(todos[index].sid + '\n' + todos[index].grade),
),
),
),
),
);
},
);
}
}
class AddGrade extends StatelessWidget {
String _sid, _grade;
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Grade"),
),
body: Form(
key: _formKey,
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student ID',
labelText: 'SID',
),
onSaved: (String value) {
print('Saving SID $value');
_sid = value.toString();
},
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
decoration: const InputDecoration(
hintText: 'Student Grade',
labelText: 'Grade',
),
onSaved: (String value) {
print('Saving Grade $value');
_grade = value.toString();
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_formKey.currentState.save();
_addTodo();
//_listTodos();
Navigator.pop(context);
},
child: Icon(Icons.save),
backgroundColor: Colors.blue,
),
);
}
Future<void> _addTodo() async {
Todo newTodo = Todo(sid: _sid, grade: _grade);
_lastInsertedId = await _model.insertTodo(newTodo);
}
}
Console Output (on execution):
Restarted application in 1,607ms.
I/flutter (14196): To Dos:
I/flutter (14196): it is empty.
I/flutter (14196): not empty-2
I/flutter (14196): To Dos:
I/flutter (14196): Todo{id: 1, sid: q, grade: qq}
I/flutter (14196): Todo{id: 2, sid: w, grade: ww}
I/flutter (14196): Todo{id: 3, sid: e, grade: ee}
I/flutter (14196): Todo{id: 4, sid: r, grade: }
I/flutter (14196): Todo{id: 5, sid: hh, grade: kk}
Screenshots of emulator, before adding new student, and after adding new student (the recent one doesn't show up either until I add another student again),
Before
After
I apologize if i didn't follow the guidelines, never really posted questions on here before.
Are you aware of FutureBuilder? I would suggest wrapping your ListView.builder in a future builder and passing in the _loadTodos function as the future. Then you can remove all of the initState code that initializes the todos.
Generally, I find that doing async work in initState doesn't always work. The UI has already built, and doesn't know to rebuild when the async work is complete. Another option might just be to call setState once the async function completes with the todos. I would think that the FutureBuilder is the better way to do it though.
If you need some additional help, let me know. I could probably write some of it out for you.
I am trying to show attribute of wfs gml layer from geoserver as label in my openlayer3 application. I am successful to get label as text but unable to access the particular attribute 'name'. Given is the code I am working with.
var sourceWFS = new ol.source.Vector({
loader: function (extent) {
$.ajax('..../geoserver/harry/ows?', {
type: 'GET',
data: {
service: 'WFS',
version: '1.1.0',
request: 'GetFeature',
typename: 'ABC',
srsname: 'EPSG:3857',
geometryField:'geometry',
bbox: extent.join(',') + ',EPSG:3857'
}
}).done(function (response) {
sourceWFS.addFeatures(formatWFS.readFeatures(response));
});
},
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ()),
strategy: ol.loadingstrategy.bbox,
projection: 'EPSG:3857',
});
var layerWFS = new ol.layer.Vector({
source: sourceWFS
});
var interaction;
var interactionSelectPointerMove = new ol.interaction.Select({
condition: ol.events.condition.pointerMove
});
var interactionSelect = new ol.interaction.Select({
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(255,0,0,1.0)',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.5)'
}),
text: new ol.style.Text({
text:("abcd")
})
})
});
var interactionSnap = new ol.interaction.Snap({
source: layerWFS.getSource()
});
I am getting abcd as label on selection
You will need a style function to set the text in the style from whichever feature property you wish to display
var selectStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(255,0,0,1.0)',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.5)'
}),
text: new ol.style.Text({
text:("abcd")
})
});
var interactionSelect = new ol.interaction.Select({
style: function(feature) {
selectStyle.getText().setText(feature.get('name'));
return selectStyle;
}
});
You will not get any attribute that is "hidden" by a GML attribute by default. The most common "missing" attributes are name and id. You can turn off this (standard complying) behaviour by checking the Override GML Attributes in the WFS services page for the version of GML your client is requesting.
What you are actually displaying is the "abcd" string itself and not the value of "abcd" property.
To access some feature property value in an ol.Style you must use a StyleFunction as follows :
style: function(feature, resolution){
return new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(255,0,0,1.0)',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(255,0,0,0.5)'
}),
text: new ol.style.Text({
text: feature.get("abcd");
})
})
}
I am new to Flutter and Dart. I have some data from an api json based and the variable of the data is called data. I have taken this sample code from the official flutter documentation and i want to be able to use the data variable and replace the string text, like so:
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text(data[index]['name']),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
new ButtonTheme.bar( // make buttons use the appropriate styles for cards
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () { /* ... */ },
),
new FlatButton(
child: const Text('LISTEN'),
onPressed: () { /* ... */ },
),
],
),
),
],
),
);
But I am getting an error on line title: const Text(data[index]['name']), and the error says Argument of type constant creation must be constant expression. This error it's coming from the Android Studio itself (version 3.2)
But when i use this code (taken from youtube course) it is working fine:
return new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Card(
child: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Container(
child: Text(data[index]['name'],
style: TextStyle(
fontSize: 16.0, color: Colors.black54))),
)),
new Card(
child: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Container(
child: Text(data[index]['description'],
style: TextStyle(
fontSize: 16.0, color: Colors.redAccent)),
)),
)
],
),
);
How to use the first code example without getting any errors? Thanks!
UPDATE: Here is the full code
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.green,
),
home: new MyHomePage(title: 'Flutter App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List data;
Future<String> getData() async {
http.Response response = await http.get(
Uri.encodeFull('https://dummyapicall.api'),
headers: {
"Accept": "application/json",
}
);
this.setState(() {
data = json.decode(response.body);
});
return 'Success!';
}
#override
void initState() {
super.initState();
this.getData();
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
// return new Container(
// child: new Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: <Widget>[
// new Card(
// child: new Padding(
// padding: const EdgeInsets.all(16.0),
// child: new Container(
// child: Text(data[index]['name'],
// style: TextStyle(
// fontSize: 16.0, color: Colors.black54))),
// )),
// new Card(
// child: new Padding(
// padding: const EdgeInsets.all(16.0),
// child: new Container(
// child: Text(data[index]['description'],
// style: TextStyle(
// fontSize: 16.0, color: Colors.redAccent)),
// )),
// )
// ],
// ),
// );
return new Card(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: const Icon(Icons.album),
title: const Text(data[index]['name']),
subtitle: const Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
new ButtonTheme.bar( // make buttons use the appropriate styles for cards
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: const Text('BUY TICKETS'),
onPressed: () { /* ... */ },
),
new FlatButton(
child: const Text('LISTEN'),
onPressed: () { /* ... */ },
),
],
),
),
],
),
);
},
),
// floatingActionButton: new FloatingActionButton(
// onPressed: _incrementCounter,
// tooltip: 'Increment',
// child: new Icon(Icons.add),
// ), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
As your Text widget is defined as const the label or the properties of the widget should also be const, as your data is dynamic not a const at the compile time itself you will be shown the error.
Const Widget must be created from data that can be calculated at compile time. A const object does not have access to anything you would need to calculate at runtime. 1 + 2 is a valid const expression, but new DateTime.now() is not.
From : More about Const, Static, Final
Just remove the const keyword in both places of the ListTile.
They can't be constant as you are including a variable (data) inside the Text widget.
children: <Widget>[
ListTile(
leading: const Icon(Icons.album),
title: Text(data[index]['name']),
subtitle: const Text(
'Music by Julie Gable. Lyrics by Sidney Stein.'),
),
.....