当前位置:网站首页>一款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);
}
}
}
代码下载
边栏推荐
- Which securities company has a low, safe and reliable account opening commission
- 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能
- Wang Xing's infinite game ushers in the "ultimate" battle
- 波浪动画彩色五角星loader加载js特效
- 【邂逅Django】——(二)数据库配置
- [encounter Django] - (II) database configuration
- MySQL报错1040Too many connections的原因以及解决方案
- 彩色五角星SVG动态网页背景js特效
- 用.Net Core接入微信公众号开发
- 游戏公会在去中心化游戏中的未来
猜你喜欢

VM虚拟机配置动态ip和静态ip访问

波浪动画彩色五角星loader加载js特效

我花上万学带货:3天赚3元,成交靠刷单

Meta再放大招!VR新模型登CVPR Oral:像人一样「读」懂语音

CS5268优势替代AG9321MCQ Typec多合一扩展坞方案

JS变色的乐高积木

王兴的无限游戏迎来“终极”一战

leetcode:226. 翻转二叉树【dfs翻转】

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

Ikvm of toolbox Net project new progress
随机推荐
工具箱之 IKVM.NET 项目新进展
Run PowerShell script prompt "because running script is prohibited on this system" solution
There are risks in trading
Sharing with the best paper winner of CV Summit: how is a good paper refined?
软件测试中功能测试流程
R language uses conf of yardstick package_ The mat function calculates the confusion matrix of the multiclass model on each fold of each cross validation (or resampling), and uses the summary to outpu
79. Word search [DFS + backtracking visit + traversal starting point]
Function test process in software testing
不同的测试技术区分
Three questions about scientific entrepreneurship: timing, pain points and important decisions
Hardware development notes (9): basic process of hardware development, making a USB to RS232 module (8): create asm1117-3.3v package library and associate principle graphic devices
R语言使用yardstick包的conf_mat函数计算多分类(Multiclass)模型在每个交叉验证(或者重采样)的每一折fold上的混淆矩阵、并使用summary输出每个fold的其它详细指标
Shell script imports stored procedures into the database
香港科技大学李泽湘教授:我错了,为什么工程意识比上最好的大学都重要?
ROS2 Foxy depthai_ ROS tutorial
基于mysql乐观锁实现秒杀的示例代码
Logstash error: cannot reload pipeline, because the existing pipeline is not reloadable
leetcode:241. 为运算表达式设计优先级【dfs + eval】
商汤科技崩盘 :IPO时已写好的剧本
Tencent always takes epoll, which is annoying