Reputation: 97
I'm learning flutter and I've developed my first todo app. The issue I'm experiencing is that the app works well on debug mode on my device and emulator but when I run flutter run build command and install the release apk the textfield where you enter the Todo item doest work and instead I get a grey box. I'll append some images to clarify. I'm a noob so it's probable that I missed something. I just wanted to test my app as a release apk to see if it was fluent.
Thanks for your help!
this is the debug apk that vscode installs in my Motorola one
this is how that dialog looks like on the release apk
I've uploaded the project for you to see but here is the Form code and the list
TodoItemForm.dart:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:todo/models/TodoItemModel.dart';
class TodoItemForm extends StatefulWidget {
TodoItemForm({
Key key,
@required this.context,
this.item,
this.onSubmit,
this.onClose,
}) : super(key: key) {
if (this.item == null)
this.item = new TodoItemModel("", false, DateTime.now(), DateTime.now());
}
final BuildContext context;
TodoItemModel item;
final ValueChanged<TodoItemModel> onSubmit;
final VoidCallback onClose;
@override
_TodoItemFormState createState() => _TodoItemFormState();
}
class _TodoItemFormState extends State<TodoItemForm> {
TextEditingController _todoItemTextController = new TextEditingController();
@override
void initState() {
super.initState();
if (widget.item != null) {
_todoItemTextController.value = TextEditingValue(text: widget.item.text);
} else {
widget.item = new TodoItemModel(
_todoItemTextController.text, false, DateTime.now(), DateTime.now());
}
}
void onSubmit() {
widget.item.text = _todoItemTextController.text;
widget.onSubmit(widget.item);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Row(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Icon(
Icons.playlist_add,
color: Theme.of(context).primaryColor,
),
),
Text(
"New To Do Item",
),
],
),
insetPadding: EdgeInsets.symmetric(horizontal: 2),
content: Expanded(
child: TextField(
controller: _todoItemTextController,
autofocus: true,
decoration: InputDecoration(
labelText: "Task to do:",
hintText: "Buy Groseries!",
),
),
),
actions: <Widget>[
FlatButton(
onPressed: this.onSubmit,
child: Text(
"SAVE",
style: new TextStyle(color: Theme.of(context).accentColor),
),
),
FlatButton(
onPressed: widget.onClose,
child: Text(
"CANCEL",
style: new TextStyle(color: Theme.of(context).accentColor),
),
),
],
);
}
}
TaskList.dart:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:todo/models/TodoItemModel.dart';
import 'package:todo/services/TodoServiceProvider.dart';
import 'package:todo/widgets/TodoItem.dart';
import 'package:todo/widgets/TodoItemForm.dart';
class TaskList extends StatefulWidget {
TaskList({Key key}) : super(key: key);
@override
_TaskListState createState() => _TaskListState();
}
class _TaskListState extends State<TaskList> {
List<TodoItemModel> _items = [];
final _todoItemTextController = new TextEditingController();
@override
void initState() {
super.initState();
this.refreshTodos();
}
void refreshTodos() {
TodoServiceProvider.getTodoItems().then((todoList) {
setState(() {
_items = todoList;
});
});
}
void _handleSubmit(TodoItemModel newItem) {
TodoServiceProvider.createTodo(newItem).then((todoItem) {
this.refreshTodos();
this._handleClose();
});
}
void _handleEdit(TodoItemModel item) {
TodoServiceProvider.updateTodo(item).then((todoItem) {
this.refreshTodos();
this._handleClose();
});
}
void _handleClose() {
Navigator.pop(context);
_todoItemTextController.clear();
}
Future<bool> _handleItemCompleted(TodoItemModel model, DismissDirection dir) {
return TodoServiceProvider.deleteTodo(model.id).then((response) {
if (response) {
setState(() {
_items.remove(model);
});
return Future.value(true);
}
return Future.value(false);
}).catchError((error) => Future.value(false));
}
void _showTodoItemForm({TodoItemModel item: null}) {
final alert = TodoItemForm(
context: context,
item: item,
onSubmit: item == null ? this._handleSubmit : this._handleEdit,
onClose: this._handleClose,
);
showDialog(
context: context,
builder: (_) {
return alert;
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Todo"),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _showTodoItemForm,
),
body: Container(
padding: EdgeInsets.all(12),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ReorderableListView(
onReorder: (oldIndex, newIndex) {
this.setState(() {
final aux = _items[oldIndex];
if (oldIndex > newIndex) {
_items.removeAt(oldIndex);
_items.insert(newIndex, aux);
} else {
_items.insert(newIndex, aux);
_items.removeAt(oldIndex);
}
});
},
children: [
for (final _item in _items)
FlatButton(
key: ValueKey(_item),
child: TodoItem(
model: _item,
onItemCompleted: this._handleItemCompleted,
),
onPressed: () {
this._showTodoItemForm(item: _item);
},
),
],
),
)
],
),
),
);
}
}
TodoItemModel.dart:
import 'package:todo/widgets/TodoItem.dart';
class TodoItemModel {
int _id;
String _text;
bool _finished;
DateTime _creationDate;
DateTime _dueDate;
TodoItemModel(this._text, this._finished, this._creationDate, this._dueDate);
int get id => _id;
String get text => _text;
DateTime get creationDate => _creationDate;
void set text(String value) {
_text = value;
}
void set id(int value) => _id = value;
Map<String, dynamic> toJSON() {
var map = new Map<String, dynamic>();
map["text"] = _text;
map["creation_date"] = _creationDate.toIso8601String();
if (_id != null) map["id"] = _id;
return map;
}
TodoItemModel.fromJSON(Map<String, dynamic> json) {
this._id = json["id"];
this._text = json["text"];
this._creationDate = DateTime.parse(json["creation_date"]);
}
}
Full project url: https://drive.google.com/drive/folders/1tNue3EfdwV_7M7zHt_A7A4RsNIdppHqj?usp=sharing
Upvotes: 0
Views: 1653
Reputation: 282
I think the problem is the Expanded Widget in AlertDialog.
TodoItemForm.dart:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:todo/models/TodoItemModel.dart';
class TodoItemForm extends StatefulWidget {
TodoItemForm({
Key key,
@required this.context,
this.item,
this.onSubmit,
this.onClose,
}) : super(key: key) {
if (this.item == null)
this.item = new TodoItemModel("", false, DateTime.now(), DateTime.now());
}
final BuildContext context;
TodoItemModel item;
final ValueChanged<TodoItemModel> onSubmit;
final VoidCallback onClose;
@override
_TodoItemFormState createState() => _TodoItemFormState();
}
class _TodoItemFormState extends State<TodoItemForm> {
TextEditingController _todoItemTextController = new TextEditingController();
@override
void initState() {
super.initState();
if (widget.item != null) {
_todoItemTextController.value = TextEditingValue(text: widget.item.text);
} else {
widget.item = new TodoItemModel(
_todoItemTextController.text, false, DateTime.now(), DateTime.now());
}
}
void onSubmit() {
widget.item.text = _todoItemTextController.text;
widget.onSubmit(widget.item);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Row(
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(0, 0, 10, 0),
child: Icon(
Icons.playlist_add,
color: Theme.of(context).primaryColor,
),
),
Text(
"New To Do Item",
),
],
),
insetPadding: EdgeInsets.symmetric(horizontal: 2),
content: Container( //Change this line
child: TextField(
controller: _todoItemTextController,
autofocus: true,
decoration: InputDecoration(
labelText: "Task to do:",
hintText: "Buy Groseries!",
),
),
),
actions: <Widget>[
FlatButton(
onPressed: this.onSubmit,
child: Text(
"SAVE",
style: new TextStyle(color: Theme.of(context).accentColor),
),
),
FlatButton(
onPressed: widget.onClose,
child: Text(
"CANCEL",
style: new TextStyle(color: Theme.of(context).accentColor),
),
),
],
);
}
}
Upvotes: 4