Flutter:页面3,搜索汗青记载页面

[复制链接]
发表于 2025-11-4 18:02:24 | 显示全部楼层 |阅读模式

view
利用内置的Chip简化布局
  1. import 'package:chenyanzhenxuan/common/index.dart';
  2. import 'package:ducafe_ui_core/ducafe_ui_core.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:get/get.dart';
  5. import 'package:tdesign_flutter/tdesign_flutter.dart';
  6. import 'index.dart';
  7. class SearchGoodsPage extends GetView<SearchGoodsController> {
  8.   const SearchGoodsPage({super.key});
  9.   // 搜索
  10.   Widget _buildSearch() {
  11.     return <Widget>[
  12.       SearchWidget(
  13.         type: 'input',
  14.         inputBgColor: AppTheme.pageBgColor,
  15.         controller: controller.searchController,
  16.         onChange: (value) {
  17.           controller.onSearchChange(value);
  18.         },
  19.       ),
  20.     ].toRow()
  21.     .paddingAll(30.w)
  22.     .card(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)));
  23.   }
  24.   // 热门搜索
  25.   Widget _buildHotSearch() {
  26.     return <Widget>[
  27.       <Widget>[
  28.         TDImage(assetUrl: 'assets/img/hot.png',width: 34.w,height: 34.w,),
  29.         SizedBox(width: 10.w,),
  30.         TextWidget.body('热门搜索',size: 28.sp,),
  31.       ].toRow().paddingHorizontal(30.w),
  32.       <Widget>[
  33.         for(var i = 0; i < 6; i++)
  34.         Chip(
  35.           label: TextWidget.body('热门搜索$i',size: 24.sp,color: AppTheme.color999,),
  36.           backgroundColor: AppTheme.blockBgColor,
  37.           shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.w)),
  38.         )
  39.       ].toWrap(spacing: 20.w,runSpacing: 0,).paddingLeft(30.w),
  40.     ].toColumn(crossAxisAlignment: CrossAxisAlignment.start);
  41.   }
  42.   // 历史记录
  43.   Widget _buildHistory(BuildContext context) {
  44.     return <Widget>[
  45.       <Widget>[
  46.         TextWidget.body('历史记录',size: 28.sp,),
  47.         TDImage(assetUrl: 'assets/img/hot-del.png',width: 28.w,height: 32.w,).onTap(() {
  48.           showGeneralDialog(
  49.           context: context,
  50.           pageBuilder: (BuildContext buildContext, Animation<double> animation,
  51.               Animation<double> secondaryAnimation) {
  52.             return TDAlertDialog(
  53.               title: '清空搜索历史',
  54.               content: '请确定清空搜索历史?',
  55.               buttonWidget: <Widget>[
  56.                 <Widget>[const TextWidget.body('取消')]
  57.                     .toRow(mainAxisAlignment: MainAxisAlignment.center)
  58.                     .card(color: const Color(0xffeeeeee))
  59.                     .tight(width: 240.w, height: 80.w)
  60.                     .onTap(() => Navigator.of(context).pop()),
  61.                 <Widget>[
  62.                   const TextWidget.body(
  63.                     '确定',
  64.                     color: Colors.white,
  65.                   )
  66.                 ]
  67.                     .toRow(mainAxisAlignment: MainAxisAlignment.center)
  68.                     .card(color: const Color(0xffE93323))
  69.                     .tight(width: 240.w, height: 80.w)
  70.                     .onTap(() {
  71.                   controller.clearSearchHistory();
  72.                   Navigator.of(context).pop();
  73.                 }),
  74.               ]
  75.                   .toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween)
  76.                   .paddingOnly(left: 30.w, right: 30.w, bottom: 40.w),
  77.             );
  78.           },
  79.         );
  80.         }),
  81.       ].toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween).paddingHorizontal(30.w),
  82.       <Widget>[
  83.         for(var i = 0; i < controller.searchHistory.length; i++)
  84.         Chip(
  85.           label: TextWidget.body(controller.searchHistory[i],size: 24.sp,color: AppTheme.color999,),
  86.           backgroundColor: AppTheme.blockBgColor,
  87.           shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.w)),
  88.           deleteIconColor: AppTheme.color999,
  89.           onDeleted: () {
  90.             controller.deleteSearchHistory(controller.searchHistory[i]);
  91.           },
  92.         )
  93.       ].toWrap(spacing: 20.w,runSpacing: 0,).paddingLeft(30.w),
  94.     ].toColumn(crossAxisAlignment: CrossAxisAlignment.start);
  95.   }
  96.   // 主视图
  97.   Widget _buildView(BuildContext context) {
  98.     return <Widget>[
  99.       _buildSearch(),
  100.       // SizedBox(height: 30.w,),
  101.       // _buildHotSearch(),
  102.       SizedBox(height: 30.w,),
  103.       _buildHistory(context),
  104.       controller.searchHistory.isEmpty ? const EmptyState() : const SizedBox()
  105.     ].toColumn();
  106.   }
  107.   @override
  108.   Widget build(BuildContext context) {
  109.     return GetBuilder<SearchGoodsController>(
  110.       init: SearchGoodsController(),
  111.       id: "search_goods",
  112.       builder: (_) {
  113.         return Scaffold(
  114.           backgroundColor: AppTheme.pageBgColor, // 自定义颜色
  115.           appBar: const TDNavBar(
  116.             height: 44,
  117.             title: "搜索",
  118.             titleFontWeight: FontWeight.w600,
  119.             backgroundColor: Colors.white,
  120.             screenAdaptation: true,
  121.             useDefaultBack: true,
  122.           ),
  123.           body: SingleChildScrollView(
  124.             child: _buildView(context),
  125.           ),
  126.         );
  127.       },
  128.     );
  129.   }
  130. }
