当前位置:网站首页>一款Flutter版的记事本
一款Flutter版的记事本
2022-07-01 13:00:00 【xiangxiongfly915】
一款Flutter版的记事本

定义实体类
class NoteInfo {
final String name;
final String path;
final DateTime updateTime;
const NoteInfo(this.name, this.path, this.updateTime);
}
首页代码
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'EditNodePage.dart';
import 'FileUtils.dart';
import 'NoteInfo.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter日记本',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: '日记本'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<NoteInfo> noteList = [];
@override
void initState() {
loadNotes();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: noteList.isEmpty ? _buildEmpty() : _buildList(),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add, color: Colors.white),
backgroundColor: Colors.blue,
onPressed: () async {
var result = await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return const EditNodePage();
}));
loadNotes();
},
),
);
}
/// 空页面
_buildEmpty() {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.hourglass_empty_sharp,
color: Colors.black.withOpacity(0.6),
size: 40,
),
Text(
"空空如也,快来写日记",
style: TextStyle(color: Colors.black.withOpacity(0.6)),
),
],
),
);
}
_buildList() {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () async {
var result = await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return EditNodePage(path: noteList[index].path);
}));
loadNotes();
},
child: ListTile(
title: Text(noteList[index].name),
subtitle: Text("${noteList[index].updateTime}"),
),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(height: 1),
itemCount: noteList.length,
);
}
/// 加载日记
loadNotes() async {
var parentDir = await getTemporaryDirectory();
List<FileSystemEntity> dirList = parentDir.listSync(recursive: false);
List<FileSystemEntity> fileList = [];
for (var dir in dirList) {
if ((await dir.stat()).type == FileSystemEntityType.file) {
fileList.add(dir);
}
}
fileList.sort((f1, f2) {
try {
DateTime dateTime1 = File(f1.path).lastModifiedSync();
DateTime dateTime2 = File(f2.path).lastModifiedSync();
return dateTime2.microsecondsSinceEpoch - dateTime1.microsecondsSinceEpoch;
} catch (e) {
return 0;
}
});
noteList.clear();
for (var f in fileList) {
File file = File(f.path);
if (file.path.endsWith("txt")) {
noteList.add(NoteInfo(FileUtils.getFileName(file.path), file.path, file.lastModifiedSync()));
}
}
setState(() {});
}
}
编辑页代码
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'FileUtils.dart';
class EditNodePage extends StatefulWidget {
final String? path;
const EditNodePage({Key? key, this.path}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _EditNodePageState();
}
}
class _EditNodePageState extends State<EditNodePage> {
late TextEditingController _titleController;
late TextEditingController _contentController;
@override
void initState() {
_titleController = TextEditingController();
_contentController = TextEditingController();
loadData();
super.initState();
}
@override
void dispose() {
_titleController.dispose();
_contentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("编辑"),
actions: [
IconButton(onPressed: save, icon: const Icon(Icons.done)),
],
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: _titleController,
decoration: const InputDecoration(hintText: "请输入日记名称"),
),
Expanded(
child: TextField(
textAlignVertical: TextAlignVertical.top,
controller: _contentController,
decoration: const InputDecoration(hintText: "开始你的故事"),
maxLength: 2000,
maxLines: null,
minLines: 1,
keyboardType: TextInputType.multiline,
),
),
],
),
),
),
);
}
loadData() async {
if (widget.path != null) {
String fileName = FileUtils.getFileName(widget.path);
String content = const Utf8Decoder().convert(await File(widget.path!).readAsBytes());
setState(() {
_titleController.text = fileName;
_contentController.text = content;
});
}
}
save() async {
try {
String title = _titleController.text;
String content = _contentController.text;
var parentDir = await getTemporaryDirectory();
var file = File("${parentDir.path}/$title.txt");
bool exists = file.existsSync();
if (!exists) {
file.createSync();
}
file.writeAsStringSync(content);
Navigator.of(context).pop(title);
} on Exception catch (e) {
print(e);
}
}
}
代码下载
边栏推荐
- Asp. NETCORE uses dynamic to simplify database access
- I spent tens of thousands of dollars to learn and bring goods: I earned 3 yuan in three days, and the transaction depends on the bill
- [encounter Django] - (II) database configuration
- 工具箱之 IKVM.NET 项目新进展
- Meta enlarge again! VR new model posted on CVPR oral: read and understand voice like a human
- 腾讯总考epoll, 很烦
- Nc100 converts strings to integers (ATOI)
- Huawei HMS core joins hands with hypergraph to inject new momentum into 3D GIS
- Based on the open source stream batch integrated data synchronization engine Chunjun data restore DDL parsing module actual combat sharing
- Zabbix 6.0 源码安装以及 HA 配置
猜你喜欢

Meta再放大招!VR新模型登CVPR Oral:像人一样「读」懂语音
![[Niu Ke's questions -sql big factory interview real questions] no2 User growth scenario (a certain degree of information flow)](/img/a0/e9e7506c9c34986dc73562539c8410.png)
[Niu Ke's questions -sql big factory interview real questions] no2 User growth scenario (a certain degree of information flow)

Look at the sky at dawn and the clouds at dusk, and enjoy the beautiful pictures

【牛客刷题-SQL大厂面试真题】NO2.用户增长场景(某度信息流)

Feign & Eureka & zuul & hystrix process

MySQL statistical bill information (Part 2): data import and query

Professor Li Zexiang, Hong Kong University of science and technology: I'm wrong. Why is engineering consciousness more important than the best university?

Vs code set code auto save

Operator-1初识Operator

The popular major I chose became "Tiankeng" four years later
随机推荐
题目 2612: 蓝桥杯2021年第十二届省赛真题-最少砝码(枚举找规律+递推)
Fiori applications are shared through the enhancement of adaptation project
MySQL statistical bill information (Part 2): data import and query
[today in history] July 1: the father of time sharing system was born; Alipay launched barcode payment; The first TV advertisement in the world
Operator-1初识Operator
Run PowerShell script prompt "because running script is prohibited on this system" solution
79. 单词搜索【dfs + 回溯visit + 遍历起点】
Sharing with the best paper winner of CV Summit: how is a good paper refined?
Redis explores cache consistency
简单的两个圆球loading加载
MySQL gap lock
木架的场景功能
Feign & Eureka & Zuul & Hystrix 流程
There are still many things to be done in the second half of the year
Idea of [developing killer]
[Niu Ke's questions -sql big factory interview real questions] no2 User growth scenario (a certain degree of information flow)
华为HMS Core携手超图为三维GIS注入新动能
Meta再放大招!VR新模型登CVPR Oral:像人一样「读」懂语音
Three stages of aho
用.Net Core接入微信公众号开发