Flutter自动存储输入内容插件self_storing_input的使用
Flutter 自动存储输入内容插件 self_storing_input 的使用
概述
self_storing_input
是一组自动保存和加载输入值到数据存储中的输入小部件。
示例演示
使用方法
定义 Saver
首先,实现一个 Saver
,用于加载、验证和保存数据项。itemKey
可以是任何形式,例如资源 URL 字符串或连接字符串、表、对象 ID 和列的元组。
示例代码:
class _DemoSaver with ChangeNotifier implements Saver<String> {
Map<String, dynamic> storage = {};
bool failSaving = false;
Duration delay = const Duration(milliseconds: 100);
[@override](/user/override)
Future<T> load<T>(String itemKey) async {
// 这个延迟是为了演示目的。
await Future.delayed(delay);
return storage[itemKey];
}
[@override](/user/override)
OperationResult validate<T>(String itemKey, T value) {
if (itemKey == Fields.phrase && (value?.toString()?.length ?? 0) % 2 == 1) {
return OperationResult.error('Value should have even number of letters.');
}
return OperationResult.success();
}
[@override](/user/override)
Future<OperationResult> save<T>(String itemKey, T value) async {
// 这个延迟是为了演示目的。
await Future.delayed(delay);
if (failSaving) {
return OperationResult.error('Failed to save the value, for demo purposes.');
}
storage[itemKey] = value;
notifyListeners();
return OperationResult.success();
}
}
定义输入小部件
将 self_storing_input
小部件添加到屏幕,并用定义的 Saver
和 itemKey
参数化每个小部件。这些小部件会处理加载数据、验证数据、保存数据以及处理诸如网络连接差和数据存储失败等故障模式。
关闭覆盖层
在屏幕状态中定义一个 OverlayController
:
OverlayController _controller = OverlayController();
将屏幕小部件主体包装在一个 GestureDetector
中,以便在点击时关闭编辑覆盖层:
GestureDetector(
onTap: () async {
_controller.close();
},
child: Scaffold(
body: ...
将 _controller
传递给每个 self_storing
小部件:
SelfStoringText(
overlayController: _controller,
...
完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:self_storing_input/self_storing_input.dart';
import 'package:url_launcher/url_launcher.dart';
class Fields {
static const String phrase = 'phrase';
static const String paragraph = 'paragraph';
static const String tristate = 'tristate';
static const String twostate = 'twostate';
static const String unselectableRadioGroup = 'unselectableRadioGroup';
static const String radioGroup = 'radioGroup';
}
class _DemoSaver with ChangeNotifier implements Saver<String> {
Map<String, dynamic> storage = {};
bool failSaving = false;
Duration delay = const Duration(milliseconds: 100);
[@override](/user/override)
Future<T> load<T>(String itemKey) async {
await Future.delayed(delay);
return storage[itemKey];
}
[@override](/user/override)
OperationResult validate<T>(String itemKey, T value) {
if (itemKey == Fields.phrase && (value?.toString()?.length ?? 0) % 2 == 1) {
return OperationResult.error('Value should have even number of letters.');
}
return OperationResult.success();
}
[@override](/user/override)
Future<OperationResult> save<T>(String itemKey, T value) async {
await Future.delayed(delay);
if (failSaving) {
return OperationResult.error('Failed to save the value, for demo purposes.');
}
storage[itemKey] = value;
notifyListeners();
return OperationResult.success();
}
}
void main() {
runApp(Demo());
}
class Demo extends StatefulWidget {
[@override](/user/override)
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
OverlayController _controller = OverlayController();
final _DemoSaver _saver = _DemoSaver();
[@override](/user/override)
void initState() {
_saver.addListener(() => setState(() {}));
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: GestureDetector(
onTap: () async {
_controller.close();
},
child: Scaffold(
body: SingleChildScrollView(
child: ListTileTheme(
contentPadding: EdgeInsets.all(0),
child: Padding(
padding: EdgeInsets.all(40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_section('SELF_STORING_INPUT\nDEMO', buildDemoHeader()),
_section('Demo Parameters', buildDemoParameters()),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_section('Self Storing Input Widgets', buildDemo()),
if (_saver.storage.isNotEmpty)
_section('Storage Content', buildStorageObserver()),
],
)
],
),
),
),
),
),
),
);
}
static Widget _right(List<Widget> widgets) {
return Padding(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: widgets),
padding: EdgeInsets.only(left: 20),
);
}
Widget _section(String header, List<Widget> children) {
return Container(
width: 400,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
header,
style: TextStyle(color: Theme.of(context).accentColor, fontSize: 20),
),
SizedBox(height: 20),
_right(children),
SizedBox(height: 40),
],
),
);
}
List<Widget> buildDemoHeader() {
return [
TextButton(
onPressed: () async => await launch('https://github.com/google/flutter.widgets/tree/master/packages/self_storing_input/example'),
child: Text(
'Source Code',
style: TextStyle(
color: Theme.of(context).accentColor,
decoration: TextDecoration.underline,
),
),
),
];
}
List<Widget> buildDemoParameters() {
return [
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
title: Text('Fail the save operation'),
value: _saver.failSaving,
onChanged: (v) => setState(() => _saver.failSaving = v),
),
SizedBox(height: 10),
TextFormField(
onChanged: (v) => setState(() => _saver.delay = Duration(milliseconds: int.parse(v))),
initialValue: _saver.delay.inMilliseconds.toString(),
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Delay time for the save operation, ms'),
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
)
];
}
List<Widget> buildDemo() {
return [
Text('${Fields.phrase}:'),
SelfStoringText(
Fields.phrase,
overlayController: _controller,
saver: _saver,
),
SizedBox(height: 20),
Text('${Fields.paragraph}:'),
SelfStoringText(
Fields.paragraph,
overlayController: _controller,
saver: _saver,
style: SelfStoringTextStyle(
overlayStyle: OverlayStyle.forTextEditor(height: 130),
keyboardType: TextInputType.multiline,
maxLines: null,
),
),
SizedBox(height: 20),
Text('checkboxes:'),
SelfStoringCheckbox(
Fields.tristate,
saver: _saver,
overlayController: _controller,
title: Text(Fields.tristate),
),
SizedBox(height: 20),
SelfStoringCheckbox(
Fields.twostate,
saver: _saver,
overlayController: _controller,
title: Text(Fields.twostate),
tristate: false,
),
SizedBox(height: 40),
Text('${Fields.unselectableRadioGroup}:'),
SelfStoringRadioGroup(
Fields.unselectableRadioGroup,
saver: _saver,
isUnselectable: true,
overlayController: _controller,
items: {1: 'One', 2: 'Two', 3: 'Three'},
),
SizedBox(height: 40),
Text('${Fields.radioGroup}:'),
SelfStoringRadioGroup(
Fields.radioGroup,
saver: _saver,
overlayController: _controller,
items: {1: 'One', 2: 'Two', 3: 'Three'},
),
];
}
List<Widget> buildStorageObserver() {
return [
for (var id in _saver.storage.keys) Text('$id: ${_saver.storage[id]}'),
];
}
}
更多关于Flutter自动存储输入内容插件self_storing_input的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自动存储输入内容插件self_storing_input的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
self_storing_input
是一个用于 Flutter 的插件,它允许你自动存储用户在输入框中的内容。这样,即使用户关闭或刷新应用程序,他们之前的输入内容也会被保留,并且在下次打开应用程序时自动恢复。
安装插件
首先,你需要在 pubspec.yaml
文件中添加 self_storing_input
插件的依赖:
dependencies:
flutter:
sdk: flutter
self_storing_input: ^0.1.0 # 请确保使用最新版本
然后,运行 flutter pub get
来获取依赖。
使用插件
-
导入插件:
在你的 Dart 文件中导入
self_storing_input
插件:import 'package:self_storing_input/self_storing_input.dart';
-
创建 SelfStoringInput 字段:
使用
SelfStoringInput
替代普通的TextField
或TextFormField
,并为其指定一个唯一的storageKey
。这个键用于在本地存储中唯一标识输入内容。SelfStoringInput( storageKey: 'username', // 唯一的存储键 decoration: InputDecoration(labelText: '用户名'), ),
你可以像使用普通的
TextField
一样使用SelfStoringInput
,并且它的值会在应用关闭后自动保存和恢复。 -
示例代码:
以下是一个完整的示例,展示了如何在 Flutter 应用中使用
self_storing_input
:import 'package:flutter/material.dart'; import 'package:self_storing_input/self_storing_input.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Self Storing Input Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: SelfStoringInputDemo(), ); } } class SelfStoringInputDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Self Storing Input Demo'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ SelfStoringInput( storageKey: 'username', decoration: InputDecoration(labelText: '用户名'), ), SizedBox(height: 20), SelfStoringInput( storageKey: 'email', decoration: InputDecoration(labelText: '电子邮件'), ), ], ), ), ); } }