复制代码
controller
  1. import 'package:chenyanzhenxuan/common/index.dart';
  2. import 'package:get/get.dart';
  3. import 'package:flutter/material.dart';
  4. class SearchGoodsController extends GetxController {
  5.   SearchGoodsController();
  6.   // 搜索框
  7.   final searchController = TextEditingController();
  8.   // 搜索关键词
  9.   String searchKey = '';
  10.   // 搜索历史
  11.   List<String> searchHistory = [];
  12.   @override
  13.   void onReady() {
  14.     super.onReady();
  15.     _initData();
  16.   }
  17.   @override
  18.   void onClose() {
  19.     super.onClose();
  20.     searchController.dispose();
  21.   }
  22.   // 初始化数据
  23.   void _initData() {
  24.     searchHistory = Storage().getList('search_history');
  25.     update(["search_goods"]);
  26.   }
  27.   // 搜索框发送改变
  28.   void onSearchChange(String value) {
  29.     if(value.isEmpty) return Loading.toast("请输入搜索内容");
  30.     searchController.text = value;
  31.     // 查找是否存在该搜索词
  32.     final index = searchHistory.indexOf(value);
  33.     // 如果已存在,删除旧值
  34.     if (index != -1) {
  35.       searchHistory.removeAt(index);
  36.     }
  37.     // 将新搜索词添加到数组开头
  38.     searchHistory.insert(0, value);
  39.     // 限制历史记录条数
  40.     if (searchHistory.length > 20) {
  41.       searchHistory = searchHistory.sublist(0, 20);
  42.     }
  43.     // 保存更新后的搜索历史
  44.     Storage().setList('search_history', searchHistory);
  45.     // 使用 Get.toNamed 的返回回调来刷新数据
  46.     Get.toNamed('/goods_list_page', arguments: {
  47.       'searchValue': value,
  48.       'title': '搜索',
  49.       'type': 1,
  50.     })?.then((_) {
  51.       searchController.text = '';
  52.       _initData(); // 返回时重新加载数据
  53.     });
  54.     update(["search_goods"]);
  55.   }
  56.   // 清空搜索历史
  57.   void clearSearchHistory() {
  58.     searchHistory = [];
  59.     Storage().setList('search_history', searchHistory);
  60.     update(["search_goods"]);
  61.   }
  62.   // 删除单个历史记录
  63.   void deleteSearchHistory(String value) {
  64.     searchHistory.remove(value);
  65.     Storage().setList('search_history', searchHistory);
  66.     update(["search_goods"]);
  67.   }
  68.   
  69. }
复制代码
SearchWidget
  1. import 'package:ducafe_ui_core/ducafe_ui_core.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:tdesign_flutter/tdesign_flutter.dart';
  5. import 'package:chenyanzhenxuan/common/index.dart';
  6. class SearchWidget extends StatelessWidget {
  7.   // 类型
  8.   final String type;
  9.   // 搜索框控制器
  10.   final TextEditingController? controller;
  11.   // 输入框背景色
  12.   final Color? inputBgColor;
  13.   // 搜索框发送改变
  14.   final Function(String value)? onChange;
  15.   const SearchWidget({
  16.     super.key,
  17.     required this.type,
  18.     this.controller,
  19.     this.inputBgColor,
  20.     this.onChange,
  21.   });
  22.   @override
  23.   Widget build(BuildContext context) {
  24.     return <Widget>[
  25.       <Widget>[
  26.         TDImage(
  27.           assetUrl: type == 'text' ? 'assets/img/search.png' : 'assets/img/search.png',
  28.           width: 32.w,
  29.           height: 32.w,
  30.         ),
  31.         SizedBox(width: 20.w),
  32.         type == 'text' ? TextWidget.body('搜索您要找的商品名称', size: 28.sp, color: AppTheme.color999)
  33.         : InputWidget(
  34.           placeholder: "搜索您要找的商品名称",
  35.           controller: controller,
  36.         ).width(450.w),
  37.       ].toRow(),
  38.       <Widget>[
  39.         TextWidget.body('搜索', size: 26.sp, color: AppTheme.colorfff),
  40.       ].toRow(mainAxisAlignment: MainAxisAlignment.center)
  41.       .card(color: AppTheme.error,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.w)))
  42.       .tight(width: 120.w,height: 60.w)
  43.       .onTap(() {
  44.         if(type == 'text'){
  45.           Get.toNamed('/search_goods_page');
  46.         }else{
  47.           if(type == 'input' && controller?.text != null){
  48.             onChange!(controller!.text);
  49.           }
  50.         }
  51.       }),
  52.     ]
  53.     .toRow(mainAxisAlignment: MainAxisAlignment.spaceBetween)
  54.     .paddingOnly(left: 30.w,right: 4.w)
  55.     .card(
  56.       color: inputBgColor,
  57.       shape: RoundedRectangleBorder(
  58.         borderRadius: BorderRadius.circular(30.w)
  59.       )
  60.     )
  61.     .tight(width: 690.w, height: 68.w)
  62.     .onTap(() {
  63.       if(type == 'text'){
  64.         Get.toNamed('/search_goods_page');
  65.       }
  66.     });
  67.   }
  68. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表