import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:keyboard/base/base_page.dart'; import 'package:keyboard/data/bean/keyboard_info.dart'; import 'package:keyboard/module/keyboard_manage/keyboard_manage_controller.dart'; import 'package:keyboard/resource/string.gen.dart'; import 'package:reorderables/reorderables.dart'; import '../../data/bean/character_info.dart'; import '../../resource/assets.gen.dart'; import '../../router/app_pages.dart'; import '../../widget/gradient_rect_slider_track_shape.dart'; import '../../widget/tab_custom_gradient_indicator.dart'; class KeyboardManagePage extends BasePage { const KeyboardManagePage({super.key}); @override immersive() { return true; } static Future start({KeyboardInfo? customKeyboardInfo}) async { return Get.toNamed( RoutePath.keyboardManage, arguments: {"customKeyboardInfo": customKeyboardInfo}, ); } @override Widget buildBody(BuildContext context) { return Container( decoration: BoxDecoration( image: DecorationImage( image: Assets.images.bgKeyboardManage.provider(), fit: BoxFit.fill, ), ), child: SafeArea( child: Container( alignment: Alignment.topCenter, child: Column( children: [ // TabBar _buildTitle(), SizedBox(height: 10.h), Expanded( child: Container( decoration: ShapeDecoration( color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(20.r), topRight: Radius.circular(20.r), ), ), ), child: PageView( controller: controller.pageController, onPageChanged: (index) { controller.switchPageKeyboardType(index); }, children: [ _buildKeyboardSettings(isCustom: true), _buildKeyboardSettings(isCustom: false), ], ), ), ), ], ), ), ), ); } Widget _buildTitle() { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.w), child: Row( children: [ GestureDetector( onTap: controller.clickBack, child: Assets.images.iconMineBackArrow.image( width: 24.w, height: 24.w, ), ), Expanded( child: TabBar( // onTap: controller.switchTabKeyboardType, controller: controller.tabController, tabs: controller.keyboardManageType .map((e) => Tab(text: e)) .toList(), dividerHeight: 0, indicator: TabCustomGradientIndicator(), labelStyle: TextStyle( color: Colors.black.withAlpha(204), fontSize: 17.sp, fontWeight: FontWeight.w500, ), unselectedLabelStyle: TextStyle( color: Colors.black.withAlpha(102), fontSize: 17.sp, fontWeight: FontWeight.w500, ), ), ), SizedBox(width: 24.w), ], ), ); } Widget _buildKeyboardSettings({required bool isCustom}) { return Column( children: [ Expanded( child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (isCustom) _buildDropdownButton(), // 只有自定义显示下拉 _buildIntimacySlider(isCustom: isCustom), _buildKeyboardCharacter(isCustom: isCustom), ], ), ), ), _buildSaveButton(isCustom: isCustom), ], ); } Widget _buildDropdownButton() { return Obx(() { return Padding( padding: EdgeInsets.only(left: 16.w, top: 24.h, right: 16.w), child: Row( children: [ Text( "自己&", textAlign: TextAlign.center, style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), DropdownButton( underline: Container(height: 0), style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 16.sp, fontWeight: FontWeight.w500, ), icon: Assets.images.iconCharacterArrowDown.image( width: 20.r, height: 20.r, ), value: controller.currentCustomKeyboardInfo.name, onChanged: (String? newValue) { controller.switchCustomKeyboard(newValue); }, items: List.generate(controller.customKeyboardInfoList.length, ( index, ) { String? value = controller.customKeyboardInfoList[index].name; return DropdownMenuItem( value: value, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Padding( padding: EdgeInsets.symmetric(vertical: 8), child: Text( value ?? "", style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ), if (index != controller.customKeyboardInfoList.length - 1) Divider( color: Color(0xFFF6F6F6), thickness: 1, height: 1, ), ], ), ); }), ), ], ), ); }); } Widget _buildIntimacySlider({required bool isCustom}) { return // 亲密度模块 Container( margin: EdgeInsets.only(left: 16.w, top: 24.h, right: 16.w), padding: EdgeInsets.only( left: 16.w, top: 23.h, right: 16.w, bottom: 26.h, ), decoration: BoxDecoration( image: DecorationImage( image: Assets.images.bgKeyboardManageIntimacy.provider(), fit: BoxFit.fill, ), borderRadius: BorderRadius.circular(10.r), ), child: Column( children: [ // 亲密度 Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Assets.images.iconKeyboardManageFavorite.image( width: 20.w, height: 20.w, ), Assets.images.iconKeyboardManageIntimacyText.image( width: 48.w, height: 19.h, ), const Spacer(), Container( alignment: Alignment.center, width: 81.w, height: 28.h, decoration: ShapeDecoration( color: const Color(0xFFE1E0E7), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.r), ), ), child: Obx(() { return Text( isCustom ? '${StringName.intimacy}${controller.currentCustomIntimacy}%' : '${StringName.intimacy}${controller.currentGeneralIntimacy}%', textAlign: TextAlign.right, style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 12.sp, fontWeight: FontWeight.w400, ), ); }), ), ], ), SizedBox(height: 19.h), Builder( builder: (context) { return SliderTheme( data: SliderTheme.of(context).copyWith( trackShape: const GradientRectSliderTrackShape(), trackHeight: 8.h, thumbColor: Colors.white, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7.r), overlayShape: const RoundSliderOverlayShape( overlayRadius: 16, ), ), child: Obx(() { return Slider( value: isCustom ? controller.currentCustomIntimacy.toDouble() : controller.currentGeneralIntimacy.toDouble(), divisions: 100, min: 0, max: 100, onChanged: (value) { controller.updateIntimacy(value.toInt(), isCustom); }, ); }), ); }, ), ], ), ); } // 键盘人设列表 Widget _buildKeyboardCharacter({required bool isCustom}) { return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(left: 16.w, top: 24.h, bottom: 16.h), child: Text( StringName.keyboardCharacter, style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 14.sp, fontWeight: FontWeight.w500, ), ), ), Obx(() { return ReorderableWrap( runSpacing: 16.h, spacing: 4.w, runAlignment: WrapAlignment.start, alignment: WrapAlignment.start, needsLongPressDraggable: true, padding: EdgeInsets.symmetric(horizontal: 16.w), onReorder: (oldIndex, newIndex) { controller.onReorder(oldIndex, newIndex, isCustom); }, onNoReorder: (int index) {}, onReorderStarted: (int index) {}, scrollPhysics: const BouncingScrollPhysics(), footer: [ _buildFooterItem( image: Assets.images.iconKeyboardManagePlus.image( width: 18.w, height: 18.w, ), name: StringName.addCharacter, onTap: () { controller.clickAddCharacter(isCustom: isCustom); }, ), _buildFooterItem( image: Assets.images.iconKeyboardManageCustom.image( width: 18.w, height: 18.w, ), name: StringName.customCharacter, onTap: () { controller.clickCustomCharacter(); }, ), ], children: isCustom ? controller.currentCustomKeyboardCharacterList .map( (e) => _buildKeyboardCharacterItem( e, isCustom: isCustom, ), ) .toList() : controller.currentGeneralKeyboardCharacterList .map( (e) => _buildKeyboardCharacterItem( e, isCustom: isCustom, ), ) .toList(), ); }), ], ); } Widget _buildKeyboardCharacterItem( CharacterInfo characterInfo, { required bool isCustom, }) { return SizedBox( width: (Get.width - 40.w) / 3, child: Stack( children: [ Container( height: 44.h, margin: EdgeInsets.only(top: 4.h), decoration: ShapeDecoration( color: const Color(0xFFF5F4F9), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Text( '${characterInfo.emoji}${characterInfo.name}', style: TextStyle( color: Colors.black.withAlpha(204), fontSize: 14.sp, fontWeight: FontWeight.w400, ), textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ), Positioned( right: 0, top: 0, child: GestureDetector( onTap: () { controller.clickRemoveCharacter(characterInfo, isCustom); }, child: Assets.images.iconKeyboardManageX.image( width: 18.w, height: 18.w, ), ), ), ], ), ); } // 添加人设按钮 Widget _buildFooterItem({ required Widget image, required String name, void Function()? onTap, }) { return GestureDetector( onTap: onTap, child: Container( margin: EdgeInsets.only(top: 4.h), child: DottedBorder( color: const Color(0xFFC9C2DB), // 虚线颜色 strokeWidth: 1.0.w, // 线条宽度 borderType: BorderType.Rect, // 圆角矩形 radius: Radius.circular(8.r), // 圆角半径 child: Container( width: 102.w, height: 38.h, alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ image, Text( name, style: TextStyle( color: const Color(0xFFC9C2DB), fontSize: 14.sp, fontWeight: FontWeight.w500, ), ), ], ), ), ), ), ); } // 保存按钮 Widget _buildSaveButton({required bool isCustom}) { return Obx(() { bool hasChanges = isCustom ? (controller.customKeyboardCharacterListChanged || controller.customIntimacyChanged) : (controller.generalKeyboardCharacterListChanged || controller.generalIntimacyChanged.value); return GestureDetector( onTap: () { controller.clickSave(isCustom); }, child: Container( width: double.infinity, margin: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.h), height: 48.h, alignment: Alignment.center, decoration: hasChanges ? ShapeDecoration( gradient: LinearGradient( begin: Alignment(0.04, 0.21), end: Alignment(0.98, 0.76), colors: [ const Color(0xFF7D46FC), const Color(0xFFBC87FF), ], ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50.r), ), shadows: [ BoxShadow( color: Color(0x66BDA8C9), blurRadius: 10, offset: Offset(0, 4), spreadRadius: 0, ), ], ) : ShapeDecoration( color: const Color(0x33121212), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(29.50), ), ), child: Text( StringName.keyboardSave, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 16.sp, fontWeight: FontWeight.w500, ), ), ), ); }); } }