ios開發(fā)Flutter構(gòu)建todo?list應(yīng)用
正文
今天,我們將使用 Flutter 構(gòu)建一個動態(tài)的 todo list 的應(yīng)用。
開發(fā)完成的效果如下:

我們直接進入正題。
基礎(chǔ) Flutter 應(yīng)用腳手架
# create new project flutter create flutter_todo_app # navigate to project cd flutter_todo_app # run flutter flutter run
我們清除文件 lib/main.dart,從頭開始開發(fā)。
main.dart 這個文件是 Flutter 應(yīng)用的入口文件。在這篇文章中,我將僅僅使用這個文件來開發(fā)。
首先,我們先導(dǎo)入 material 包。
import 'package:flutter/material.dart';
下一步,我們得有一個主要的方法。在這個例子中,它將返回 TodoApp 實例。
void main() => runApp( new TodoApp(), );
這個 TodoApp 應(yīng)該是一個 statelessWidget。這將會是我們列表的骨架
class TodoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Todo list',
home: new TodoList(),
);
}
}
正如你所見,我返回了一個 MaterialApp 實例,它具有一個 title 屬性和一個 home 功能。這個 home 函數(shù)返回一個 TodoList 實例。這個 TodoList 類才是我們控制的列表項。
class TodoList extends StatefulWidget {
@override
_TodoListState createState() => new _TodoListState();
}
等等,這是什么?所有的掛件都會調(diào)用一個狀態(tài)去知道將要發(fā)生什么和渲染什么。在這個例子中,我們調(diào)用了 _TodoListState。這將包含應(yīng)用中的列表及其運行邏輯。
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
}
接下來,創(chuàng)建列表變量。
final List<Todo> _todos = <Todo>[];
也許你已經(jīng)注意到了,我們定義了這個列表的類型是 Todo,但 Flutter 怎么知道 Todo 長是什么樣呢?
Flutter 并不會知道,所以我們得創(chuàng)建一個類來定義。如下:
class Todo {
Todo({required this.name, required this.checked});
final String name;
bool checked;
}
這跟 typescript 中的類型定義很像。我們告訴 flutter 一個 todo 項應(yīng)該包含什么,什么字段是必須的。在我們的案例中,我們有名字和 checked 兩個狀態(tài)屬性。
回到 _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)),
);
}
讓我們看看上面發(fā)生了什么。我們返回了應(yīng)用的一個腳手架,在腳手架上,我們添加了一個包含標(biāo)題的 appBar 的屬性。我們定義了 body 屬性,這將存放 ListView 組件。
在上面代碼片段中,通過 map 方法返回每個元素的 TodoItem。
然后,在應(yīng)用的底部,我們定義了一個按鈕。當(dāng)按鈕被點擊時候,將調(diào)用 _displayDialog 方法。
到目前為止,我們還需要完成下面的代碼片段:
- 創(chuàng)建
TodoItem - 定義一個
_displayDialog函數(shù) - 定義一個
_handleTodoChange函數(shù)
讓我們一個一個來解決。
創(chuàng)建 TodoItem
TodoItem 是我們列表項的單獨體現(xiàn)。
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 掛件來展示內(nèi)容和添加點擊事件。
展示 Dialog 去添加列表項
點擊應(yīng)用的右下角的按鈕,將會調(diào)起 _displayDialog 方法。
這將調(diào)起一個帶有文本框的對話框。當(dāng)點擊確認(rèn)的時候,將以文本框的內(nèi)容基礎(chǔ)添加一個新的列表項。
在 _TodoListState 中創(chuàng)建 _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 表明在將來的某個時候?qū)⒎祷貪撛诘闹祷蛘咤e誤信息。在我們的案例中,將會返回用戶輸入的值。
對話框中有一個動作,就是當(dāng)我們點擊按鈕的時候,將會關(guān)閉對話框并且調(diào)用 _addTodoItem 函數(shù)。
我們看看 _addTodoItem 函數(shù)長什么樣:
void _addTodoItem(String name) {
setState(() {
_todos.add(Todo(name: name, checked: false));
});
_textFieldController.clear();
}
這函數(shù)比你想象中的簡單,是吧。
列表項添加狀態(tài)
最后一部分是,我們應(yīng)該為列表項進行標(biāo)記。我們需要一個處理函數(shù) _handleTodoChange:
void _handleTodoChange(Todo todo) {
setState(() {
todo.checked = !todo.checked;
});
}
這里我們只是改變了其列表項的狀態(tài)。
完整的代碼如下:
// 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開發(fā)Flutter構(gòu)建todo list應(yīng)用的詳細(xì)內(nèi)容,更多關(guān)于ios開發(fā)Flutter構(gòu)建todo list的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解iOS游戲開發(fā)中Cocos2D的坐標(biāo)位置關(guān)系
這篇文章主要介紹了iOS游戲開發(fā)中Cocos2D的坐標(biāo)位置關(guān)系,Cocos2D是專門用來開發(fā)iOS游戲的開源框架,文中示例代碼采用Objective-C語言,需要的朋友可以參考下2016-02-02
iOS利用UIBezierPath + CAAnimation實現(xiàn)路徑動畫效果
在iOS開發(fā)中,制作動畫效果是最讓開發(fā)者享受的環(huán)節(jié)之一,這篇文章主要給大家介紹了關(guān)于iOS利用UIBezierPath + CAAnimation實現(xiàn)路徑動畫效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10
xcode8 關(guān)閉控制臺不打印不信息的解決方法(圖文詳解)
這篇文章主要介紹了xcode8 關(guān)閉控制臺不打印信息的解決方法,本文圖文并茂給大家介紹的非常詳細(xì),感興趣的朋友參考下吧2016-10-10
詳解iOS開發(fā)中Keychain的相關(guān)使用
這篇文章主要介紹了iOS開發(fā)中Keychain的相關(guān)使用,文中列舉了一個使用Keychain來保存密碼的例子,需要的朋友可以參考下2015-10-10
實例解析iOS中音樂播放器應(yīng)用開發(fā)的基本要點
這篇文章主要介紹了iOS開發(fā)中制作一個簡單的音樂播放器的基本要點解析,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-01-01
iOS中利用CoreAnimation實現(xiàn)一個時間的進度條效果
在iOS中實現(xiàn)進度條通常都是通過不停的設(shè)置progress來完成的,這樣的進度條適用于網(wǎng)絡(luò)加載(上傳下載文件、圖片等)。下面通過本文給大家介紹iOS中利用CoreAnimation實現(xiàn)一個時間的進度條,需要的的朋友參考下吧2017-09-09

