language_view.dart 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:get/get.dart';
  4. import 'package:nomo/app/base/base_view.dart';
  5. import 'package:nomo/app/widgets/click_opacity.dart';
  6. import 'package:nomo/app/widgets/ix_app_bar.dart';
  7. import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
  8. import '../controllers/language_controller.dart';
  9. class LanguageView extends BaseView<LanguageController> {
  10. const LanguageView({super.key});
  11. @override
  12. Widget buildContent(BuildContext context) {
  13. return Column(
  14. children: [
  15. IXAppBar(title: 'Language'),
  16. Expanded(
  17. child: SingleChildScrollView(
  18. child: Padding(
  19. padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 20.h),
  20. child: Container(
  21. decoration: BoxDecoration(
  22. color: Get.reactiveTheme.highlightColor,
  23. borderRadius: BorderRadius.circular(16.r),
  24. ),
  25. child: Obx(
  26. () => Column(
  27. children: controller.languages.asMap().entries.map((entry) {
  28. final index = entry.key;
  29. final language = entry.value;
  30. final isSelected =
  31. controller.selectedLanguage.value == language.code;
  32. return Column(
  33. children: [
  34. _buildLanguageOption(
  35. language: language,
  36. isSelected: isSelected,
  37. onTap: () =>
  38. controller.selectLanguage(language.code),
  39. ),
  40. if (index < controller.languages.length - 1)
  41. _buildDivider(),
  42. ],
  43. );
  44. }).toList(),
  45. ),
  46. ),
  47. ),
  48. ),
  49. ),
  50. ),
  51. ],
  52. );
  53. }
  54. /// 构建语言选项
  55. Widget _buildLanguageOption({
  56. required LanguageInfo language,
  57. required bool isSelected,
  58. required VoidCallback onTap,
  59. }) {
  60. return ClickOpacity(
  61. onTap: onTap,
  62. child: Padding(
  63. padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
  64. child: Row(
  65. children: [
  66. // 语言信息
  67. Expanded(
  68. child: Column(
  69. crossAxisAlignment: CrossAxisAlignment.start,
  70. children: [
  71. Text(
  72. language.name,
  73. style: TextStyle(
  74. fontSize: 16.sp,
  75. fontWeight: FontWeight.w500,
  76. color: isSelected
  77. ? const Color(0xFF00A8E8)
  78. : Colors.white,
  79. ),
  80. ),
  81. SizedBox(height: 4.h),
  82. Text(
  83. language.nativeName,
  84. style: TextStyle(
  85. fontSize: 14.sp,
  86. color: Get.reactiveTheme.hintColor,
  87. ),
  88. ),
  89. ],
  90. ),
  91. ),
  92. // 选中指示器
  93. Container(
  94. width: 24.w,
  95. height: 24.w,
  96. decoration: BoxDecoration(
  97. shape: BoxShape.circle,
  98. color: isSelected
  99. ? const Color(0xFF00A8E8)
  100. : Colors.transparent,
  101. border: Border.all(
  102. color: isSelected
  103. ? const Color(0xFF00A8E8)
  104. : Colors.white.withOpacity(0.3),
  105. width: 2.w,
  106. ),
  107. ),
  108. child: isSelected
  109. ? Icon(Icons.check, color: Colors.white, size: 16.w)
  110. : null,
  111. ),
  112. ],
  113. ),
  114. ),
  115. );
  116. }
  117. /// 构建分割线
  118. Widget _buildDivider() {
  119. return Padding(
  120. padding: EdgeInsets.symmetric(horizontal: 20.w),
  121. child: Divider(
  122. color: Get.reactiveTheme.hintColor.withOpacity(0.1),
  123. height: 1.h,
  124. thickness: 1.h,
  125. ),
  126. );
  127. }
  128. }