feat: 增加侧滑事件

This commit is contained in:
2025-12-02 06:09:25 -08:00
parent 8e27ddeded
commit e82480b937
13 changed files with 669 additions and 250 deletions
@@ -14,12 +14,19 @@ import '../../../widgets/kr_network_image.dart';
import 'package:kaer_with_panels/app/widgets/dialogs/kr_dialog.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/app/widgets/swipe/has_swipe_config.dart';
import 'package:kaer_with_panels/app/widgets/swipe/swipe_config.dart';
import 'dart:convert';
/// 购买会员页面视图
class KRPurchaseMembershipView extends GetView<KRPurchaseMembershipController> {
class KRPurchaseMembershipView extends GetView<KRPurchaseMembershipController>
implements HasSwipeConfig {
const KRPurchaseMembershipView({super.key});
@override
SwipeConfig get swipeConfig =>
SwipeConfig(enableLeft: true, onLeft: () => Get.back());
@override
Widget build(BuildContext context) {
return HIBaseScaffold(
@@ -27,106 +34,129 @@ class KRPurchaseMembershipView extends GetView<KRPurchaseMembershipController> {
title: '套餐选择',
subtitle: '*所有套餐均不限流量不限速度',
topContentAreaHeight: 110,
child: Obx(() {
return Stack(
children: [
Padding(
padding: EdgeInsets.only(bottom: 80.0),
child: SingleChildScrollView(
child: Column(
children: [
/*_kr_buildAccountSection(context),*/
if (controller.kr_isLoading.value)
Container(
height: MediaQuery.of(context).size.height * 0.5,
child: Center(
child: KRSimpleLoading(
color: Colors.white,
size: 50.0,
),
),
)
else if (controller.kr_plans.isEmpty)
Container(
height: MediaQuery.of(context).size.height * 0.5,
child: Center(
child: Text(
AppTranslations.kr_purchaseMembership.noData,
style: KrAppTextStyle(
fontSize: 14,
color: Theme.of(context)
.textTheme
.bodyMedium
?.color,
),
),
),
)
else
Container(
margin: EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
children: [
// 套餐选择部分
child: Stack(
children: [
Positioned(
left: 0,
top: 0,
bottom: 0,
width: 20,
child: const _LeftEdgeSwipeBack(),
),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(bottom: 80.0),
child: Obx(() => SingleChildScrollView(
child: Column(
children: [
/*_kr_buildAccountSection(context),*/
if (controller.kr_isLoading.value)
Container(
padding: EdgeInsets.all(0.0),
height:
MediaQuery.of(context).size.height * 0.5,
child: Center(
child: KRSimpleLoading(
color: Colors.white,
size: 50.0,
),
),
)
else if (controller.kr_plans.isEmpty)
Container(
height:
MediaQuery.of(context).size.height * 0.5,
child: Center(
child: Text(
AppTranslations
.kr_purchaseMembership.noData,
style: KrAppTextStyle(
fontSize: 14,
color: Theme.of(context)
.textTheme
.bodyMedium
?.color,
),
),
),
)
else
Container(
margin: EdgeInsets.only(
left: 40.0 - 20, right: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
// 使用 List.generate 动态创建卡片列表
children: List.generate(
controller.kr_getTotalOptionsCount(
controller.kr_plans[controller
.kr_selectedPlanIndex.value]),
(index) {
final plan = controller.kr_plans[
controller
.kr_selectedPlanIndex.value];
final discountIndex =
plan.kr_discount.isEmpty
? null
: index;
// 使用 Padding 来为每个卡片添加底部的间距,模拟 mainAxisSpacing
return Padding(
padding:
EdgeInsets.only(bottom: 8.0),
child: SizedBox(
height: 130.0,
child: _kr_buildPlanOptionCard(
plan,
controller
.kr_selectedPlanIndex.value,
discountIndex,
context,
index,
),
// 套餐选择部分
Container(
padding: EdgeInsets.all(0.0),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Column(
// 使用 List.generate 动态创建卡片列表
children: List.generate(
controller.kr_getTotalOptionsCount(
controller.kr_plans[controller
.kr_selectedPlanIndex
.value]),
(index) {
final plan = controller
.kr_plans[
controller
.kr_selectedPlanIndex
.value];
final discountIndex =
plan.kr_discount.isEmpty
? null
: index;
// 使用 Padding 来为每个卡片添加底部的间距,模拟 mainAxisSpacing
return Padding(
padding: EdgeInsets.only(
bottom: 8.0),
child: SizedBox(
height: 130.0,
child:
_kr_buildPlanOptionCard(
plan,
controller
.kr_selectedPlanIndex
.value,
discountIndex,
context,
index,
),
),
);
},
),
);
},
),
],
),
),
],
),
),
],
),
],
),
],
)),
),
Positioned(
top: 160.0, // 距离顶部的距离
right: 10.0, // 固定在右侧 20.w 的位置
child: KrLocalImage(
imageName: 'purchase_slogan',
imageType: ImageType.svg,
),
)),
Positioned(
top: 160.0, // 距离顶部的距离
right: 10.0, // 固定在右侧 20.w 的位置
child: KrLocalImage(
imageName: 'purchase_slogan',
imageType: ImageType.svg,
),
),
const HIHelpEntrance(isLight: false)
],
),
const HIHelpEntrance(isLight: false)
],
);
}),
),
],
),
);
}
@@ -328,3 +358,47 @@ class KRPurchaseMembershipView extends GetView<KRPurchaseMembershipController> {
);
}
}
class _LeftEdgeSwipeBack extends StatefulWidget {
const _LeftEdgeSwipeBack();
@override
State<_LeftEdgeSwipeBack> createState() => _LeftEdgeSwipeBackState();
}
class _LeftEdgeSwipeBackState extends State<_LeftEdgeSwipeBack> {
Offset? _start;
Offset? _last;
DateTime? _startTime;
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragStart: (details) {
_start = details.globalPosition;
_startTime = DateTime.now();
KRLogUtil.kr_d(
'Purchase left edge dragStart x=${details.globalPosition.dx}',
tag: 'PurchaseSwipe');
},
onHorizontalDragUpdate: (details) {
_last = details.globalPosition;
},
onHorizontalDragEnd: (details) {
final durationMs = DateTime.now()
.difference(_startTime ?? DateTime.now())
.inMilliseconds;
final distance =
_last != null && _start != null ? (_last!.dx - _start!.dx) : 0.0;
KRLogUtil.kr_d(
'Purchase left edge dragEnd dur=$durationMs dist=$distance',
tag: 'PurchaseSwipe');
if (distance > 20) {
Get.back();
}
_start = null;
_last = null;
_startTime = null;
},
);
}
}