144 lines
3.7 KiB
Dart
Raw Normal View History

2025-07-21 15:46:30 +08:00
/// 可拖拽广告红包组件
library;
import 'package:flutter/material.dart';
class Ads extends StatefulWidget {
const Ads({super.key});
@override
State<Ads> createState() => _AdsState();
}
class _AdsState extends State<Ads> with WidgetsBindingObserver {
double winWidth = 0.0;
double winHeight = 0.0;
double dx = 10.0;
double dy = 120.0;
double ballWidth = 50.0;
double ballHeight = 50.0;
bool isAnimate = false;
// 是否显示
bool isVisible = true;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((_) {
updateResize();
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
// 监听窗口尺寸变化
@override
void didChangeMetrics() {
super.didChangeMetrics();
WidgetsBinding.instance.addPostFrameCallback((_) {
updateResize();
});
}
// 更新设备尺寸
void updateResize() {
setState(() {
winWidth = MediaQuery.of(context).size.width;
winHeight = MediaQuery.of(context).size.height;
});
}
// 拖拽更新
void onPanUpdate(Offset position) {
isAnimate = false;
dx = position.dx - ballWidth / 2;
dy = position.dy - ballHeight / 2;
setState(() {});
}
// 拖拽结束
void onPanEnd(Offset position) {
isAnimate = true;
if (dx + ballWidth / 2 < winWidth / 2) {
dx = 10.0;
} else {
dx = winWidth - ballWidth - 10.0;
}
if (dy + ballHeight > winHeight / 2) {
dy = winHeight / 2 - ballHeight;
} else if (dy < 120) {
dy = 120.0;
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Visibility(
visible: isVisible,
child: AnimatedPositioned(
duration: Duration(milliseconds: isAnimate ? 200 : 0),
left: dx,
top: dy,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onPanUpdate: (DragUpdateDetails details) {
onPanUpdate(details.globalPosition);
},
onPanEnd: (details) {
onPanEnd(details.globalPosition);
},
onTap: () {
debugPrint('click ads');
},
child: Stack(
children: [
SizedBox(
height: ballHeight,
width: ballWidth,
child: UnconstrainedBox(
child: Container(
height: 40.0,
width: 40.0,
decoration: BoxDecoration(
color: Colors.black.withAlpha(50),
borderRadius: BorderRadius.circular(100.0),
),
child: UnconstrainedBox(
child: Image.asset(
'assets/images/hbico.png',
width: 25.0,
fit: BoxFit.contain,
),
),
),
)),
Positioned(
right: 0,
top: 0,
child: GestureDetector(
child: Icon(
Icons.close,
color: Colors.white,
size: 10.0,
),
onTap: () {
setState(() {
isVisible = false;
});
},
),
),
],
),
),
),
);
}
}