import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
Future<T?> showCustomGuidePop<T>({
required BuildContext context,
required GlobalKey popKey,
required String title,
Offset? offset,
}) {
return Navigator.push(
context,
_CustomGuidePopRoute<T>(
popKey: popKey,
title: title,
offset: offset
),
);
}
class _CustomGuidePopRoute<T> extends PopupRoute<T> {
final GlobalKey popKey;
final String title;
final Offset? offset;
_CustomGuidePopRoute({
required this.popKey,
required this.title,
this.offset,
});
@override
Color? get barrierColor => null;
@override
bool get barrierDismissible => true;
@override
String? get barrierLabel => null;
@override
Duration get transitionDuration => Duration(milliseconds: 100);
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return CustomGuidePop<T>(
popKey: popKey,
title: title,
offset: offset,
);
}
@override
Animation<double> createAnimation() {
return CurvedAnimation(
parent: super.createAnimation(),
curve: Curves.linear,
reverseCurve: const Interval(0.0, 1.5),
);
}
}
class CustomGuidePop<T> extends StatefulWidget {
final GlobalKey popKey;
final String title;
final Offset offset;
CustomGuidePop({
Key? key,
required this.popKey,
required this.title,
Offset? offset,
}):this.offset = offset ?? Offset.zero, super(key: key);
@override
State<CustomGuidePop> createState() => _CustomGuidePopState();
}
class _CustomGuidePopState extends State<CustomGuidePop> {
late GlobalKey globalKey = GlobalKey();
late Rxn<RelativeRect> positionObs;
late Timer timer;
@override
void initState() {
super.initState();
positionObs = Rxn();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
RenderBox? contentBox = globalKey.currentContext?.findRenderObject() as RenderBox?;
RenderBox? targetBox = widget.popKey.currentContext?.findRenderObject() as RenderBox?;
double left = 0;
double top = 0;
if(targetBox == null || contentBox == null) {
return;
}
var contentSize = contentBox.size;
var targetSize = targetBox.size;
Offset localToGlobal = targetBox.localToGlobal(Offset.zero);
// 目前仅支持在左边显示弹窗
left = localToGlobal.dx - contentSize.width;
top = localToGlobal.dy - (contentSize.height - targetSize.height) * 0.5;
left = left + widget.offset.dx;
top = top + widget.offset.dy;
positionObs.value = RelativeRect.fromLTRB(left, top, 0, 0);
});
// 默认3秒后消失
timer = Timer(Duration(seconds: 3), () {
Navigator.of(context).pop();
});
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: GestureDetector(
child: _buildWindow(context),
onPanDown: (details) {
Navigator.of(context).pop();
},
),
);
}
Widget _buildWindow(BuildContext context) {
return Stack(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.transparent,
),
Obx(() {
return Positioned(
key: globalKey,
left: positionObs.value?.left ?? 0,
top: positionObs.value?.top ?? 0,
child: Visibility(
maintainAnimation: true,
maintainSize: true,
maintainState: true,
visible: positionObs.value != null,
child: Row(
children: [
Container(
padding: EdgeInsets.all(16),
constraints: BoxConstraints(maxWidth: 375 - 160),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(10),
),
child: Text(
widget.title,
style: const TextStyle(
color: Colors.white,
),
),
),
Container(
margin: EdgeInsets.only(right: 5),
child: CustomPaint(
size: Size(8, 14),
painter: RowPainter(),
),
)
],
),
),
);
}),
],
);
}
}
class RowPainter extends CustomPainter {
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.grey;
paint.style = PaintingStyle.fill;
paint.strokeCap = StrokeCap.round;
paint.strokeJoin = StrokeJoin.round;
paint.isAntiAlias = true;
paint.strokeWidth = 1;
Path path = Path();
path.moveTo(0, 0);
path.lineTo(7.5, 6);
path.lineTo(8, 7);
path.lineTo(7.5, 8);
path.lineTo(0, 14);
path.close();
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Flutter气泡引导pop
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...