静态页面
import 'package:flutter/material.dart';
import 'package:flutterdemo/app/services/screenAdapter.dart';
import 'package:get/get.dart';
import '../controllers/search_controller.dart';
class SearchView extends GetView<SearchControllerS> {
const SearchView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(246, 246, 246, 1),
appBar: AppBar(
title: Container(
width: ScreenAdapter.width(840),
height: ScreenAdapter.height(96),
decoration: BoxDecoration(
color: const Color.fromRGBO(246, 246, 246, 1),
borderRadius: BorderRadius.circular(30),
),
child: TextField(
autofocus: true,
style: TextStyle(
// 修改框框的字体
fontSize: ScreenAdapter.fontSize(36)
),
decoration: InputDecoration(
// 配置padding值
contentPadding: const EdgeInsets.all(0),
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide.none
)
),
),
),
centerTitle: true,
backgroundColor: Colors.white,
actions: [
TextButton(
onPressed: (){},
child: Text("搜索",
style: TextStyle(color: Colors.black54,fontSize: ScreenAdapter.fontSize(36)))
)
],
elevation: 0,
),
body: ListView(
padding: EdgeInsets.all(ScreenAdapter.height(20)),
children: [
Padding(
padding: EdgeInsets.only(bottom: ScreenAdapter.height(20)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("搜索历史",style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenAdapter.fontSize(42)
)),
const Icon(Icons.delete_forever_outlined)
],
),
),
Wrap(
children: [
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
],
),
const SizedBox(height: 20),
Padding(
padding: EdgeInsets.only(bottom: ScreenAdapter.height(20)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("猜你喜欢",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenAdapter.fontSize(42))
),
const Icon(Icons.refresh)
],
),
),
Wrap(
children: [
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Text("手机"),
),
],
),
const SizedBox(height: 20),
// 热销商品
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)
),
child: Column(
children: [
Container(
width: double.infinity,
height: ScreenAdapter.height(138),
decoration: const BoxDecoration(
color: Colors.white,
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/hot_search.png"
))
),
),
Container(
padding: EdgeInsets.all(ScreenAdapter.width(20)),
child: GridView.builder(
shrinkWrap: true, // 收缩
itemCount: 8, //必须设置
// todo
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: ScreenAdapter.width(40),
mainAxisSpacing: ScreenAdapter.height(20),
childAspectRatio: 3/1
),
itemBuilder: ((context,index){
return Row(
children: [
Container(
alignment: Alignment.center,
width: ScreenAdapter.width(120),
padding: EdgeInsets.all(ScreenAdapter.width(10)),
child: Image.network(
"https://www.itying.com/images/shouji.png",
fit: BoxFit.fitHeight,
),
),
Expanded(
child: Container(
padding: EdgeInsets.all(ScreenAdapter.width(10)),
alignment: Alignment.topLeft,
child: const Text("小米净化器 热水器 小米手机"),
)
)
],
);
})
),
)
],
),
)
],
)
);
}
}
监听键盘回车 跳转到搜索页面
child: TextField(
autofocus: true,
style: TextStyle(
// 修改框框的字体
fontSize: ScreenAdapter.fontSize(36)
),
decoration: InputDecoration(
// 配置padding值
contentPadding: const EdgeInsets.all(0),
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide.none
)
),
// 输入触发方法
onChanged: (value){
controller.keyworld = value;
},
// 监听键盘的回车事件
onSubmitted: (value){
// 替换路由
Get.offAndToNamed("/product-list",arguments: {"keywords":value});
},
),
保存历史搜索记录 删除历史记录 长按删除
shared_preferences: ^2.2.2
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class Storage {
static setData(String key, dynamic value) async {
var prefs = await SharedPreferences.getInstance();
prefs.setString(key, json.encode(value));
}
static getData(String key) async {
try {
var prefs = await SharedPreferences.getInstance();
String? tempData = prefs.getString(key);
if (tempData != null) {
return json.decode(tempData);
} else {
return null;
}
} catch (e) {
return null;
}
}
static removeData(String key) async {
var prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
static clear(String key) async {
var prefs = await SharedPreferences.getInstance();
prefs.clear();
}
}
import 'package:flutterdemo/app/services/storage.dart';
class SearchServices{
// 保存历史搜索记录
static setHistoryData(keywords) async{
/*
1、获取本地存储里面的数据 (searchList)
2、判断本地存储是否有数据
2.1、如果有数据
1、读取本地存储的数据
2、判断本地存储中有没有当前数据,
如果有不做操作、
如果没有当前数据,本地存储的数据和当前数据拼接后重新写入
2.2、如果没有数据
直接把当前数据放在数组中写入到本地存储
*/
List? searchListData = await Storage.getData("searchList");
if(searchListData != null){
//todo
var hasData = searchListData.any((v){
return v == keywords;
});
if(!hasData){
searchListData.add(keywords);
await Storage.setData("searchList", searchListData);
}
}else{
List tempList = [];
tempList.add(keywords);
await Storage.setData("searchList", tempList);
}
}
// 获取历史搜索记录
static Future<List> getHistoryData() async{
List? searchListData = await Storage.getData("searchList");
if(searchListData != null){
return searchListData;
}else{
return [];
}
}
// 删除搜索记录
static deleteHistoryData(keywords) async{
List? searchListData = await Storage.getData("searchList");
if(searchListData != null){
searchListData.remove(keywords);
await Storage.setData("searchList", searchListData);
}
}
// 清空搜索记录
static clearHistoryData() async{
await Storage.clear('searchList');
}
}
constroller
import 'package:flutterdemo/app/services/searchServices.dart';
import 'package:flutterdemo/app/services/storage.dart';
import 'package:get/get.dart';
// 提示: 新版本的Flutter中SearchController和Flutter内置的类名有冲突,
// 所以SeacherChConroller需要改成其他名称
class SearchControllerS extends GetxController {
//TODO: Implement SearchController
String keyworld = "";
RxList historyList = [].obs;
@override
void onInit() {
super.onInit();
getHistoryData();
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {
super.onClose();
}
getHistoryData() async{
var tempList = await SearchServices.getHistoryData();
if(tempList.isNotEmpty){
historyList.addAll(tempList);
update();
}
}
clearHistoryData() async{
await SearchServices.clearHistoryData();
historyList.clear();
update();
}
removeHistoryData(keyworld) async{
var tempList = await SearchServices.getHistoryData();
if(tempList.isNotEmpty){
tempList.remove(keyworld);
await Storage.setData("searchList", tempList);
// 注意
historyList.remove(keyworld);
update();
}
}
}
// 监听键盘的回车事件
onSubmitted: (value){
// 保存搜索记录
SearchServices.setHistoryData(value);
// 替换路由
Get.offAndToNamed("/product-list",arguments: {"keywords":value});
},
IconButton(
onPressed: (){
Get.bottomSheet(Container(
padding: EdgeInsets.all(ScreenAdapter.width(20)),
color: Colors.white,
width: ScreenAdapter.width(1080),
height: ScreenAdapter.height(360),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("您确定要清空历史记录吗?",style: TextStyle(
fontSize: ScreenAdapter.fontSize(48)
),)
],
),
SizedBox(height: ScreenAdapter.height(40)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width: ScreenAdapter.width(420),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color.fromARGB(123, 151, 147, 147)),
foregroundColor: MaterialStateProperty.all(Colors.white)
),
onPressed: (){
Get.back();
},
child:const Text("取消"))
),
SizedBox(
width: ScreenAdapter.width(420),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color.fromARGB(123, 151, 147, 147)),
foregroundColor: MaterialStateProperty.all(Colors.red)
),
onPressed: (){},
child: Text("确定")),
)
],
)
],
),
));
},
icon: const Icon(Icons.delete_forever_outlined))
Obx(() => Wrap(
// todo 循环语句
children: controller.historyList.map((value) => GestureDetector(
onLongPress: (){
Get.defaultDialog(
title: "提示信息!",
middleText: "您确定要删除吗?",
confirm: ElevatedButton(
onPressed: (){
controller.removeHistoryData(value);
Get.back();
}, child: const Text("确定")
),
cancel: ElevatedButton(
onPressed: (){
Get.back();
},
child: const Text("取消"))
);
},
child: Container(
padding: EdgeInsets.fromLTRB(
ScreenAdapter.width(32),
ScreenAdapter.width(16),
ScreenAdapter.width(32),
ScreenAdapter.width(16),
),
margin: EdgeInsets.all(ScreenAdapter.height(16)),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Text(value),
),
)).toList(),