一个布局可能会有很多组件 ,每个组件都可能是一个大功能,可能要用一大堆代码实现,这时候就可以把那个组件拆出来,单独放在一个类里面了。一个组件拆出来,放在一个类里面,单独展示的话就是全屏显示的一个组件,然后抽出来的时候就是设宽高,直接调用这个类。或者如果已经调好的就直接调用这个类
比如发布按钮和跳到顶部的按钮就可以拆分出来。
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Container(
color: Colors.transparent,
child: Stack(children: [
RefreshConfiguration(
enableLoadingWhenFailed: true,
hideFooterWhenNotFull: true,
child: SmartRefresher(
enablePullDown: true,
enablePullUp: true,
controller: _refreshController,
onLoading: _onLoading,
onRefresh: _onRefresh,
footer: const ClassicFooter(
loadStyle: LoadStyle.ShowWhenLoading),
child: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverToBoxAdapter(child: MomentBanner(controller)),
getMomentListView()
]))),
MomentBottomItem(showFastView, _scrollController),//两个控件都放在这个类里面面了,简洁了好多
])));
因为发布按钮是一个动画来的,所以也单独拆到一个类里面,实现的功能代码也放在这个类里面,清晰明了。怎么拆?可以单独跳转到那个动画按键界面,它是满屏的,居中的。同样道理,满屏变成宽70和高70。这跟原生的自定义view差不多,可以想象成70宽70高,然后装着一个自己定义的一个组件界面
Container(
width: WidgetAdaptation.getWidth(70),
height: WidgetAdaptation.getWidth(70),
margin: EdgeInsets.only(
bottom: WidgetAdaptation.getWidth(10)),
child: const ReleaseDynamicAnimation(),
alignment: Alignment.center)
MomentBottomItem类如下
import 'package:flutter/material.dart';
import 'package:social_im/camera_picker/constants/constants.dart';
import 'package:social_im/common/globalEventBus.dart';
import 'package:social_im/generated/l10n.dart';
import 'package:social_im/pages/dialog/ReleaseDynamicsAnimation.dart';
import 'package:social_im/pages/widget/splitLine.dart';
import 'package:social_im/utils/widgetAdaptation.dart';
///动态b底部控件
import '../../dialog/PostSeekingDialog.dart';
class MomentBottomItem extends StatefulWidget {
bool showFastView = false;
ScrollController scrollController;
MomentBottomItem(this.showFastView, this.scrollController, {Key? key})
: super(key: key);
@override
State<StatefulWidget> createState() => MomentBottomItemState();
}
class MomentBottomItemState extends State<MomentBottomItem> {
List<AssetEntity> assetss = [];
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
///调起相册
releaseDynamic() async {
//停掉发布动态按钮的动画
EventBusUtil.fire(SendDynamicAnimationEvent(false));
showDialog(
context: context, builder: (context) => PostMomentSeekingDialog())
.then((value) => EventBusUtil.fire(SendDynamicAnimationEvent(true)));
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
@override
Widget build(BuildContext context) {
return Positioned(
right: WidgetAdaptation.getWidth(13),
bottom: WidgetAdaptation.getWidth(50),
child: Container(
margin: EdgeInsets.only(right: WidgetAdaptation.getWidth(0)),
child: Column(children: [
Offstage(
offstage: !widget.showFastView,
child: GestureDetector(
onTap: () {
// _scrollController.position.pixels
widget.scrollController.jumpTo(0.0);
},
child: Image(
width: WidgetAdaptation.getWidth(45),
height: WidgetAdaptation.getWidth(45),
image: const AssetImage(
'assets/images/icon_dynamic_slide_up.png')))),
Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
GestureDetector(
onTap: () {
releaseDynamic();
},
child: Container(
margin: EdgeInsets.only(
top: WidgetAdaptation.getWidth(13)),
color: Colors.transparent,
height: WidgetAdaptation.getWidth(80),
width: WidgetAdaptation.getWidth(58))),
Stack(
alignment: Alignment.bottomCenter,
clipBehavior: Clip.none,
children: [
GestureDetector(
onTap: () {
releaseDynamic();
},
child: Container(
width: WidgetAdaptation.getWidth(70),
height: WidgetAdaptation.getWidth(70),
margin: EdgeInsets.only(
bottom: WidgetAdaptation.getWidth(10)),
child: const ReleaseDynamicAnimation(),//发布按钮的实现在这里
alignment: Alignment.center)),
Positioned(
bottom: -18,
child: GestureDetector(
onTap: () {
releaseDynamic();
},
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight:
WidgetAdaptation.getWidth(24),
minWidth:
WidgetAdaptation.getWidth(58)),
child: Container(
padding: const EdgeInsets.only(
left: 14,
right: 14,
top: 2,
bottom: 2),
margin: EdgeInsets.only(
bottom: WidgetAdaptation.getWidth(
10)),
alignment: Alignment.center,
decoration: BoxDecorationUtil()
.setFillBoxDecorationImg(
'assets/images/bg_send_moment.png'),
child: Text(S.current.post,
style: const TextStyle(
color: Color(0xFF09DECB),
fontSize: 14))))))
])
])
])));
}
}
ReleaseDynamicAnimation发布按钮的实现
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../common/Global.dart';
import '../../common/backgroundWall.dart';
import '../../common/globalEventBus.dart';
import '../../utils/printUtil.dart';
import '../../utils/widgetAdaptation.dart';
import '../widget/splitLine.dart';
class ReleaseDynamicAnimation extends StatefulWidget{
const ReleaseDynamicAnimation({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() =>ReleaseAnimation();
}
class ReleaseAnimation extends State<ReleaseDynamicAnimation> with TickerProviderStateMixin, WidgetsBindingObserver, RouteAware{
final List<Widget> backdropAnimationList = [];
///背景动画控制器 ///背景动画控件集合
final List<AnimationController> backdropControllerList = [];
int playMilliseconds = 1500;
int playTimeMilliseconds = 1500;
late StreamSubscription<SendDynamicAnimationEvent> sendDynamicEvent;
bool hasSelectTab=false;
@override
void initState() {
WidgetsBinding.instance!.addObserver(this);
sendDynamicEvent=EventBusUtil.listen((event) {
if(event.isSelectTab==true&&!hasSelectTab){
createBackdropAnimation(true);
}else{
createBackdropAnimation(false);
}
hasSelectTab=event.isSelectTab;
});
super.initState();
}
@override
void dispose() {
backdropAnimationList.clear();
for (int i = 0; i < backdropControllerList.length; i++) {
backdropControllerList[i].reset();
backdropControllerList[i].dispose();
}
backdropControllerList.clear();
super.dispose();
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
@override
Widget build(BuildContext context) {
return Stack(alignment: Alignment.center, children: [
Stack(alignment: Alignment.center, children: backdropAnimationList),
Container(
width: WidgetAdaptation.getWidth(50),
height: WidgetAdaptation.getWidth(50),
alignment: Alignment.center,
decoration: BoxDecorationUtil().setFillBoxDecorationImg(
'assets/images/icon_send_moment_cir.png'),
child: Container(
margin: const EdgeInsets.only(right: 2),
width: WidgetAdaptation.getWidth(26),
height: WidgetAdaptation.getWidth(26),
alignment: Alignment.center,
decoration: BoxDecorationUtil().setFillBoxDecorationImg(
'assets/images/icon_send_moment_plane.png'),
)),
]);
}
Animation<double> createItemAnimation(parent, double begin, double end,
double beginCurve, double endCurve, curve) {
Animation<double> animation =
Tween<double>(begin: begin, end: end).animate(CurvedAnimation(
parent: parent,
curve: Interval(beginCurve, endCurve, //间隔,后40%的动画时间
curve: curve)));
return animation;
}
///创建背景动画
createBackdropAnimation(isPlayBackdropAnimation) {
if (isPlayBackdropAnimation&&mounted) {
AnimationController animationController =
createBackdropController(playMilliseconds);
backdropControllerList.add(animationController);
Animation<double> backdropTransparentAnimation = createItemAnimation(
animationController, 0.5, 1.0, 0.0, 0.5, Curves.linear);
Animation<double> backdropTransparentAnimationTwo = createItemAnimation(
animationController, 0.0, 1.0, 0.5, 0.9, Curves.linear);
Animation<double> backdropHeightAnimation = createItemAnimation(
animationController,
WidgetAdaptation.getWidth(50),
WidgetAdaptation.getWidth(80),
0.0,
1.0,
Curves.linear);
backdropAnimationList.add(AnimatedBuilder(
animation: animationController,
builder: (BuildContext context, Widget? child) {
return Opacity(
opacity: (backdropTransparentAnimation.value) -
(backdropTransparentAnimationTwo.value),
child: BackgroundWall(
// width: backdropHeightAnimation.value,
height: backdropHeightAnimation.value,
radius: 5,
avtarUrl:
'assets/images/icon_send_moment_animation.png',
svgaAvtarUrl: Global.defBackImag));
}));
try {
//动画页退出时,捕获可能发生的异常
animationController.forward();
// PrintUtil.prints('动画播放');
mySetState(() {});
} catch (e) {
PrintUtil.prints('动画播放异常 $e');
return;
}
// PrintUtil.prints('动画播放 $playTimeMilliseconds');
Future.delayed(Duration(milliseconds: playTimeMilliseconds), () {
if (isPlayBackdropAnimation && mounted && hasSelectTab) {
createBackdropAnimation(true);
}
});
} else {
for (int i = 0; i < backdropControllerList.length; i++) {
backdropControllerList[i].reset();
backdropControllerList[i].dispose();
}
backdropControllerList.clear();
backdropAnimationList.clear();
mySetState(() {});
}
}
AnimationController createBackdropController(milliseconds) {
AnimationController animationController = AnimationController(
duration: Duration(milliseconds: milliseconds), vsync: this);
animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController.reset();
animationController.dispose();
if (backdropControllerList.contains(animationController)) {
backdropControllerList.remove(animationController);
backdropAnimationList.removeAt(0);
}
}
});
return animationController;
}
}