import 'dart:math';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:wrapper/wrapper.dart';
class BtnPopupWidget extends StatefulWidget {
final double spineHeight;
final bool formEnd;
final double width;
final double height;
final double angle;
final double right;
final double btnHeight;
final double btnWidth;
final Widget content;
BtnPopupWidget( {
Key? key,
required this.width,
required this.height,
required this.btnHeight,
required this.btnWidth,
required this.content,
this.spineHeight=12,
this.angle=80,
this.right=0,
this.formEnd=false
}) : super(key: key);
@override
State<BtnPopupWidget> createState() => _BtnPopupWidgetState();
}
class _BtnPopupWidgetState extends State<BtnPopupWidget> with SingleTickerProviderStateMixin{
final LayerLink _layerLink = LayerLink();
bool show = false;
OverlayEntry? _overlayEntry;
AnimationController? controller;//动画控制器
// CurvedAnimation? curved;//曲线动画,动画插值,
late final Animation<Offset> _offset;
@override
void initState() {
// TODO: implement initState
super.initState();
controller = new AnimationController(
vsync: this, duration: const Duration(seconds: 2));
//设置动画
_offset= Tween<Offset>(
begin:const Offset(0, -0.5) ,
end: Offset.zero,
).animate(CurvedAnimation(
parent: controller!,
curve: Curves.bounceOut,
)
..addListener((){
setState(() {
});
})
..addStatusListener((status) {
if(status==AnimationStatus.reverse){
status=AnimationStatus.completed;
}
})
);
}
@override
Widget build(BuildContext context) {
return CompositedTransformTarget(
link: _layerLink,
child: GestureDetector(
onTap: () {
if (show) {
show = false;
_overlayEntry!.remove();
controller!.reverse();
} else {
_overlayEntry = EmojiPanel();
show = true;
Overlay.of(context)?.insert(_overlayEntry!);
controller!.forward();
}
},
child: Container(
child: Text("按钮"),
),
),
);
}
OverlayEntry EmojiPanel() {
double _spineHeight =widget.spineHeight;
// bool _formEnd = true;
double _width =widget.width;
double _height =widget.height;
double _angle = widget.angle;
double right =widget.right;
double btnHeight = widget.btnWidth;
double btnWidth=widget.btnWidth;
///尖端路径构造器
Path _spinePathBuilder(Canvas canvas, SpineType spineType, Rect range) {
///从尾部偏移计算相关坐标
var lineHeight = _height - _spineHeight;
var angleRad = pi / 180 * _angle;
var sideLength = _spineHeight * tan(angleRad / 2);
var offset = right + btnWidth/2;
var startX = _width - offset - sideLength;
var stratY = lineHeight;
var controlPointX = _width - offset;
var controlPointY = _height + btnHeight / 3;
var endX = startX + sideLength * 2;
var endY = lineHeight;
//绘制双曲线
return Path()
..moveTo(startX, stratY)
..conicTo(controlPointX, controlPointY, endX, endY, 1.5);
}
return OverlayEntry(builder: (context) {
///排除父级对子级的约束
return UnconstrainedBox(
child: CompositedTransformFollower(
///主体的位置
followerAnchor: Alignment.bottomRight,
///浮窗的位置
targetAnchor: Alignment.topRight,
offset: Offset(0, -5),
link: _layerLink,
//显示动画设置
child: SlideTransition(
position: _offset,
child: Container(
width: _width,
height: _height,
child: Wrapper(
padding: EdgeInsets.zero,
///箭头
spinePathBuilder: _spinePathBuilder,
///箭头高度
spineHeight: _spineHeight,
///背景色
color: Colors.white,
///箭头位置
spineType: SpineType.bottom,
///影深
elevation: 10,
///从尾部偏移
// formEnd: _formEnd,
///偏移量
// offset: 150,
///阴影颜色
shadowColor: Colors.black.withAlpha(88),
///圆角半径
radius: 10,
///针尖夹角
// angle: _angle,
///内容
child: widget.content
),
),
),
),
);
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_overlayEntry!.remove();
controller!.dispose();
}
}
最后
以上就是背后丝袜最近收集整理的关于flutter中点击按钮滑动弹出弹框、变更弹框箭头的全部内容,更多相关flutter中点击按钮滑动弹出弹框、变更弹框箭头内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复