profile_edit_page.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/src/widgets/framework.dart';
  4. import 'package:flutter_screenutil/flutter_screenutil.dart';
  5. import 'package:keyboard/base/base_page.dart';
  6. import 'package:keyboard/module/profile/edit/profile_edit_controller.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:get/get.dart';
  9. import 'package:keyboard/utils/age_zodiac_sign_util.dart';
  10. import '../../../data/bean/keyboard_info.dart';
  11. import '../../../resource/assets.gen.dart';
  12. import '../../../resource/string.gen.dart';
  13. import '../../../router/app_pages.dart';
  14. import '../../../utils/styles.dart';
  15. import '../../../widget/avatar/avatar_image_widget.dart';
  16. import '../../../widget/gradient_rect_slider_track_shape.dart';
  17. class ProfileEditPage extends BasePage<ProfileEditController> {
  18. const ProfileEditPage({super.key});
  19. static start({KeyboardInfo? keyboardInfo}) {
  20. Get.toNamed(
  21. RoutePath.profileEdit,
  22. arguments: {"keyboardInfo": keyboardInfo},
  23. );
  24. }
  25. @override
  26. bool immersive() {
  27. return true;
  28. }
  29. @override
  30. backgroundColor() {
  31. return Color(0xFFF6F5FA);
  32. }
  33. @override
  34. Widget buildBody(BuildContext context) {
  35. return Stack(
  36. children: [
  37. Container(
  38. child: Assets.images.bgCharacterCustomDetail.image(
  39. width: double.infinity,
  40. fit: BoxFit.fill,
  41. ),
  42. ),
  43. SafeArea(
  44. child: Container(
  45. color: Colors.transparent,
  46. alignment: Alignment.topCenter,
  47. child: Stack(
  48. children: [
  49. Column(
  50. children: [
  51. _buildTitle(),
  52. SizedBox(height: 42.h),
  53. Expanded(
  54. child: Container(
  55. decoration: ShapeDecoration(
  56. color: Color(0xFFF6F5FA),
  57. shape: RoundedRectangleBorder(
  58. borderRadius: BorderRadius.only(
  59. topLeft: Radius.circular(20.r),
  60. topRight: Radius.circular(20.r),
  61. ),
  62. ),
  63. ),
  64. child: SingleChildScrollView(
  65. child: Column(
  66. children: [
  67. _buildNameCard(),
  68. SizedBox(height: 20.h),
  69. _buildIntimacySlider(),
  70. SizedBox(height: 10.h),
  71. _buildGenderCard(),
  72. SizedBox(height: 10.h),
  73. _buildBirthdayCard(),
  74. SizedBox(height: 10.h),
  75. // _buildRelationshipCard(),
  76. // SizedBox(height: 10.h),
  77. ],
  78. ),
  79. ),
  80. ),
  81. ),
  82. Container(
  83. color: Color(0xFFF6F5FA),
  84. child: _buildSaveButton(),
  85. ),
  86. ],
  87. ),
  88. Positioned(left: 16.w, top: 60.h, child: _buildAvatar()),
  89. Positioned(left: 68.w, top: 112.h, child: _buildAvatarSwitch()),
  90. ],
  91. ),
  92. ),
  93. ),
  94. ],
  95. );
  96. }
  97. _buildTitle() {
  98. return Container(
  99. alignment: Alignment.centerLeft,
  100. padding: EdgeInsets.only(top: 12.h, left: 16.w),
  101. child: GestureDetector(
  102. onTap: controller.clickBack,
  103. child: Assets.images.iconMineBackArrow.image(width: 24.w, height: 24.w),
  104. ),
  105. );
  106. }
  107. _buildNameCard() {
  108. return GestureDetector(
  109. onTap: () {
  110. controller.clickNickname();
  111. },
  112. child: Container(
  113. padding: EdgeInsets.only(left: 104.w, top: 14.h),
  114. child: Row(
  115. crossAxisAlignment: CrossAxisAlignment.end,
  116. children: [
  117. Obx(() {
  118. return Text(
  119. controller.currentNickname??"请输入昵称",
  120. textAlign: TextAlign.center,
  121. style: TextStyle(
  122. color: Colors.black.withAlpha(204),
  123. fontSize: 18.sp,
  124. fontWeight: FontWeight.w500,
  125. ),
  126. );
  127. }),
  128. Container(
  129. child: Assets.images.iconCharacterCustomDetailEdit.image(
  130. width: 20.r,
  131. height: 20.r,
  132. ),
  133. ),
  134. ],
  135. ),
  136. ),
  137. );
  138. }
  139. _buildAvatar() {
  140. return GestureDetector(
  141. onTap: controller.nextAvatar,
  142. child: Obx(() {
  143. return Container(
  144. width: 72.r,
  145. height: 72.r,
  146. child:
  147. controller.avatarUrl.isNotEmpty
  148. ? CircleAvatarWidget(
  149. image: Assets.images.iconKeyboardDefaultAvatar.provider(),
  150. imageUrl: controller.avatarUrl,
  151. size: 72.w,
  152. borderColor: Colors.white,
  153. borderWidth: 2.r,
  154. placeholder: (_, __) {
  155. return const CupertinoActivityIndicator();
  156. },
  157. )
  158. : SizedBox(),
  159. );
  160. }),
  161. );
  162. }
  163. _buildAvatarSwitch() {
  164. return GestureDetector(
  165. onTap: controller.nextAvatar,
  166. child: SizedBox(
  167. width: 22.r,
  168. height: 22.r,
  169. child: Assets.images.iconCharacterCustomDetailSwitch.image(
  170. width: 22.r,
  171. height: 22.r,
  172. ),
  173. ),
  174. );
  175. }
  176. // 性别
  177. Widget _buildGenderCard() {
  178. return _buildListItem(
  179. onTap: () {
  180. controller.clickGender();
  181. },
  182. firstWidget: Text('性别', style: Styles.getTextStyleBlack204W400(14.sp)),
  183. bottomWidget: Obx(() {
  184. return Row(
  185. children: [
  186. Assets.images.iconCharacterCustomDetailMale.image(
  187. width: 24.w,
  188. height: 24.w,
  189. ),
  190. SizedBox(width: 6.w),
  191. Text(
  192. controller.genderText,
  193. style: Styles.getTextStyleBlack204W400(14.sp),
  194. ),
  195. Spacer(),
  196. Assets.images.iconArrowRight.image(width: 24.w, height: 24.w),
  197. ],
  198. );
  199. }),
  200. );
  201. }
  202. Widget _buildBirthdayCard() {
  203. return _buildListItem(
  204. onTap: () {
  205. controller.clickBirthday();
  206. },
  207. firstWidget: Text(
  208. '出生日期', style: Styles.getTextStyleBlack204W400(14.sp)),
  209. bottomWidget: Obx(() {
  210. return Row(
  211. children: [
  212. Text(
  213. controller.currentBirthday ?? "请选择",
  214. style: Styles.getTextStyleBlack204W400(14.sp),
  215. ),
  216. SizedBox(width: 12.w),
  217. Text(
  218. controller.currentBirthday != null
  219. ? '${AgeZodiacSignUtil.calculateAgeFromString(controller.currentBirthday!).toString()}岁'
  220. : "",
  221. style: Styles.getTextStyleBlack204W400(14.sp),
  222. ),
  223. Spacer(),
  224. Assets.images.iconArrowRight.image(width: 24.w, height: 24.w),
  225. ],
  226. );
  227. }),
  228. );
  229. }
  230. Widget _buildRelationshipCard() {
  231. return _buildListItem(
  232. onTap: () {
  233. debugPrint('点击了关系');
  234. },
  235. firstWidget: Text('关系', style: Styles.getTextStyleBlack204W400(14.sp)),
  236. bottomWidget: Row(
  237. children: [
  238. Spacer(),
  239. Assets.images.iconArrowRight.image(width: 24.w, height: 24.w),
  240. ],
  241. ),
  242. );
  243. }
  244. Widget _buildSaveButton() {
  245. return GestureDetector(
  246. onTap: () {
  247. controller.clickSaveButton();
  248. },
  249. child: Container(
  250. width: double.infinity,
  251. margin: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.h),
  252. height: 48.h,
  253. alignment: Alignment.center,
  254. decoration: ShapeDecoration(
  255. color: const Color(0xFF7D46FC),
  256. shape: RoundedRectangleBorder(
  257. borderRadius: BorderRadius.circular(50.r),
  258. ),
  259. ),
  260. child: Text(
  261. StringName.profileEditSave,
  262. textAlign: TextAlign.center,
  263. style: Styles.getTextStyleWhiteW500(16.sp),
  264. ),
  265. ),
  266. );
  267. }
  268. // 列表项
  269. Widget _buildListItem({
  270. required Widget firstWidget,
  271. required Widget bottomWidget,
  272. VoidCallback? onTap,
  273. }) {
  274. return Container(
  275. padding: EdgeInsets.only(
  276. left: 12.w,
  277. right: 12.w,
  278. top: 14.h,
  279. bottom: 14.h,
  280. ),
  281. margin: EdgeInsets.only(left: 16.w, right: 16.w),
  282. width: double.infinity,
  283. decoration: ShapeDecoration(
  284. color: Colors.white,
  285. shape: RoundedRectangleBorder(
  286. borderRadius: BorderRadius.circular(12.r),
  287. ),
  288. ),
  289. child: Column(
  290. crossAxisAlignment: CrossAxisAlignment.start,
  291. mainAxisAlignment: MainAxisAlignment.center,
  292. children: [
  293. firstWidget,
  294. _buildDivider(),
  295. GestureDetector(
  296. behavior: HitTestBehavior.opaque,
  297. onTap: onTap,
  298. child: bottomWidget,
  299. ),
  300. ],
  301. ),
  302. );
  303. }
  304. // 下划线
  305. Widget _buildDivider() {
  306. return Container(
  307. margin: EdgeInsets.only(top: 8.h, bottom: 8.h),
  308. width: 304.w,
  309. decoration: ShapeDecoration(
  310. shape: RoundedRectangleBorder(
  311. side: BorderSide(
  312. width: 1.r,
  313. strokeAlign: BorderSide.strokeAlignCenter,
  314. color: const Color(0xFFF5F4F9),
  315. ),
  316. ),
  317. ),
  318. );
  319. }
  320. Widget _buildIntimacySlider() {
  321. return // 亲密度模块
  322. Container(
  323. margin: EdgeInsets.only(left: 16.w, top: 24.h, right: 16.w),
  324. padding: EdgeInsets.only(
  325. left: 16.w,
  326. top: 23.h,
  327. right: 16.w,
  328. bottom: 26.h,
  329. ),
  330. decoration: BoxDecoration(
  331. image: DecorationImage(
  332. image: Assets.images.bgProfileEditIntimacy.provider(),
  333. fit: BoxFit.fill,
  334. ),
  335. borderRadius: BorderRadius.circular(10.r),
  336. ),
  337. child: Column(
  338. children: [
  339. // 亲密度
  340. Row(
  341. crossAxisAlignment: CrossAxisAlignment.center,
  342. children: [
  343. Assets.images.iconKeyboardManageFavorite.image(
  344. width: 20.w,
  345. height: 20.w,
  346. ),
  347. Assets.images.iconKeyboardManageIntimacyText.image(
  348. width: 48.w,
  349. height: 19.h,
  350. ),
  351. const Spacer(),
  352. Container(
  353. alignment: Alignment.center,
  354. width: 81.w,
  355. height: 28.h,
  356. decoration: ShapeDecoration(
  357. color: const Color(0xFFE1E0E7),
  358. shape: RoundedRectangleBorder(
  359. borderRadius: BorderRadius.circular(16.r),
  360. ),
  361. ),
  362. child: Obx(() {
  363. return Text(
  364. '${StringName.intimacy}${controller
  365. .currentCustomIntimacy}%',
  366. textAlign: TextAlign.right,
  367. style: TextStyle(
  368. color: Colors.black.withAlpha(204),
  369. fontSize: 12.sp,
  370. fontWeight: FontWeight.w400,
  371. ),
  372. );
  373. }),
  374. ),
  375. ],
  376. ),
  377. SizedBox(height: 19.h),
  378. Builder(
  379. builder: (context) {
  380. return SliderTheme(
  381. data: SliderTheme.of(context).copyWith(
  382. trackShape: const GradientRectSliderTrackShape(),
  383. trackHeight: 8.h,
  384. thumbColor: Colors.white,
  385. thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7.r),
  386. overlayShape: const RoundSliderOverlayShape(
  387. overlayRadius: 16,
  388. ),
  389. ),
  390. child: Obx(() {
  391. return Slider(
  392. value: controller.currentCustomIntimacy.toDouble(),
  393. divisions: 100,
  394. min: 0,
  395. max: 100,
  396. onChanged: (value) {
  397. controller.updateIntimacy(value.toInt());
  398. },
  399. );
  400. }),
  401. );
  402. },
  403. ),
  404. ],
  405. ),
  406. );
  407. }
  408. }