diff --git a/lib/base/common_dialog.dart b/lib/base/common_dialog.dart index 12dc515..2bcd3d3 100644 --- a/lib/base/common_dialog.dart +++ b/lib/base/common_dialog.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:back_button_interceptor/back_button_interceptor.dart'; @@ -28,23 +27,23 @@ class CommonDialog extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Container( - margin: EdgeInsets.only(top: 15.0), + margin: const EdgeInsets.only(top: 15.0), constraints: BoxConstraints( minHeight: 40, ), child: IconTheme( - data: IconThemeData( + data: const IconThemeData( color: Colors.white, size: 40.0, ), child: LoadingIcon()), ), - SizedBox( + const SizedBox( height: 15, ), if (text != null) Padding( - padding: EdgeInsets.only( + padding: const EdgeInsets.only( left: 15, right: 15, bottom: 15, @@ -53,7 +52,7 @@ class CommonDialog extends StatelessWidget { textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, - style: TextStyle(color: Colors.white, fontSize: 14), + style: const TextStyle(color: Colors.white, fontSize: 14), child: Text(text!), ), ), @@ -83,7 +82,7 @@ class LoadingIconState extends State with SingleTickerProviderState @override void initState() { super.initState(); - _controller = new AnimationController(vsync: this, duration: Duration(milliseconds: 1000))..repeat(); + _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 1000))..repeat(); _doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller!) ..addListener(() { setState(() {}); @@ -113,12 +112,14 @@ typedef HideCallback = Future Function(); int backButtonIndex = 2; +OverlayEntry? overlay; + HideCallback showCommonDialog( - BuildContext context, { - String? text, - bool backButtonClose = false, - CommonDialogState commonDialogState = CommonDialogState.LOADING, - }) { + BuildContext context, { + String? text, + bool backButtonClose = false, + CommonDialogState commonDialogState = CommonDialogState.LOADING, +}) { Completer result = Completer(); var backButtonName = 'QL_Toast$backButtonIndex'; BackButtonInterceptor.add((stopDefaultButtonEvent, _) { @@ -131,7 +132,11 @@ HideCallback showCommonDialog( }, zIndex: backButtonIndex, name: backButtonName); backButtonIndex++; - var overlay = OverlayEntry( + if (overlay != null) { + overlay?.remove(); + overlay = null; + } + overlay = OverlayEntry( maintainState: true, builder: (_) => WillPopScope( onWillPop: () async { @@ -145,10 +150,12 @@ HideCallback showCommonDialog( ), ); result.complete(() { - overlay.remove(); + overlay?.remove(); BackButtonInterceptor.removeByName(backButtonName); }); - Overlay.of(context)?.insert(overlay); + if (overlay != null) { + Overlay.of(context)?.insert(overlay!); + } return () async { var hide = await result.future; @@ -193,4 +200,4 @@ HideCallback loadingDialog(BuildContext context, {String? text}) { commonDialogState: CommonDialogState.LOADING, backButtonClose: true, ); -} \ No newline at end of file +} diff --git a/lib/base/theme.dart b/lib/base/theme.dart index d96bc51..0531b7d 100644 --- a/lib/base/theme.dart +++ b/lib/base/theme.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; diff --git a/lib/main.dart b/lib/main.dart index bfcf0c3..d072c4c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,7 +33,7 @@ class MyApp extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return GestureDetector( behavior: HitTestBehavior.opaque, - onTap: (){ + onTap: () { FocusScope.of(context).requestFocus(FocusNode()); }, child: MaterialApp( @@ -41,7 +41,8 @@ class MyApp extends ConsumerWidget { onGenerateRoute: (setting) { return Routes.generateRoute(setting); }, - home: ref.read(userInfoProvider).userInfoBean != null ? const HomePage() : LoginPage(), + // home: ref.read(userInfoProvider).userInfoBean != null ? const HomePage() : LoginPage(), + home: HomePage(), ), ); } diff --git a/lib/module/home/home_page.dart b/lib/module/home/home_page.dart index c81dc21..aa9fcc7 100644 --- a/lib/module/home/home_page.dart +++ b/lib/module/home/home_page.dart @@ -40,7 +40,7 @@ class _HomePageState extends State { onTap: () { ref.read(themeProvider).changeTheme(); }, - child: Center(child: Text("改变主题")), + child: const Center(child: Text("改变主题")), ); }), ], diff --git a/lib/module/login/login_page.dart b/lib/module/login/login_page.dart index c04899b..082db33 100644 --- a/lib/module/login/login_page.dart +++ b/lib/module/login/login_page.dart @@ -16,7 +16,6 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State { final TextEditingController _userNameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); - HideCallback? _hideCallback; @override Widget build(BuildContext context) { @@ -24,21 +23,9 @@ class _LoginPageState extends State { body: Consumer(builder: (context, ref, child) { var model = ref.watch(loginProvider); - if (model.isLoading) { - WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { - _hideCallback ??= loadingDialog(context, text: "登录中..."); - }); - } else { - if (_hideCallback != null) { - WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { - _hideCallback!(); - }); - } - } - if (model.loginSuccess) { WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { - Navigator.of(context).pushNamed(Routes.route_HomePage); + Navigator.of(context).popAndPushNamed(Routes.route_HomePage); }); } return SizedBox( @@ -130,16 +117,19 @@ class _LoginPageState extends State { SizedBox( width: MediaQuery.of(context).size.width - 30, child: CupertinoButton( - color: (_userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty) + color: (_userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty && !model.isLoading) ? Theme.of(context).primaryColor : Theme.of(context).primaryColor.withOpacity(0.3), - child: const Text( - "登录", - style: TextStyle( - fontSize: 16, - ), - ), + child: model.isLoading + ? const CupertinoActivityIndicator() + : const Text( + "登录", + style: TextStyle( + fontSize: 16, + ), + ), onPressed: () { + if (model.isLoading) return; Utils.hideKeyBoard(context); model.login(_userNameController.text, _passwordController.text); }), diff --git a/lib/module/task/task_page.dart b/lib/module/task/task_page.dart index 7db28a6..2e1faa1 100644 --- a/lib/module/task/task_page.dart +++ b/lib/module/task/task_page.dart @@ -1,5 +1,7 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:qinglong_app/base/base_state_widget.dart'; import 'package:qinglong_app/module/task/task_viewmodel.dart'; @@ -15,13 +17,24 @@ class _TaskPageState extends State { Widget build(BuildContext context) { return BaseStateWidget( builder: (context, model, child) { - return ListView.builder( - itemBuilder: (context, index) { - return ListTile( - title: Text(model.list[index]), - ); + return RefreshIndicator( + onRefresh: () async { + return Future.delayed(Duration(seconds: 1), () {}); }, - itemCount: model.list.length, + child: ListView.separated( + padding: EdgeInsets.symmetric( + vertical: 15, + ), + itemBuilder: (context, index) { + return TaskItemCell(); + }, + itemCount: model.list.length, + separatorBuilder: (BuildContext context, int index) { + return SizedBox( + height: 10, + ); + }, + ), ); }, model: taskProvider, @@ -31,3 +44,94 @@ class _TaskPageState extends State { ); } } + +class TaskItemCell extends StatelessWidget { + const TaskItemCell({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Slidable( + key: const ValueKey(0), + startActionPane: ActionPane( + motion: const ScrollMotion(), + extentRatio: 0.3, + dragDismissible: false, + children: [ + SlidableAction( + flex: 1, + icon: CupertinoIcons.memories, + foregroundColor: Colors.white, + backgroundColor: Color(0xFF0F77FE), + onPressed: (BuildContext context) {}, + ), + SlidableAction( + flex: 1, + backgroundColor: Colors.green, + foregroundColor: Colors.white, + icon: CupertinoIcons.clock_fill, + onPressed: (BuildContext context) {}, + ), + ], + ), + endActionPane: ActionPane( + motion: ScrollMotion(), + extentRatio: 0.15, + children: [ + SlidableAction( + backgroundColor: Colors.cyan, + flex: 1, + onPressed: (_) {}, + foregroundColor: Colors.white, + icon: CupertinoIcons.ellipsis, + ), + ], + ), + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 15, + vertical: 5, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: const [ + Text( + "东东农场", + style: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 18, + ), + ), + SizedBox( + width: 5, + ), + SizedBox( + width: 15, + height: 15, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + ), + Spacer(), + Text("2020/12/12 12:23"), + ], + ), + const SizedBox( + height: 5, + ), + const Text( + "12/12/12", + style: TextStyle( + fontSize: 12, + ), + ), + ], + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index bbedd48..cda6fb8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -97,6 +97,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.3" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 9e8b6f7..06027ad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: shared_preferences: ^2.0.12 synchronized: ^3.0.0 back_button_interceptor: ^5.0.2 + flutter_slidable: ^1.2.0 dev_dependencies: flutter_test: