|
|
|
@ -1,4 +1,5 @@ |
|
|
|
import 'package:cached_network_image/cached_network_image.dart'; |
|
|
|
import 'package:dating_touchme_app/extension/ex_widget.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter/cupertino.dart'; |
|
|
|
import 'package:dating_touchme_app/generated/assets.dart'; |
|
|
|
@ -8,8 +9,15 @@ import 'package:get/get.dart'; |
|
|
|
import 'package:dating_touchme_app/controller/mine/user_info_controller.dart'; |
|
|
|
import 'package:tdesign_flutter/tdesign_flutter.dart'; |
|
|
|
|
|
|
|
class UserInfoPage extends StatelessWidget { |
|
|
|
UserInfoPage({super.key}); |
|
|
|
class UserInfoPage extends StatefulWidget { |
|
|
|
const UserInfoPage({super.key}); |
|
|
|
|
|
|
|
@override |
|
|
|
_UserInfoState createState() => _UserInfoState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _UserInfoState extends State<UserInfoPage> { |
|
|
|
|
|
|
|
// 显示头像选择选项 |
|
|
|
void _showAvatarPopup(UserInfoController controller){ |
|
|
|
Navigator.of(Get.context!).push( |
|
|
|
@ -76,7 +84,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
// 显示学历选择弹框 |
|
|
|
Future _showEducationPicker(UserInfoController controller) async { |
|
|
|
final List<String> educationOptions = ['大专以下', '大专', '本科', '硕士及以上']; |
|
|
|
|
|
|
|
|
|
|
|
await showModalBottomSheet( |
|
|
|
context: Get.context!, |
|
|
|
shape: const RoundedRectangleBorder( |
|
|
|
@ -88,53 +96,53 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
builder: (BuildContext context) { |
|
|
|
return Container( |
|
|
|
padding: const EdgeInsets.all(16), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, // 明确设置背景色 |
|
|
|
borderRadius: const BorderRadius.only( |
|
|
|
topLeft: Radius.circular(8), |
|
|
|
topRight: Radius.circular(8), |
|
|
|
), |
|
|
|
), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, // 明确设置背景色 |
|
|
|
borderRadius: const BorderRadius.only( |
|
|
|
topLeft: Radius.circular(8), |
|
|
|
topRight: Radius.circular(8), |
|
|
|
), |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
// 标题和关闭按钮 |
|
|
|
Stack( |
|
|
|
alignment: Alignment.center, |
|
|
|
children: [ |
|
|
|
// 关闭按钮 - 左对齐 |
|
|
|
Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
child: IconButton( |
|
|
|
icon: const Icon(Icons.close), |
|
|
|
onPressed: () { |
|
|
|
Navigator.pop(context); |
|
|
|
}, |
|
|
|
), |
|
|
|
), |
|
|
|
// 标题 - 居中 |
|
|
|
Text( |
|
|
|
'学历', |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
// 标题和关闭按钮 |
|
|
|
Stack( |
|
|
|
alignment: Alignment.center, |
|
|
|
children: [ |
|
|
|
// 关闭按钮 - 左对齐 |
|
|
|
Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
child: IconButton( |
|
|
|
icon: const Icon(Icons.close), |
|
|
|
onPressed: () { |
|
|
|
Navigator.pop(context); |
|
|
|
}, |
|
|
|
), |
|
|
|
), |
|
|
|
// 标题 - 居中 |
|
|
|
Text( |
|
|
|
'学历', |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
const SizedBox(height: 16), |
|
|
|
|
|
|
|
|
|
|
|
// 学历选项列表 |
|
|
|
for (String education in educationOptions) |
|
|
|
for (String education in educationOptions) |
|
|
|
Container( |
|
|
|
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), // 左右10,上下6 |
|
|
|
child: ElevatedButton( |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: controller.education.value == education |
|
|
|
? const Color.fromRGBO(123, 104, 238, 1) // 紫色 |
|
|
|
: const Color.fromRGBO(247, 247, 247, 1), |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25), // 增加水平内边距 |
|
|
|
minimumSize: const Size(double.infinity, 48), // 宽度充满,最小高度48 |
|
|
|
backgroundColor: controller.education.value == education |
|
|
|
? const Color.fromRGBO(123, 104, 238, 1) // 紫色 |
|
|
|
: const Color.fromRGBO(247, 247, 247, 1), |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25), // 增加水平内边距 |
|
|
|
minimumSize: const Size(double.infinity, 48), // 宽度充满,最小高度48 |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(32), |
|
|
|
), |
|
|
|
@ -153,7 +161,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
|
|
|
|
|
|
|
|
// 底部间距 |
|
|
|
const SizedBox(height: 20), |
|
|
|
], |
|
|
|
@ -169,7 +177,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
final now = DateTime.now(); |
|
|
|
final maxDate = DateTime(now.year - 18); // 最小18岁 |
|
|
|
final minDate = DateTime(now.year - 80); // 最大80岁 |
|
|
|
|
|
|
|
|
|
|
|
// 初始选择日期(默认为25岁) |
|
|
|
DateTime initialDate = DateTime(now.year - 25); |
|
|
|
if (controller.birthday.value.isNotEmpty) { |
|
|
|
@ -189,10 +197,10 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
print('解析日期失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 临时存储选择的日期 |
|
|
|
DateTime? selectedDate = initialDate; |
|
|
|
|
|
|
|
|
|
|
|
await showCupertinoModalPopup( |
|
|
|
context: Get.context!, |
|
|
|
builder: (BuildContext context) { |
|
|
|
@ -251,6 +259,10 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
} |
|
|
|
|
|
|
|
final FocusNode _blankFocusNode = FocusNode(); |
|
|
|
final TextEditingController _controller = TextEditingController(); |
|
|
|
final FocusNode _blankFocusNode2 = FocusNode(); |
|
|
|
final TextEditingController _controller2 = TextEditingController(); |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return GetX<UserInfoController>( |
|
|
|
@ -303,14 +315,14 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
child: ClipOval( |
|
|
|
child: (controller.avatarUrl.value.startsWith('http') |
|
|
|
? Image.network( |
|
|
|
controller.avatarUrl.value, |
|
|
|
fit: BoxFit.cover, |
|
|
|
) |
|
|
|
: Image.asset( |
|
|
|
Assets.imagesAvatarsExample, |
|
|
|
fit: BoxFit.cover, |
|
|
|
)), |
|
|
|
? Image.network( |
|
|
|
controller.avatarUrl.value, |
|
|
|
fit: BoxFit.cover, |
|
|
|
) |
|
|
|
: Image.asset( |
|
|
|
Assets.imagesAvatarsExample, |
|
|
|
fit: BoxFit.cover, |
|
|
|
)), |
|
|
|
), |
|
|
|
), |
|
|
|
Positioned( |
|
|
|
@ -341,7 +353,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 25), |
|
|
|
|
|
|
|
|
|
|
|
// 性别选择 |
|
|
|
const Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
@ -403,7 +415,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
], |
|
|
|
), |
|
|
|
const SizedBox(height: 20), |
|
|
|
|
|
|
|
|
|
|
|
// 昵称 |
|
|
|
const Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
@ -427,14 +439,26 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: TextField( |
|
|
|
controller: TextEditingController(text: controller.nickname.value), |
|
|
|
focusNode: _blankFocusNode, |
|
|
|
controller: _controller, |
|
|
|
onChanged: (value) { |
|
|
|
controller.nickname.value = value; |
|
|
|
}, |
|
|
|
onTapOutside: (e){ |
|
|
|
_blankFocusNode.unfocus(); |
|
|
|
}, |
|
|
|
onTap: (){ |
|
|
|
// 确保光标在文本末尾 |
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) { |
|
|
|
_controller.selection = TextSelection.fromPosition( |
|
|
|
TextPosition(offset: _controller.text.length), |
|
|
|
); |
|
|
|
}); |
|
|
|
}, |
|
|
|
decoration: const InputDecoration( |
|
|
|
border: InputBorder.none, |
|
|
|
hintText: '请输入昵称', |
|
|
|
hintStyle: TextStyle(color: Colors.grey), |
|
|
|
hintStyle: TextStyle(color: Colors.grey), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -442,7 +466,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 20), |
|
|
|
|
|
|
|
|
|
|
|
// 出生日期 |
|
|
|
const Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
@ -458,8 +482,9 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
const SizedBox(height: 10), |
|
|
|
GestureDetector( |
|
|
|
onTap: () async { |
|
|
|
FocusScope.of(context).requestFocus(_blankFocusNode); |
|
|
|
// FocusScope.of(context).requestFocus(_blankFocusNode); |
|
|
|
// 显示Cupertino日期选择器 |
|
|
|
// _blankFocusNode.unfocus(); |
|
|
|
await _showDatePicker(controller); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
@ -487,7 +512,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 20), |
|
|
|
|
|
|
|
|
|
|
|
// 学历 |
|
|
|
const Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
@ -503,7 +528,8 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
const SizedBox(height: 10), |
|
|
|
GestureDetector( |
|
|
|
onTap: () async { |
|
|
|
FocusScope.of(context).requestFocus(_blankFocusNode); |
|
|
|
// FocusScope.of(context).requestFocus(_blankFocusNode); |
|
|
|
// _blankFocusNode.unfocus(); |
|
|
|
// 显示学历选择弹框 |
|
|
|
await _showEducationPicker(controller); |
|
|
|
}, |
|
|
|
@ -532,7 +558,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 20), |
|
|
|
|
|
|
|
|
|
|
|
// 邀请码 |
|
|
|
const Align( |
|
|
|
alignment: Alignment.centerLeft, |
|
|
|
@ -553,9 +579,22 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
color: Color.fromRGBO(247, 247, 247, 1), |
|
|
|
), |
|
|
|
child: TextField( |
|
|
|
focusNode: _blankFocusNode2, |
|
|
|
controller: _controller2, |
|
|
|
onChanged: (value) { |
|
|
|
controller.invitationCode.value = value; |
|
|
|
}, |
|
|
|
onTapOutside: (e){ |
|
|
|
_blankFocusNode2.unfocus(); |
|
|
|
}, |
|
|
|
onTap: (){ |
|
|
|
// 确保光标在文本末尾 |
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) { |
|
|
|
_controller2.selection = TextSelection.fromPosition( |
|
|
|
TextPosition(offset: _controller2.text.length), |
|
|
|
); |
|
|
|
}); |
|
|
|
}, |
|
|
|
decoration: const InputDecoration( |
|
|
|
hintText: '请输入邀请码', |
|
|
|
hintStyle: TextStyle(color: Colors.grey), |
|
|
|
@ -564,7 +603,7 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 24), |
|
|
|
|
|
|
|
|
|
|
|
// 开始交友按钮 |
|
|
|
SizedBox( |
|
|
|
width: double.infinity, |
|
|
|
@ -581,20 +620,20 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
), |
|
|
|
child: controller.isSubmitting.value |
|
|
|
? const SizedBox( |
|
|
|
width: 20, |
|
|
|
height: 20, |
|
|
|
child: CircularProgressIndicator( |
|
|
|
color: Colors.white, |
|
|
|
strokeWidth: 2, |
|
|
|
), |
|
|
|
) |
|
|
|
width: 20, |
|
|
|
height: 20, |
|
|
|
child: CircularProgressIndicator( |
|
|
|
color: Colors.white, |
|
|
|
strokeWidth: 2, |
|
|
|
), |
|
|
|
) |
|
|
|
: const Text( |
|
|
|
'开始交友', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
), |
|
|
|
'开始交友', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 20), |
|
|
|
@ -608,4 +647,14 @@ class UserInfoPage extends StatelessWidget { |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
// TODO: implement dispose |
|
|
|
super.dispose(); |
|
|
|
_blankFocusNode.dispose(); |
|
|
|
_controller.dispose(); |
|
|
|
_blankFocusNode2.dispose(); |
|
|
|
_controller2.dispose(); |
|
|
|
} |
|
|
|
} |