基础组件库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

search_input_widget.dart 9.2 KiB

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