军警魂 發表於 2022-9-27 17:18:40

ios开发Flutter构建todo list应用

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>正文</li><ul class="second_class_ul"><li>基础 Flutter 应用脚手架</li><li>创建 TodoItem</li><li>展示 Dialog 去添加列表项</li><li>列表项添加状态</li></ul></ul></div><p class="maodian"></p><h2>正文</h2>
<p>今天,我们将使用 <code>Flutter</code> 构建一个动态的 <code>todo list</code> 的应用。</p>
<p>开发完成的效果如下:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202209/20220927095656049.gif" /></p>
<p>我们直接进入正题。</p>
<p class="maodian"></p><h3>基础 Flutter 应用脚手架</h3>
<div class="jb51code"><pre class="brush:bash;"># create new project
flutter create flutter_todo_app
# navigate to project
cd flutter_todo_app
# run flutter
flutter run
</pre></div>
<p>我们清除文件 <code>lib/main.dart</code>,从头开始开发。</p>
<p>main.dart 这个文件是 Flutter 应用的入口文件。在这篇文章中,我将仅仅使用这个文件来开发。</p>
<p>首先,我们先导入 <code>material</code> 包。</p>
<div class="jb51code"><pre class="brush:java;">import 'package:flutter/material.dart';
</pre></div>
<p>下一步,我们得有一个主要的方法。在这个例子中,它将返回 <code>TodoApp</code> 实例。</p>
<div class="jb51code"><pre class="brush:java;">void main() =&gt; runApp(
new TodoApp(),
);
</pre></div>
<p>这个 <code>TodoApp</code> 应该是一个 <code>statelessWidget</code>。这将会是我们列表的骨架</p>
<div class="jb51code"><pre class="brush:java;">class TodoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Todo list',
      home: new TodoList(),
    );
}
}
</pre></div>
<p>正如你所见,我返回了一个 <code>MaterialApp</code> 实例,它具有一个 <code>title</code> 属性和一个 <code>home</code> 功能。这个 <code>home</code> 函数返回一个 <code>TodoList</code> 实例。这个 <code>TodoList</code> 类才是我们控制的列表项。</p>
<div class="jb51code"><pre class="brush:java;">class TodoList extends StatefulWidget {
@override
_TodoListState createState() =&gt; new _TodoListState();
}
</pre></div>
<p>等等,这是什么?所有的挂件都会调用一个状态去知道将要发生什么和渲染什么。在这个例子中,我们调用了 <code>_TodoListState</code>。这将包含应用中的列表及其运行逻辑。</p>
<div class="jb51code"><pre class="brush:java;">class _TodoListState extends State&lt;TodoList&gt; {
final TextEditingController _textFieldController = TextEditingController();
final List&lt;Todo&gt; _todos = &lt;Todo&gt;[];
@override
Widget build(BuildContext context) {
          // Widget template comes here
}
// Other functions
}
</pre></div>
<p>接下来,创建列表变量。</p>
<div class="jb51code"><pre class="brush:java;">final List&lt;Todo&gt; _todos = &lt;Todo&gt;[];
</pre></div>
<p>也许你已经注意到了,我们定义了这个列表的类型是 <code>Todo</code>,但 <code>Flutter</code> 怎么知道 <code>Todo</code> 长是什么样呢?</p>
<p><code>Flutter</code> 并不会知道,所以我们得创建一个类来定义。如下:</p>
<div class="jb51code"><pre class="brush:java;">class Todo {
Todo({required this.name, required this.checked});
final String name;
bool checked;
}
</pre></div>
<p>这跟 <code>typescript</code> 中的类型定义很像。我们告诉 <code>flutter</code> 一个 todo 项应该包含什么,什么字段是必须的。在我们的案例中,我们有名字和 <code>checked</code> 两个状态属性。</p>
<p>回到 <code>_TodoListState</code> 中,我们开始让我们的挂件展示点东西。</p>
<div class="jb51code"><pre class="brush:java;">@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: () =&gt; _displayDialog(),
              tooltip: 'Add Item',
              child: Icon(Icons.add)),
        );
}
</pre></div>
<p>让我们看看上面发生了什么。我们返回了应用的一个脚手架,在脚手架上,我们添加了一个包含标题的 <code>appBar</code> 的属性。我们定义了 <code>body</code> 属性,这将存放 <code>ListView</code> 组件。</p>
<p>在上面代码片段中,通过 <code>map</code> 方法返回每个元素的 <code>TodoItem</code>。</p>
<p>然后,在应用的底部,我们定义了一个按钮。当按钮被点击时候,将调用 <code>_displayDialog</code> 方法。</p>
<p>到目前为止,我们还需要完成下面的代码片段:</p>
<ul><li>创建 <code>TodoItem</code></li><li>定义一个 <code>_displayDialog</code> 函数</li><li>定义一个 <code>_handleTodoChange</code> 函数</li></ul>
<p>让我们一个一个来解决。</p>
<p class="maodian"></p><h3>创建 TodoItem</h3>
<p><code>TodoItem</code> 是我们列表项的单独体现。</p>
<div class="jb51code"><pre class="brush:java;">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),
      ),
      title: Text(todo.name, style: _getTextStyle(todo.checked)),
    );
}
}
</pre></div>
<p>正如你所见,我们传递一个 <code>todo</code> 和 <code>onTodoChanged</code> 进来。</p>
<p>然后我们定义了一个 <code>TextStyle</code> 去处理列表项是否被勾选。</p>
<p>然后我们使用 <code>ListTile</code> 挂件来展示内容和添加点击事件。</p>
<p class="maodian"></p><h3>展示 Dialog 去添加列表项</h3>
<p>点击应用的右下角的按钮,将会调起 <code>_displayDialog</code> 方法。</p>
<p>这将调起一个带有文本框的对话框。当点击确认的时候,将以文本框的内容基础添加一个新的列表项。</p>
<p>在 <code>_TodoListState</code> 中创建 <code>_displayDialog</code>。</p>
<div class="jb51code"><pre class="brush:java;">Future&lt;void&gt; _displayDialog() async {
        return showDialog&lt;void&gt;(
          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: &lt;Widget&gt;[
                TextButton(
                child: const Text('Add'),
                onPressed: () {
                    Navigator.of(context).pop();
                    _addTodoItem(_textFieldController.text);
                },
                ),
              ],
          );
          },
        );
}
</pre></div>
<p><code>Flutter</code> 中的 <code>Future</code> 表明在将来的某个时候将返回潜在的值或者错误信息。在我们的案例中,将会返回用户输入的值。</p>
<p>对话框中有一个动作,就是当我们点击按钮的时候,将会关闭对话框并且调用 <code>_addTodoItem</code> 函数。</p>
<p>我们看看 <code>_addTodoItem</code> 函数长什么样:</p>
<div class="jb51code"><pre class="brush:java;">void _addTodoItem(String name) {
        setState(() {
          _todos.add(Todo(name: name, checked: false));
        });
        _textFieldController.clear();
}
</pre></div>
<p>这函数比你想象中的简单,是吧。</p>
<p class="maodian"></p><h3>列表项添加状态</h3>
<p>最后一部分是,我们应该为列表项进行标记。我们需要一个处理函数 <code>_handleTodoChange</code>:</p>
<div class="jb51code"><pre class="brush:java;">void _handleTodoChange(Todo todo) {
        setState(() {
          todo.checked = !todo.checked;
        });
}
</pre></div>
<p>这里我们只是改变了其列表项的状态。</p>
<p>完整的代码如下:</p>
<div class="jb51code"><pre class="brush:java;">// 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),
      ),
      title: Text(todo.name, style: _getTextStyle(todo.checked)),
    );
}
}
class TodoList extends StatefulWidget {
@override
_TodoListState createState() =&gt; new _TodoListState();
}
class _TodoListState extends State&lt;TodoList&gt; {
final TextEditingController _textFieldController = TextEditingController();
final List&lt;Todo&gt; _todos = &lt;Todo&gt;[];
@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: () =&gt; _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&lt;void&gt; _displayDialog() async {
    return showDialog&lt;void&gt;(
      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: &lt;Widget&gt;[
            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() =&gt; runApp(new TodoApp());
</pre></div>
<p>本文采用的是意译的方式。原文链接 - Build a todo list app with Flutter</p>
<p>以上就是ios开发Flutter构建todo list应用的详细内容,更多关于ios开发Flutter构建todo list的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Flutter Module添加到iOS项目示例详解</li><li>Flutter&nbsp;iOS开发OC混编Swift动态库和静态库问题填坑</li><li>ios开发Flutter之数据存储</li><li>Flutter项目在 iOS14 启动崩溃的解决方法</li><li>Flutter集成到已有iOS工程的方法步骤</li><li>Flutter调用Android和iOS原生代码的方法示例</li><li>iOS 项目嵌入Flutter 运行(最新推荐)</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: ios开发Flutter构建todo list应用