From d7a38d02a24dfce4b180f9c6959cd61894edc06f Mon Sep 17 00:00:00 2001 From: LollipopKit Date: Mon, 13 Sep 2021 16:06:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E5=89=B2=E4=B8=BA=E5=A4=9A=E4=B8=AAta?= =?UTF-8?q?b?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 1 - lib/page/convert.dart | 154 ++++++++++++++++++++++++++++++++++++++++++ lib/page/home.dart | 138 ++++++------------------------------- 3 files changed, 175 insertions(+), 118 deletions(-) create mode 100644 lib/page/convert.dart diff --git a/lib/main.dart b/lib/main.dart index 35ebece9..5e599cc0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -57,4 +57,3 @@ Future main() async { ); }); } - diff --git a/lib/page/convert.dart b/lib/page/convert.dart new file mode 100644 index 00000000..31303d3b --- /dev/null +++ b/lib/page/convert.dart @@ -0,0 +1,154 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; + +class EncodePage extends StatefulWidget { + const EncodePage({Key? key}) : super(key: key); + + @override + _EncodePageState createState() => _EncodePageState(); +} + +class _EncodePageState extends State + with AutomaticKeepAliveClientMixin { + late TextEditingController _textEditingController; + late TextEditingController _textEditingControllerResult; + late MediaQueryData _media; + late ThemeData _theme; + + static const List _typeOption = [ + 'base64 decode', + 'base64 encode', + 'URL encode', + 'URL decode' + ]; + int _typeOptionIndex = 0; + + @override + void initState() { + super.initState(); + _textEditingController = TextEditingController(); + _textEditingControllerResult = TextEditingController(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _media = MediaQuery.of(context); + _theme = Theme.of(context); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return Scaffold( + body: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 7), + child: AnimationLimiter( + child: Column( + children: AnimationConfiguration.toStaggeredList( + duration: const Duration(milliseconds: 377), + childAnimationBuilder: (widget) => SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: widget, + ), + ), + children: [ + const SizedBox(height: 13), + _buildInputTop(), + _buildTypeOption(), + _buildResult(), + ], + )))), + floatingActionButton: FloatingActionButton( + onPressed: () { + _textEditingControllerResult.text = doConvert(); + }, + tooltip: 'convert', + child: const Icon(Icons.send), + ), + ); + } + + String doConvert() { + final text = _textEditingController.text; + switch (_typeOptionIndex) { + case 0: + return utf8.decode(base64.decode(text)); + case 1: + return base64.encode(utf8.encode(text)); + case 2: + return Uri.encodeFull(text); + case 3: + return Uri.decodeFull(text); + default: + return '未知编码'; + } + } + + Widget _buildInputTop() { + return SizedBox( + height: _media.size.height * 0.33, + child: _buildInput(_textEditingController), + ); + } + + Widget _buildTypeOption() { + return Card( + child: ExpansionTile( + title: Text( + _typeOption[_typeOptionIndex], + style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500), + ), + children: _typeOption + .map((e) => ListTile( + title: Text( + e, + style: TextStyle( + color: + _theme.textTheme.bodyText2!.color!.withAlpha(177)), + ), + trailing: _buildRadio(_typeOption.indexOf(e)), + )) + .toList(), + ), + ); + } + + Widget _buildResult() { + return SizedBox( + height: _media.size.height * 0.33, + child: _buildInput(_textEditingControllerResult), + ); + } + + Widget _buildInput(TextEditingController controller) { + return Card( + child: TextField( + maxLines: 20, + decoration: InputDecoration( + fillColor: Theme.of(context).cardColor, + filled: true, + border: InputBorder.none), + controller: controller, + ), + ); + } + + Radio _buildRadio(int index) { + return Radio( + value: index, + groupValue: _typeOptionIndex, + onChanged: (int? value) { + setState(() { + _typeOptionIndex = value!; + }); + }, + ); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/page/home.dart b/lib/page/home.dart index 4a88b566..5eda0e25 100644 --- a/lib/page/home.dart +++ b/lib/page/home.dart @@ -1,7 +1,6 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:toolbox/core/route.dart'; +import 'package:toolbox/page/convert.dart'; import 'package:toolbox/page/debug.dart'; class MyHomePage extends StatefulWidget { @@ -12,137 +11,42 @@ class MyHomePage extends StatefulWidget { State createState() => _MyHomePageState(); } -class _MyHomePageState extends State { - late TextEditingController _textEditingController; - late TextEditingController _textEditingControllerResult; - late MediaQueryData _media; - late ThemeData _theme; - - static const List _typeOption = [ - 'base64 decode', - 'base64 encode', - 'URL encode', - 'URL decode' - ]; - int _typeOptionIndex = 0; +class _MyHomePageState extends State + with AutomaticKeepAliveClientMixin, SingleTickerProviderStateMixin { + final List _tabs = ['编码', 'Ping', '1', '2', '3']; + late final TabController _tabController; @override void initState() { super.initState(); - _textEditingController = TextEditingController(); - _textEditingControllerResult = TextEditingController(); - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _media = MediaQuery.of(context); - _theme = Theme.of(context); + _tabController = TabController(length: _tabs.length, vsync: this); } @override Widget build(BuildContext context) { + super.build(context); return Scaffold( appBar: AppBar( title: GestureDetector( - onLongPress: () => AppRoute(const DebugPage(), 'Debug Page').go(context), + onLongPress: () => + AppRoute(const DebugPage(), 'Debug Page').go(context), child: Text(widget.title), ), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 7), - child: Column( - children: [ - const SizedBox(height: 13), - _buildInputTop(), - _buildTypeOption(), - _buildResult(), - ], - )), - floatingActionButton: FloatingActionButton( - onPressed: () { - _textEditingControllerResult.text = doConvert(); - }, - tooltip: 'convert', - child: const Icon(Icons.send), - ), - ); - } - - String doConvert() { - final text = _textEditingController.text; - switch (_typeOptionIndex) { - case 0: - return utf8.decode(base64.decode(text)); - case 1: - return base64.encode(utf8.encode(text)); - case 2: - return Uri.encodeFull(text); - case 3: - return Uri.decodeFull(text); - default: - return '未知编码'; - } - } - - Widget _buildInputTop() { - return SizedBox( - height: _media.size.height * 0.33, - child: _buildInput(_textEditingController), - ); - } - - Widget _buildTypeOption() { - return Card( - child: ExpansionTile( - title: Text( - _typeOption[_typeOptionIndex], - style: const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500), + bottom: TabBar( + tabs: _tabs.map((e) => Tab(text: e)).toList(), + controller: _tabController, ), - children: _typeOption - .map((e) => ListTile( - title: Text( - e, - style: TextStyle( - color: - _theme.textTheme.bodyText2!.color!.withAlpha(177)), - ), - trailing: _buildRadio(_typeOption.indexOf(e)), - )) - .toList(), ), + body: TabBarView(controller: _tabController, children: const [ + EncodePage(), + EncodePage(), + EncodePage(), + EncodePage(), + EncodePage() + ]), ); } - Widget _buildResult() { - return SizedBox( - height: _media.size.height * 0.33, - child: _buildInput(_textEditingControllerResult), - ); - } - - Widget _buildInput(TextEditingController controller) { - return Card( - child: TextField( - maxLines: 20, - decoration: InputDecoration( - fillColor: Theme.of(context).cardColor, - filled: true, - border: InputBorder.none), - controller: controller, - ), - ); - } - - Radio _buildRadio(int index) { - return Radio( - value: index, - groupValue: _typeOptionIndex, - onChanged: (int? value) { - setState(() { - _typeOptionIndex = value!; - }); - }, - ); - } + @override + bool get wantKeepAlive => true; }