diff --git a/lib/constants/api.dart b/lib/constants/api.dart index 832a945b..fcf0259c 100644 --- a/lib/constants/api.dart +++ b/lib/constants/api.dart @@ -102,6 +102,9 @@ class _Manager { ///建议评价 String get adviceEvaluate => '/user/advice/evaluate'; + + ///删除建议 + String get deleteAdvice => '/user/advice/falseDelete'; } class _Upload { diff --git a/lib/ui/manager/advice/advice_page.dart b/lib/ui/manager/advice/advice_page.dart index a9c0b07f..23028ef1 100644 --- a/lib/ui/manager/advice/advice_page.dart +++ b/lib/ui/manager/advice/advice_page.dart @@ -3,9 +3,13 @@ import 'package:akuCommunity/model/manager/suggestion_or_complain_model.dart'; import 'package:akuCommunity/pages/things_page/widget/bee_list_view.dart'; import 'package:akuCommunity/ui/manager/advice/advice_card.dart'; import 'package:akuCommunity/ui/manager/advice/new_advice_page.dart'; +import 'package:akuCommunity/utils/network/base_model.dart'; +import 'package:akuCommunity/utils/network/net_util.dart'; +import 'package:akuCommunity/widget/animated/animated_transition.dart'; import 'package:akuCommunity/widget/bee_scaffold.dart'; import 'package:akuCommunity/utils/headers.dart'; import 'package:akuCommunity/widget/buttons/bottom_button.dart'; +import 'package:akuCommunity/widget/buttons/radio_button.dart'; import 'package:akuCommunity/widget/tab_bar/bee_tab_bar.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -29,6 +33,9 @@ class AdvicePage extends StatefulWidget { class _AdvicePageState extends State with TickerProviderStateMixin { EasyRefreshController _refreshController = EasyRefreshController(); TabController _tabController; + bool _selectedMode = false; + + List _selectedItems = []; String get title { switch (widget.type) { @@ -82,9 +89,18 @@ class _AdvicePageState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return BeeScaffold( title: title, + actions: [ + FlatButton( + onPressed: () => setState(() => _selectedMode = !_selectedMode), + child: (_selectedMode ? '完成' : '编辑').text.make(), + ), + ], appBarBottom: BeeTabBar( controller: _tabController, tabs: tabs, + onTap: (index) { + _selectedItems.clear(); + }, ), body: TabBarView( controller: _tabController, @@ -100,7 +116,37 @@ class _AdvicePageState extends State with TickerProviderStateMixin { return ListView.separated( padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 20.w), itemBuilder: (context, index) { - return AdviceCard(model: items[index]); + return Stack( + children: [ + Positioned( + left: 0, + top: 0, + bottom: 0, + child: GestureDetector( + onTap: () { + setState(() { + if (_selectedItems.contains(items[index].id)) + _selectedItems.remove(items[index].id); + else + _selectedItems.add(items[index].id); + }); + }, + child: Container( + color: Colors.transparent, + alignment: Alignment.topLeft, + child: BeeRadio( + value: items[index].id, + groupValues: _selectedItems, + ), + ), + ), + ), + AnimatedTranslate( + offset: _selectedMode ? Offset(60.w, 0) : Offset.zero, + child: AdviceCard(model: items[index]), + ), + ], + ); }, separatorBuilder: (_, __) => 20.hb, itemCount: items.length, @@ -109,23 +155,44 @@ class _AdvicePageState extends State with TickerProviderStateMixin { ); }).toList(), ), - bottomNavi: BottomButton( - onPressed: () async { - bool needRefresh = await Get.to(NewAdvicePage(type: widget.type)); - if (needRefresh == true) { + bottomNavi: AnimatedCrossFade( + crossFadeState: _selectedMode + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + duration: Duration(milliseconds: 300), + firstChild: BottomButton( + onPressed: () async { + await NetUtil().post( + API.manager.deleteAdvice, + params: {'ids': _selectedItems}, + showMessage: true, + ); _refreshController.callRefresh(); - Get.dialog(CupertinoAlertDialog( - title: '您的信息已提交,我们会尽快回复您,祝您生活愉快'.text.isIntrinsic.make(), - actions: [ - CupertinoDialogAction( - child: '确定'.text.color(Color(0xFFFF8200)).isIntrinsic.make(), - onPressed: Get.back, - ), - ], - )); - } - }, - child: Text('新增'), + setState(() { + _selectedMode = false; + }); + }, + child: '删除订单'.text.make(), + ), + secondChild: BottomButton( + onPressed: () async { + bool needRefresh = await Get.to(NewAdvicePage(type: widget.type)); + if (needRefresh == true) { + _refreshController.callRefresh(); + Get.dialog(CupertinoAlertDialog( + title: '您的信息已提交,我们会尽快回复您,祝您生活愉快'.text.isIntrinsic.make(), + actions: [ + CupertinoDialogAction( + child: + '确定'.text.color(Color(0xFFFF8200)).isIntrinsic.make(), + onPressed: Get.back, + ), + ], + )); + } + }, + child: Text('新增'), + ), ), ); } diff --git a/lib/widget/animated/animated_scale.dart b/lib/widget/animated/animated_scale.dart new file mode 100644 index 00000000..323c29e5 --- /dev/null +++ b/lib/widget/animated/animated_scale.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class AnimatedScale extends ImplicitlyAnimatedWidget { + final Widget child; + final double scale; + + AnimatedScale({this.child, this.scale}) + : super( + duration: Duration(milliseconds: 300), + ); + @override + ImplicitlyAnimatedWidgetState createState() => + _AnimatedScaleState(); +} + +class _AnimatedScaleState extends AnimatedWidgetBaseState { + Tween scaleTween; + @override + Widget build(BuildContext context) { + return Transform.scale( + scale: scaleTween.evaluate(animation), + child: widget.child, + ); + } + + @override + void forEachTween(visitor) { + scaleTween = visitor( + scaleTween, + widget.scale, + (value) => Tween(begin: value), + ); + } +} diff --git a/lib/widget/animated/animated_transition.dart b/lib/widget/animated/animated_transition.dart new file mode 100644 index 00000000..c9d8a73d --- /dev/null +++ b/lib/widget/animated/animated_transition.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class AnimatedTranslate extends ImplicitlyAnimatedWidget { + final Widget child; + final Offset offset; + + AnimatedTranslate({this.child, this.offset}) + : super( + duration: Duration(milliseconds: 300), + ); + @override + ImplicitlyAnimatedWidgetState createState() => + _AnimatedTranslateState(); +} + +class _AnimatedTranslateState + extends AnimatedWidgetBaseState { + Tween _offsetTween; + @override + Widget build(BuildContext context) { + return Transform.translate( + offset: _offsetTween.evaluate(animation), + child: widget.child, + ); + } + + @override + void forEachTween(visitor) { + _offsetTween = visitor( + _offsetTween, + widget.offset, + (value) => Tween(begin: value), + ); + } +} diff --git a/lib/widget/buttons/bottom_button.dart b/lib/widget/buttons/bottom_button.dart index be102fc3..82197994 100644 --- a/lib/widget/buttons/bottom_button.dart +++ b/lib/widget/buttons/bottom_button.dart @@ -30,6 +30,7 @@ class BottomButton extends StatelessWidget { onPressed: onPressed, color: kPrimaryColor, height: 98.w, + minWidth: double.infinity, ), ); } diff --git a/lib/widget/buttons/radio_button.dart b/lib/widget/buttons/radio_button.dart new file mode 100644 index 00000000..29ac8f7d --- /dev/null +++ b/lib/widget/buttons/radio_button.dart @@ -0,0 +1,55 @@ +import 'package:akuCommunity/base/base_style.dart'; +import 'package:akuCommunity/utils/headers.dart'; +import 'package:akuCommunity/widget/animated/animated_scale.dart'; +import 'package:flutter/material.dart'; + +class BeeRadio extends StatefulWidget { + final T value; + final List groupValues; + BeeRadio({Key key, @required this.value, @required this.groupValues}) + : super(key: key); + + @override + _BeeRadioState createState() => _BeeRadioState(); +} + +class _BeeRadioState extends State { + bool get _selected { + if (widget.groupValues.contains(widget.value)) return true; + return false; + } + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + height: 40.w, + width: 40.w, + decoration: BoxDecoration( + border: Border.all( + color: _selected ? kPrimaryColor : Color(0xFF979797), + width: 3.w, + ), + borderRadius: BorderRadius.circular(20.w), + ), + duration: Duration(milliseconds: 300), + curve: Curves.easeInOutCubic, + alignment: Alignment.center, + child: AnimatedOpacity( + duration: Duration(milliseconds: 300), + curve: Curves.easeInOutCubic, + opacity: _selected ? 1 : 0, + child: AnimatedScale( + scale: _selected ? 1 : 0, + child: Container( + height: 24.w, + width: 24.w, + decoration: BoxDecoration( + color: kPrimaryColor, + borderRadius: BorderRadius.circular(12.w), + ), + ), + ), + ), + ); + } +} diff --git a/lib/widget/tab_bar/bee_tab_bar.dart b/lib/widget/tab_bar/bee_tab_bar.dart index 1f5574f7..9997b9d5 100644 --- a/lib/widget/tab_bar/bee_tab_bar.dart +++ b/lib/widget/tab_bar/bee_tab_bar.dart @@ -5,7 +5,9 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; class BeeTabBar extends StatefulWidget with PreferredSizeWidget { final TabController controller; final List tabs; - BeeTabBar({Key key, @required this.controller, @required this.tabs}) + final Function(int index) onTap; + BeeTabBar( + {Key key, @required this.controller, @required this.tabs, this.onTap}) : super(key: key); @override @@ -16,6 +18,22 @@ class BeeTabBar extends StatefulWidget with PreferredSizeWidget { } class _BeeTabBarState extends State { + update() { + if (widget.onTap != null) widget.onTap(widget.controller.index); + } + + @override + void initState() { + super.initState(); + widget.controller.addListener(update); + } + + @override + void dispose() { + widget.controller.removeListener(update); + super.dispose(); + } + @override Widget build(BuildContext context) { return TabBar( @@ -30,6 +48,7 @@ class _BeeTabBarState extends State { indicatorColor: Color(0xffffc40c), indicatorSize: TabBarIndicatorSize.label, tabs: widget.tabs.map((e) => Tab(text: e)).toList(), + onTap: widget.onTap, ); } }