|
|
@@ -0,0 +1,307 @@
|
|
|
+import 'package:cached_network_image/cached_network_image.dart';
|
|
|
+import 'package:easy_refresh/easy_refresh.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
+import 'package:flutter_slidable/flutter_slidable.dart';
|
|
|
+import 'package:get/get.dart';
|
|
|
+import 'package:keyboard/base/base_page.dart';
|
|
|
+import 'package:keyboard/module/character_custom/list/character_custom_list_controller.dart';
|
|
|
+import 'package:keyboard/resource/string.gen.dart';
|
|
|
+import 'package:keyboard/utils/styles.dart';
|
|
|
+
|
|
|
+import '../../../data/bean/character_info.dart';
|
|
|
+import '../../../resource/assets.gen.dart';
|
|
|
+import '../../../router/app_pages.dart';
|
|
|
+
|
|
|
+class CharacterCustomListPage extends BasePage<CharacterCustomListController> {
|
|
|
+ const CharacterCustomListPage({super.key});
|
|
|
+
|
|
|
+ static start() {
|
|
|
+ Get.toNamed(RoutePath.characterCustomList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ immersive() {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ backgroundColor() {
|
|
|
+ return Color(0xFFF6F5FA);
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget buildBody(BuildContext context) {
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ child: Assets.images.bgCharacterCustomList.image(
|
|
|
+ width: double.infinity,
|
|
|
+ fit: BoxFit.fill,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SafeArea(
|
|
|
+ child: Container(
|
|
|
+ color: Colors.transparent,
|
|
|
+ alignment: Alignment.topCenter,
|
|
|
+ child: Stack(
|
|
|
+ children: [
|
|
|
+ Column(
|
|
|
+ children: [
|
|
|
+ _buildTitle(),
|
|
|
+ SizedBox(height: 26.h),
|
|
|
+ Expanded(
|
|
|
+ child: Obx(() {
|
|
|
+ return EasyRefresh(
|
|
|
+ controller: controller.refreshController,
|
|
|
+ header: const ClassicHeader(),
|
|
|
+ footer: ClassicFooter(
|
|
|
+ noMoreText: StringName.noMoreData,
|
|
|
+ failedText: StringName.loadFailed,
|
|
|
+ processedText: StringName.loadCompleted,
|
|
|
+ processingText: StringName.loading,
|
|
|
+ ),
|
|
|
+
|
|
|
+ // onRefresh: controller.refreshData,
|
|
|
+ onLoad: controller.loadMoreData,
|
|
|
+ child: ListView.separated(
|
|
|
+ itemCount: controller.characterList.length,
|
|
|
+ itemBuilder: (context, index) {
|
|
|
+ return _buildListItem(
|
|
|
+ characterInfo: controller.characterList[index],
|
|
|
+ );
|
|
|
+ },
|
|
|
+ separatorBuilder: (
|
|
|
+ BuildContext context,
|
|
|
+ int index,
|
|
|
+ ) {
|
|
|
+ return SizedBox(
|
|
|
+ width: double.infinity,
|
|
|
+ height: 10.h,
|
|
|
+ child: Container(
|
|
|
+ color: const Color(0xFFF4F2FB),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ _buildTitle() {
|
|
|
+ return Container(
|
|
|
+ alignment: Alignment.centerLeft,
|
|
|
+ padding: EdgeInsets.only(top: 12.h, left: 16.w, right: 16.w),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: [
|
|
|
+ GestureDetector(
|
|
|
+ onTap: controller.clickBack,
|
|
|
+ child: Assets.images.iconMineBackArrow.image(
|
|
|
+ width: 24.w,
|
|
|
+ height: 24.w,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ StringName.characterCustomHistory,
|
|
|
+ style: Styles.getTextStyleBlack204W500(17.sp),
|
|
|
+ ),
|
|
|
+ SizedBox(),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建列表项
|
|
|
+ Widget _buildListItem({required CharacterInfo characterInfo}) {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ // controller.itemButtonClick(characterInfo);
|
|
|
+ },
|
|
|
+ child: Container(
|
|
|
+ margin: EdgeInsets.symmetric(horizontal: 16.w),
|
|
|
+ decoration: ShapeDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ shape: RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.circular(12.r),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ height: 88.h,
|
|
|
+ child: ClipRect(
|
|
|
+ child: Slidable(
|
|
|
+ key: ValueKey(characterInfo.id),
|
|
|
+ endActionPane: ActionPane(
|
|
|
+ extentRatio: 0.18,
|
|
|
+ motion: StretchMotion(),
|
|
|
+
|
|
|
+ children: [
|
|
|
+ CustomSlidableAction(
|
|
|
+ padding: EdgeInsets.zero,
|
|
|
+ borderRadius: BorderRadius.only(
|
|
|
+ topRight: Radius.circular(12.r),
|
|
|
+ bottomRight: Radius.circular(12.r),
|
|
|
+ ),
|
|
|
+ backgroundColor: Colors.red,
|
|
|
+ onPressed: (buildContext) {
|
|
|
+ controller.itemDeleteClick(characterInfo);
|
|
|
+ },
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ Assets.images.iconCharacterCustomDelete.image(
|
|
|
+ width: 20.r,
|
|
|
+ height: 20.r,
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ StringName.delete,
|
|
|
+ softWrap: false,
|
|
|
+ style: Styles.getTextStyleWhiteW400(13.sp),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ child: Container(
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 16.w),
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ _buildAvatar(imageUrl: characterInfo.imageUrl),
|
|
|
+ SizedBox(width: 8.w),
|
|
|
+ _buildCharacterInfo(characterInfo),
|
|
|
+ _buildActionButton(characterInfo),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 角色头像
|
|
|
+ Widget _buildAvatar({required String? imageUrl}) {
|
|
|
+ return Container(
|
|
|
+ width: 60.r,
|
|
|
+ height: 60.r,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(8),
|
|
|
+ gradient: LinearGradient(
|
|
|
+ begin: Alignment.topCenter,
|
|
|
+ end: Alignment.bottomCenter,
|
|
|
+ colors: [Color(0xffebe6ff), Color(0xffffe6fe)],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ child: CachedNetworkImage(
|
|
|
+ imageUrl: imageUrl ?? "",
|
|
|
+ width: 60.r,
|
|
|
+ height: 60.r,
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 构建角色信息,包括名称、VIP标识和描述
|
|
|
+ Widget _buildCharacterInfo(CharacterInfo characterInfo) {
|
|
|
+ return Expanded(
|
|
|
+ child: Column(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Row(
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ characterInfo.name ?? "",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black.withAlpha(204),
|
|
|
+ fontSize: 15.sp,
|
|
|
+ fontWeight: FontWeight.w500,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(width: 4.w),
|
|
|
+ characterInfo.isVip == true
|
|
|
+ ? Assets.images.iconCharacterVip.image(
|
|
|
+ width: 38.w,
|
|
|
+ height: 16.h,
|
|
|
+ )
|
|
|
+ : Container(),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ characterInfo.description ?? "",
|
|
|
+ softWrap: true,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black.withAlpha(153),
|
|
|
+ fontSize: 12.sp,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 按钮
|
|
|
+ Widget _buildActionButton(CharacterInfo characterInfo) {
|
|
|
+ return InkWell(
|
|
|
+ onTap: () {
|
|
|
+ controller.itemButtonClick(characterInfo);
|
|
|
+ },
|
|
|
+ child: Container(
|
|
|
+ width: 72.w,
|
|
|
+ height: 28.h,
|
|
|
+ margin: EdgeInsets.only(left: 8.w),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(50.r),
|
|
|
+ gradient:
|
|
|
+ characterInfo.isAdd == true
|
|
|
+ ? null
|
|
|
+ : const LinearGradient(
|
|
|
+ colors: [Color(0xFF7D46FC), Color(0xFFBC87FF)],
|
|
|
+ begin: Alignment.topLeft,
|
|
|
+ end: Alignment.bottomRight,
|
|
|
+ ),
|
|
|
+ color: characterInfo.isAdd == true ? const Color(0xFFEDE8FF) : null,
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ if (characterInfo.isLock == true && characterInfo.isVip == true)
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.only(right: 2.w),
|
|
|
+ child: Assets.images.iconCharacterLock.image(
|
|
|
+ width: 18.r,
|
|
|
+ height: 18.r,
|
|
|
+ ), // 锁定图标
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ characterInfo.isLock == true && characterInfo.isVip == true
|
|
|
+ ? StringName.characterUnlock
|
|
|
+ : characterInfo.isAdd == true
|
|
|
+ ? StringName.characterAdded
|
|
|
+ : StringName.characterAdd,
|
|
|
+ style: TextStyle(
|
|
|
+ color:
|
|
|
+ characterInfo.isAdd == true
|
|
|
+ ? const Color(0xFF7D46FC)
|
|
|
+ : Colors.white,
|
|
|
+ fontSize: 14.sp,
|
|
|
+ fontWeight: FontWeight.w500,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|