custom_character_add_view.dart 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:easy_refresh/easy_refresh.dart';
  3. import 'package:flutter_screenutil/flutter_screenutil.dart';
  4. import 'package:flutter_slidable/flutter_slidable.dart';
  5. import 'package:keyboard/base/base_view.dart';
  6. import 'package:keyboard/dialog/custom_character/custom_character_add_controller.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:get/get.dart';
  9. import '../../data/bean/character_info.dart';
  10. import '../../data/bean/keyboard_info.dart';
  11. import '../../data/repository/characters_repository.dart';
  12. import '../../data/repository/keyboard_repository.dart';
  13. import '../../di/get_it.dart';
  14. import '../../resource/assets.gen.dart';
  15. import '../../resource/string.gen.dart';
  16. import '../../utils/styles.dart';
  17. class CustomCharacterAddView extends BaseView<CustomCharacterAddController> {
  18. final KeyboardInfo currentKeyboardInfo;
  19. @override
  20. String? get tag => "CustomCharacterAddController${currentKeyboardInfo.id}";
  21. const CustomCharacterAddView({super.key, required this.currentKeyboardInfo});
  22. @override
  23. backgroundColor() => const Color(0xFFF6F5FA);
  24. @override
  25. Widget buildBody(BuildContext context) {
  26. Get.delete<CustomCharacterAddController>(tag: tag);
  27. Get.put(CustomCharacterAddController(
  28. getIt.get<CharactersRepository>(),
  29. getIt.get<KeyboardRepository>(),
  30. currentKeyboardInfo: currentKeyboardInfo),
  31. tag: tag);
  32. return Column(
  33. children: [
  34. Expanded(
  35. child: Obx(() {
  36. return EasyRefresh(
  37. controller: controller.refreshController,
  38. header: const ClassicHeader(),
  39. footer: ClassicFooter(
  40. showMessage: false,
  41. noMoreText: StringName.noMoreData,
  42. failedText: StringName.loadFailed,
  43. processedText: StringName.loadCompleted,
  44. processingText: StringName.loading,
  45. ),
  46. // onRefresh: controller.refreshData,
  47. onLoad: controller.loadMoreData,
  48. child: ListView.separated(
  49. padding: EdgeInsets.zero,
  50. itemCount: controller.characterList.length,
  51. itemBuilder: (context, index) {
  52. return _buildListItem(
  53. characterInfo: controller.characterList[index],
  54. );
  55. },
  56. separatorBuilder: (BuildContext context, int index) {
  57. return SizedBox(
  58. width: double.infinity,
  59. height: 10.h,
  60. child: Container(color: const Color(0xFFF4F2FB)),
  61. );
  62. },
  63. ),
  64. );
  65. }),
  66. ),
  67. ],
  68. );
  69. }
  70. Widget _buildListItem({required CharacterInfo characterInfo}) {
  71. return GestureDetector(
  72. onTap: () {
  73. controller.itemButtonClick(characterInfo);
  74. },
  75. child: Container(
  76. decoration: ShapeDecoration(
  77. color: Colors.white,
  78. shape: RoundedRectangleBorder(
  79. borderRadius: BorderRadius.circular(12.r),
  80. ),
  81. ),
  82. height: 88.h,
  83. padding: EdgeInsets.symmetric(horizontal: 16.w),
  84. child: Row(
  85. children: [
  86. _buildAvatar(imageUrl: characterInfo.imageUrl),
  87. SizedBox(width: 8.w),
  88. _buildCharacterInfo(characterInfo),
  89. _buildActionButton(characterInfo),
  90. ],
  91. ),
  92. ),
  93. );
  94. }
  95. /// 角色头像
  96. Widget _buildAvatar({required String? imageUrl}) {
  97. return Container(
  98. width: 60.r,
  99. height: 60.r,
  100. decoration: BoxDecoration(
  101. borderRadius: BorderRadius.circular(8),
  102. gradient: LinearGradient(
  103. begin: Alignment.topCenter,
  104. end: Alignment.bottomCenter,
  105. colors: [Color(0xffebe6ff), Color(0xffffe6fe)],
  106. ),
  107. ),
  108. child: CachedNetworkImage(
  109. imageUrl: imageUrl ?? "",
  110. width: 60.r,
  111. height: 60.r,
  112. fit: BoxFit.cover,
  113. ),
  114. );
  115. }
  116. /// 构建角色信息,包括名称、VIP标识和描述
  117. Widget _buildCharacterInfo(CharacterInfo characterInfo) {
  118. return Expanded(
  119. child: Column(
  120. mainAxisAlignment: MainAxisAlignment.center,
  121. crossAxisAlignment: CrossAxisAlignment.start,
  122. children: [
  123. Row(
  124. children: [
  125. Text(
  126. characterInfo.name ?? "",
  127. style: TextStyle(
  128. color: Colors.black.withAlpha(204),
  129. fontSize: 15.sp,
  130. fontWeight: FontWeight.w500,
  131. ),
  132. ),
  133. SizedBox(width: 4.w),
  134. characterInfo.isVip == true
  135. ? Assets.images.iconCharacterVip.image(
  136. width: 38.w,
  137. height: 16.h,
  138. )
  139. : Container(),
  140. ],
  141. ),
  142. Text(
  143. characterInfo.description ?? "",
  144. softWrap: true,
  145. style: TextStyle(
  146. color: Colors.black.withAlpha(153),
  147. fontSize: 12.sp,
  148. fontWeight: FontWeight.w400,
  149. ),
  150. ),
  151. ],
  152. ),
  153. );
  154. }
  155. /// 按钮
  156. Widget _buildActionButton(CharacterInfo characterInfo) {
  157. return InkWell(
  158. onTap: () {
  159. controller.itemButtonClick(characterInfo);
  160. },
  161. child: Container(
  162. width: 72.w,
  163. height: 28.h,
  164. margin: EdgeInsets.only(left: 8.w),
  165. decoration: BoxDecoration(
  166. borderRadius: BorderRadius.circular(50.r),
  167. gradient:
  168. characterInfo.isAdd == true
  169. ? null
  170. : const LinearGradient(
  171. colors: [Color(0xFF7D46FC), Color(0xFFBC87FF)],
  172. begin: Alignment.topLeft,
  173. end: Alignment.bottomRight,
  174. ),
  175. color: characterInfo.isAdd == true ? const Color(0xFFEDE8FF) : null,
  176. ),
  177. child: Row(
  178. mainAxisAlignment: MainAxisAlignment.center,
  179. children: [
  180. if (characterInfo.isLock == true && characterInfo.isVip == true)
  181. Padding(
  182. padding: EdgeInsets.only(right: 2.w),
  183. child: Assets.images.iconCharacterLock.image(
  184. width: 18.r,
  185. height: 18.r,
  186. ), // 锁定图标
  187. ),
  188. Text(
  189. characterInfo.isLock == true && characterInfo.isVip == true
  190. ? StringName.characterUnlock
  191. : characterInfo.isAdd == true
  192. ? StringName.characterAdded
  193. : StringName.characterAdd,
  194. style: TextStyle(
  195. color:
  196. characterInfo.isAdd == true
  197. ? const Color(0xFF7D46FC)
  198. : Colors.white,
  199. fontSize: 14.sp,
  200. fontWeight: FontWeight.w500,
  201. ),
  202. ),
  203. ],
  204. ),
  205. ),
  206. );
  207. }
  208. }