基础组件库
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

260 lines
8.5 KiB

  1. import 'dart:convert';
  2. import 'dart:ui';
  3. import 'package:cached_network_image/cached_network_image.dart';
  4. import 'package:flutter/cupertino.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_bloc/flutter_bloc.dart';
  7. import 'package:fluttertoast/fluttertoast.dart';
  8. import 'package:provider/provider.dart';
  9. import 'package:zhiying_base_widget/pages/search_page/notifier/search_tag_notifier.dart';
  10. import 'package:zhiying_base_widget/pages/search_result_page/search_result_page.dart';
  11. import 'package:zhiying_base_widget/pages/search_think_page/bloc/search_think_bloc.dart';
  12. import 'package:zhiying_base_widget/pages/search_think_page/search_think_page.dart';
  13. import 'package:zhiying_base_widget/widgets/search/input/model/search_input_model.dart';
  14. import 'package:zhiying_base_widget/widgets/search/input/search_input_sk.dart';
  15. import 'package:zhiying_comm/zhiying_comm.dart';
  16. ///
  17. /// 搜索页的搜索框
  18. ///
  19. class SearchInputWidget extends StatefulWidget {
  20. final Map<String, dynamic> data;
  21. SearchInputModel model;
  22. SearchInputWidget(this.data, {Key key}) : super(key: key) {
  23. try {
  24. model = SearchInputModel.fromJson(jsonDecode(data['data']));
  25. } catch (e) {
  26. Logger.error(e);
  27. }
  28. }
  29. @override
  30. _SearchInputWidgetState createState() => _SearchInputWidgetState();
  31. }
  32. class _SearchInputWidgetState extends State<SearchInputWidget> {
  33. FocusNode _focusNode;
  34. TextEditingController _editingController;
  35. /// 点击搜索按钮
  36. void _onSearchButtomClick() async {
  37. String content = _editingController?.text?.toString()?.trim() ?? '';
  38. /// TODO 保存历史标签
  39. if (!EmptyUtil.isEmpty(content)) {
  40. Provider.of<SearchTagNotifier>(context, listen: false).addTag(content);
  41. RouterUtil.hideKeyboard(context);
  42. Navigator.push(context, CupertinoPageRoute(builder: (_) => SearchResultPage({'keywords': content, 'tag': 'search_page'})));
  43. } else {
  44. Fluttertoast.showToast(msg: '输入内容不能为空!');
  45. }
  46. }
  47. /// 【弃用】打开搜索联想页面
  48. void _openSearchThinkPage() {
  49. Navigator.push(context, CupertinoPageRoute(builder: (_) => SearchThinkPage({})));
  50. }
  51. /// 搜索框值改变
  52. void _searchInputChange(String text) {
  53. if (!EmptyUtil.isEmpty(text)) {
  54. // 进行网络更新
  55. print('输入框的内容是 $text');
  56. BlocProvider.of<SearchThinkBloc>(context).add(SearchThinkKeyWrodsChangeEvent(text));
  57. } else {
  58. /// 输入框为空的时候,隐藏联想视图,显示原本的视图
  59. BlocProvider.of<SearchThinkBloc>(context).add(SearchThinkShowBaseViewEvent());
  60. }
  61. }
  62. void _onEditingComplete() {
  63. Logger.log('=======我输入完毕拉!!!!');
  64. }
  65. @override
  66. void didChangeDependencies() {
  67. super.didChangeDependencies();
  68. }
  69. @override
  70. void initState() {
  71. _focusNode = FocusNode();
  72. _editingController = TextEditingController();
  73. super.initState();
  74. }
  75. @override
  76. void dispose() {
  77. _focusNode?.unfocus();
  78. _focusNode?.dispose();
  79. _editingController?.dispose();
  80. super.dispose();
  81. }
  82. @override
  83. Widget build(BuildContext context) {
  84. return Visibility(
  85. visible: !EmptyUtil.isEmpty(widget?.model),
  86. replacement: SearchInputSkeleton(),
  87. child: _getMainWidget(widget?.model),
  88. );
  89. }
  90. /// 获取主视图
  91. Widget _getMainWidget(SearchInputModel model) {
  92. return Container(
  93. color: Colors.white,
  94. width: double.infinity,
  95. margin: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top + 7.5, left: 12.5, right: 12.5),
  96. child: Row(
  97. children: <Widget>[
  98. /// 返回键
  99. _getReturnWidget(),
  100. const SizedBox(width: 8.5),
  101. /// 输入框
  102. Expanded(
  103. child: Container(
  104. width: double.infinity,
  105. height: 32,
  106. // margin: const EdgeInsets.only(
  107. // left: 12.5,
  108. // right: 12.5,
  109. // ),
  110. decoration: BoxDecoration(
  111. borderRadius: BorderRadius.circular(25),
  112. color: HexColor.fromHex('#F9F9F9'),
  113. ),
  114. child: Row(
  115. children: <Widget>[
  116. /// 搜索icon
  117. _getSearchIconWidget(model),
  118. const SizedBox(width: 7.5),
  119. /// 搜索输入框
  120. Expanded(child: _getSearchInputWidget(model)),
  121. /// 搜索按钮
  122. _getSearchButtomWidget(model),
  123. ],
  124. ),
  125. ),
  126. ),
  127. ],
  128. ),
  129. );
  130. }
  131. /// 返回键
  132. Widget _getReturnWidget() {
  133. return GestureDetector(
  134. onTap: () => Navigator.maybePop(context),
  135. child: Container(
  136. child: Icon(
  137. Icons.arrow_back_ios,
  138. size: 22,
  139. color: HexColor.fromHex('#333333'),
  140. ),
  141. // onPressed: () => Navigator.maybePop(context),
  142. ),
  143. );
  144. }
  145. /// 搜索icon
  146. Widget _getSearchIconWidget(SearchInputModel model) {
  147. return Container(
  148. height: double.infinity,
  149. width: 20,
  150. margin: const EdgeInsets.only(left: 12.5),
  151. padding: const EdgeInsets.symmetric(vertical: 6),
  152. child: CachedNetworkImage(
  153. imageUrl: model?.search_icon ?? '',
  154. ),
  155. );
  156. }
  157. /// 搜索输入框
  158. Widget _getSearchInputWidget(SearchInputModel model) {
  159. return Container(
  160. height: double.infinity,
  161. alignment: Alignment.centerLeft,
  162. decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: HexColor.fromHex('#F9F9F9')),
  163. // padding: const EdgeInsets.symmetric(vertical: 6),
  164. child: TextField(
  165. showCursor: true,
  166. // readOnly: true,
  167. // onTap: ()=> _openSearchThinkPage(),
  168. onChanged: (val) => _searchInputChange(val),
  169. cursorWidth: 1,
  170. onSubmitted: (text) => _onSearchButtomClick(),
  171. onEditingComplete: () => _onEditingComplete(),
  172. controller: _editingController,
  173. focusNode: _focusNode,
  174. cursorColor: Colors.transparent,
  175. style: TextStyle(fontSize: 14, color: HexColor.fromHex('#333333'), textBaseline: TextBaseline.alphabetic),
  176. decoration: InputDecoration(
  177. filled: true,
  178. isDense: true,
  179. // contentPadding: EdgeInsets.zero,
  180. contentPadding: const EdgeInsets.only(left: 0, right: 5, top: 0, bottom: 0),
  181. // contentPadding: const EdgeInsets.only(left: 0, right: 0, bottom: 12, top: 0),
  182. // focusColor: Colors.transparent,
  183. fillColor: Colors.transparent,
  184. border: InputBorder.none,
  185. focusedBorder: InputBorder.none,
  186. focusedErrorBorder: InputBorder.none,
  187. errorBorder: InputBorder.none,
  188. disabledBorder: InputBorder.none,
  189. enabledBorder: InputBorder.none,
  190. hintText: model?.search_inpu_hint_text ?? '搜索更多优惠商品',
  191. hintStyle: TextStyle(color: HexColor.fromHex('#999999'), fontSize: 14, textBaseline: TextBaseline.alphabetic),
  192. ),
  193. ),
  194. );
  195. }
  196. /// 搜索按钮
  197. Widget _getSearchButtomWidget(SearchInputModel model) {
  198. return GestureDetector(
  199. behavior: HitTestBehavior.opaque,
  200. onTap: () => _onSearchButtomClick(),
  201. child: Container(
  202. padding: const EdgeInsets.symmetric(horizontal: 17.5, vertical: 6),
  203. decoration: BoxDecoration(
  204. gradient: LinearGradient(
  205. colors: [HexColor.fromHex(model?.search_button_color ?? '#FD5E5E'), HexColor.fromHex(model?.search_button_t ?? '#FF0100')],
  206. begin: Alignment.centerLeft,
  207. end: Alignment.centerRight),
  208. borderRadius: BorderRadius.circular(30),
  209. ),
  210. child: Text(
  211. model?.search_button ?? '搜索',
  212. style: TextStyle(color: HexColor.fromHex('#FFFFFF'), fontSize: 14),
  213. ),
  214. ),
  215. );
  216. }
  217. /// 【弃用】搜索按钮
  218. // Widget _getSearchButtomWidget() {
  219. // return Material(
  220. // child: Container(
  221. // decoration: BoxDecoration(
  222. // borderRadius: BorderRadius.only(topRight: Radius.circular(25), bottomRight: Radius.circular(25))
  223. // ),
  224. // height: double.infinity,
  225. // width: 63,
  226. // child: RaisedButton(
  227. // padding: const EdgeInsets.only(bottom: 6, top: 6, left: 17.5, right: 17.5),
  228. // shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 25)),
  229. // child: Text('搜索', style: TextStyle( fontSize: 14, color: HexColor.fromHex('#FFFFFF')),),
  230. // onPressed: ()=> _onSearchButtomClick(),
  231. // color: HexColor.fromHex('#FF0100'),
  232. // ),
  233. // ),
  234. // );
  235. // }
  236. }