正文
今天,我们将使用 flutter 构建一个动态的 todo list 的应用。
开发完成的效果如下:

我们直接进入正题。
基础 flutter 应用脚手架
# create new project flutter create flutter_todo_app # navigate to project cd flutter_todo_app # run flutter flutter run
我们清除文件 lib/main.dart,从头开始开发。
main.dart 这个文件是 flutter 应用的入口文件。在这篇文章中,我将仅仅使用这个文件来开发。
首先,我们先导入 material 包。
import 'package:flutter/material.dart';
下一步,我们得有一个主要的方法。在这个例子中,它将返回 todoapp 实例。
void main() => runapp( new todoapp(), );
这个 todoapp 应该是一个 statelesswidget。这将会是我们列表的骨架
class todoapp extends statelesswidget {
@override
widget build(buildcontext context) {
return new materialapp(
title: 'todo list',
home: new todolist(),
);
}
}
正如你所见,我返回了一个 materialapp 实例,它具有一个 title 属性和一个 home 功能。这个 home 函数返回一个 todolist 实例。这个 todolist 类才是我们控制的列表项。
class todolist extends statefulwidget {
@override
_todoliststate createstate() => new _todoliststate();
}
等等,这是什么?所有的挂件都会调用一个状态去知道将要发生什么和渲染什么。在这个例子中,我们调用了 _todoliststate。这将包含应用中的列表及其运行逻辑。
class _todoliststate extends state<todolist> {
final texteditingcontroller _textfieldcontroller = texteditingcontroller();
final list<todo> _todos = <todo>[];
@override
widget build(buildcontext context) {
// widget template comes here
}
// other functions
}
接下来,创建列表变量。
final list<todo> _todos = <todo>[];
也许你已经注意到了,我们定义了这个列表的类型是 todo,但 flutter 怎么知道 todo 长是什么样呢?
flutter 并不会知道,所以我们得创建一个类来定义。如下:
class todo {
todo({required this.name, required this.checked});
final string name;
bool checked;
}
这跟 typescript 中的类型定义很像。我们告诉 flutter 一个 todo 项应该包含什么,什么字段是必须的。在我们的案例中,我们有名字和 checked 两个状态属性。
回到 _todoliststate 中,我们开始让我们的挂件展示点东西。
@override
widget build(buildcontext context) {
return new scaffold(
appbar: new appbar(
title: new text('todo list'),
),
body: listview(
padding: edgeinsets.symmetric(vertical: 8.0),
children: _todos.map((todo todo) {
return todoitem(
todo: todo,
ontodochanged: _handletodochange,
);
}).tolist(),
),
floatingactionbutton: floatingactionbutton(
onpressed: () => _displaydialog(),
tooltip: 'add item',
child: icon(icons.add)),
);
}
让我们看看上面发生了什么。我们返回了应用的一个脚手架,在脚手架上,我们添加了一个包含标题的 appbar 的属性。我们定义了 body 属性,这将存放 listview 组件。
在上面代码片段中,通过 map 方法返回每个元素的 todoitem。
然后,在应用的底部,我们定义了一个按钮。当按钮被点击时候,将调用 _displaydialog 方法。
到目前为止,我们还需要完成下面的代码片段:
- 创建
todoitem - 定义一个
_displaydialog函数 - 定义一个
_handletodochange函数
让我们一个一个来解决。
创建 todoitem
todoitem 是我们列表项的单独体现。
class todoitem extends statelesswidget {
todoitem({
required this.todo,
required this.ontodochanged,
}) : super(key: objectkey(todo));
final todo todo;
final ontodochanged;
textstyle? _gettextstyle(bool checked) {
if (!checked) return null;
return textstyle(
color: colors.black54,
decoration: textdecoration.linethrough,
);
}
@override
widget build(buildcontext context) {
return listtile(
ontap: () {
ontodochanged(todo);
},
leading: circleavatar(
child: text(todo.name[0]),
),
title: text(todo.name, style: _gettextstyle(todo.checked)),
);
}
}
正如你所见,我们传递一个 todo 和 ontodochanged 进来。
然后我们定义了一个 textstyle 去处理列表项是否被勾选。
然后我们使用 listtile 挂件来展示内容和添加点击事件。
展示 dialog 去添加列表项
点击应用的右下角的按钮,将会调起 _displaydialog 方法。
这将调起一个带有文本框的对话框。当点击确认的时候,将以文本框的内容基础添加一个新的列表项。
在 _todoliststate 中创建 _displaydialog。
future<void> _displaydialog() async {
return showdialog<void>(
context: context,
barrierdismissible: false, // user must tap button!
builder: (buildcontext context) {
return alertdialog(
title: const text('add a new todo item'),
content: textfield(
controller: _textfieldcontroller,
decoration: const inputdecoration(hinttext: 'type your new todo'),
),
actions: <widget>[
textbutton(
child: const text('add'),
onpressed: () {
navigator.of(context).pop();
_addtodoitem(_textfieldcontroller.text);
},
),
],
);
},
);
}
flutter 中的 future 表明在将来的某个时候将返回潜在的值或者错误信息。在我们的案例中,将会返回用户输入的值。
对话框中有一个动作,就是当我们点击按钮的时候,将会关闭对话框并且调用 _addtodoitem 函数。
我们看看 _addtodoitem 函数长什么样:
void _addtodoitem(string name) {
setstate(() {
_todos.add(todo(name: name, checked: false));
});
_textfieldcontroller.clear();
}
这函数比你想象中的简单,是吧。
列表项添加状态
最后一部分是,我们应该为列表项进行标记。我们需要一个处理函数 _handletodochange:
void _handletodochange(todo todo) {
setstate(() {
todo.checked = !todo.checked;
});
}
这里我们只是改变了其列表项的状态。
完整的代码如下:
// lib/main.dart
import 'package:flutter/material.dart';
class todo {
todo({required this.name, required this.checked});
final string name;
bool checked;
}
class todoitem extends statelesswidget {
todoitem({
required this.todo,
required this.ontodochanged,
}) : super(key: objectkey(todo));
final todo todo;
final ontodochanged;
textstyle? _gettextstyle(bool checked) {
if (!checked) return null;
return textstyle(
color: colors.black54,
decoration: textdecoration.linethrough,
);
}
@override
widget build(buildcontext context) {
return listtile(
ontap: () {
ontodochanged(todo);
},
leading: circleavatar(
child: text(todo.name[0]),
),
title: text(todo.name, style: _gettextstyle(todo.checked)),
);
}
}
class todolist extends statefulwidget {
@override
_todoliststate createstate() => new _todoliststate();
}
class _todoliststate extends state<todolist> {
final texteditingcontroller _textfieldcontroller = texteditingcontroller();
final list<todo> _todos = <todo>[];
@override
widget build(buildcontext context) {
return new scaffold(
appbar: new appbar(
title: new text('todo list'),
),
body: listview(
padding: edgeinsets.symmetric(vertical: 8.0),
children: _todos.map((todo todo) {
return todoitem(
todo: todo,
ontodochanged: _handletodochange,
);
}).tolist(),
),
floatingactionbutton: floatingactionbutton(
onpressed: () => _displaydialog(),
tooltip: 'add item',
child: icon(icons.add)),
);
}
void _handletodochange(todo todo) {
setstate(() {
todo.checked = !todo.checked;
});
}
void _addtodoitem(string name) {
setstate(() {
_todos.add(todo(name: name, checked: false));
});
_textfieldcontroller.clear();
}
future<void> _displaydialog() async {
return showdialog<void>(
context: context,
barrierdismissible: false, // user must tap button!
builder: (buildcontext context) {
return alertdialog(
title: const text('add a new todo item'),
content: textfield(
controller: _textfieldcontroller,
decoration: const inputdecoration(hinttext: 'type your new todo'),
),
actions: <widget>[
textbutton(
child: const text('add'),
onpressed: () {
navigator.of(context).pop();
_addtodoitem(_textfieldcontroller.text);
},
),
],
);
},
);
}
}
class todoapp extends statelesswidget {
@override
widget build(buildcontext context) {
return new materialapp(
title: 'todo list',
home: new todolist(),
);
}
}
void main() => runapp(new todoapp());
本文采用的是意译的方式。原文链接 - build a todo list app with flutter
以上就是ios开发flutter构建todo list应用的详细内容,更多关于ios开发flutter构建todo list的资料请关注代码网其它相关文章!
发表评论