select_estate_page.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import 'dart:async';
  2. import 'package:cs_resources/generated/assets.dart';
  3. import 'package:cs_resources/generated/l10n.dart';
  4. import 'package:cs_resources/theme/app_colors_theme.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:auto_route/auto_route.dart';
  7. import 'package:flutter_hooks/flutter_hooks.dart';
  8. import 'package:hooks_riverpod/hooks_riverpod.dart';
  9. import 'package:router/ext/auto_router_extensions.dart';
  10. import 'package:shared/utils/log_utils.dart';
  11. import 'package:widgets/ext/ex_widget.dart';
  12. import 'package:widgets/my_appbar.dart';
  13. import 'package:widgets/my_button.dart';
  14. import 'package:widgets/my_load_image.dart';
  15. import 'package:widgets/my_text_view.dart';
  16. import 'package:plugin_basic/basic_export.dart';
  17. import '../../router/page/auth_page_router.dart';
  18. import 'attach_input_widget.dart';
  19. import 'select_estate_view_model.dart';
  20. @RoutePage()
  21. class SelectEstatePage extends HookConsumerWidget with WidgetsBindingObserver {
  22. SelectEstateViewModel? viewModel;
  23. bool _isKeyboardVisible = false; //软件是否展示
  24. double _previousBottom = 0; // 用于保存上一个 Insets
  25. Function()? throttledShowDropDownDialog; // 定义防抖函数
  26. bool isVisible = true; //页面是否可见
  27. SelectEstatePage({Key? key}) : super(key: key);
  28. //启动当前页面
  29. static void startInstance({BuildContext? context}) {
  30. if (context != null) {
  31. context.router.push(SelectEstatePageRoute());
  32. } else {
  33. appRouter.push(SelectEstatePageRoute());
  34. }
  35. }
  36. @override
  37. Widget build(BuildContext context, WidgetRef ref) {
  38. viewModel = ref.watch(selectEstateViewModelProvider.notifier);
  39. final state = ref.watch(selectEstateViewModelProvider);
  40. // 初始化防抖函数
  41. throttledShowDropDownDialog ??= throttle(() {
  42. viewModel?.showDropDownDialog(needReLocation: true);
  43. }) as Function()?;
  44. useEffect(() {
  45. // 组件挂载时执行 - 执行接口请求
  46. WidgetsBinding.instance.addObserver(this);
  47. return () {
  48. // 组件卸载时执行
  49. WidgetsBinding.instance.removeObserver(this);
  50. };
  51. }, []);
  52. return Scaffold(
  53. appBar: MyAppBar.appBar(context, S.current.yy_home_accounts),
  54. backgroundColor: context.appColors.backgroundDefault,
  55. body: Container(
  56. padding: const EdgeInsets.symmetric(horizontal: 38),
  57. width: double.infinity,
  58. child: VisibilityDetector(
  59. key: const Key('select-estate-page'),
  60. onVisibilityChanged: (VisibilityInfo info) {
  61. // 检测页面是否可见
  62. isVisible = info.visibleFraction > 0;
  63. Log.d("检测页面是否可见:$isVisible");
  64. },
  65. child: Column(
  66. mainAxisSize: MainAxisSize.max,
  67. crossAxisAlignment: CrossAxisAlignment.center,
  68. children: [
  69. SingleChildScrollView(
  70. scrollDirection: Axis.vertical,
  71. physics: const BouncingScrollPhysics(),
  72. child: Column(
  73. crossAxisAlignment: CrossAxisAlignment.center,
  74. children: [
  75. //顶部图片
  76. const MyAssetImage(
  77. Assets.authChooseEstateBuilding,
  78. width: 267,
  79. height: 158,
  80. ).marginOnly(top: 28, bottom: 38),
  81. MyTextView(
  82. S.current.estate_or_building_name,
  83. fontSize: 23,
  84. marginBottom: 20,
  85. textAlign: TextAlign.center,
  86. isFontMedium: true,
  87. textColor: context.appColors.textBlack,
  88. ),
  89. //输入资产的名称
  90. AttachInputWidget(
  91. onChanged: (context, value) {
  92. viewModel?.searchEstate(context, value);
  93. },
  94. ),
  95. MyTextView(
  96. S.current.estate_name_desc,
  97. fontSize: 15,
  98. marginTop: 19,
  99. isFontMedium: true,
  100. textColor: context.appColors.textBlack,
  101. ),
  102. ],
  103. )).expanded(),
  104. MyButton(
  105. onPressed: (){
  106. isVisible = false;
  107. viewModel?.submitEstate();
  108. },
  109. text: S.current.next,
  110. textColor: Colors.white,
  111. backgroundColor: context.appColors.btnBgDefault,
  112. fontWeight: FontWeight.w500,
  113. type: ClickType.throttle,
  114. fontSize: 16,
  115. minHeight: 50,
  116. radius: 5,
  117. ).marginOnly(top: 50, bottom: 50),
  118. ],
  119. ),
  120. ),
  121. ),
  122. );
  123. }
  124. @override
  125. void didChangeMetrics() {
  126. //页面不可见时不走逻辑
  127. if (!isVisible) return;
  128. // 当键盘弹出或收起时,这里会被调用
  129. final currentInsets = WidgetsBinding.instance.window.viewInsets;
  130. if (currentInsets.bottom > 0 && _previousBottom == 0) {
  131. //键盘已弹出
  132. _isKeyboardVisible = true;
  133. } else if (currentInsets.bottom == 0 && _previousBottom > 0) {
  134. //键盘已收起
  135. _isKeyboardVisible = false;
  136. //软键盘收起的时候,重新布局Attach下拉选弹窗
  137. throttledShowDropDownDialog?.call();
  138. }
  139. // 更新上一个 Insets
  140. _previousBottom = currentInsets.bottom;
  141. }
  142. //防抖 throttle 函数
  143. Function throttle(void Function() callback, [int milliseconds = 500]) {
  144. bool _isAllowed = true;
  145. Timer? _throttleTimer;
  146. return () {
  147. if (!_isAllowed) return;
  148. _isAllowed = false;
  149. callback();
  150. _throttleTimer?.cancel();
  151. _throttleTimer = Timer(Duration(milliseconds: milliseconds), () {
  152. _isAllowed = true;
  153. });
  154. };
  155. }
  156. }