flutter/lib/pages/search/index.dart
2025-08-28 16:58:47 +08:00

218 lines
6.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:loopin/components/my_toast.dart';
import '../../behavior/custom_scroll_behavior.dart';
class SearchPage extends StatefulWidget {
const SearchPage({super.key});
@override
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
final TextEditingController _searchController = TextEditingController();
final GetStorage _storage = GetStorage();
List<dynamic> _searchHistory = [];
@override
void initState() {
super.initState();
_loadSearchHistory();
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
// 加载搜索历史
void _loadSearchHistory() {
setState(() {
_searchHistory = _storage.read('searchHistory') ?? [];
});
}
// 保存搜索历史
void _saveSearchHistory() {
_storage.write('searchHistory', _searchHistory);
}
// 添加搜索项
void _addSearchItem(String query) {
if (query.trim().isEmpty) return;
setState(() {
// 移除重复项
_searchHistory.remove(query);
// 添加到开头
_searchHistory.insert(0, query);
// 暂时限制历史记录数量未10条
if (_searchHistory.length > 10) {
_searchHistory = _searchHistory.sublist(0, 10);
}
});
_saveSearchHistory();
}
// 清除单个搜索历史
void _removeSearchItem(int index) {
setState(() {
_searchHistory.removeAt(index);
});
_saveSearchHistory();
}
// 清除所有搜索历史
void _clearAllHistory() {
setState(() {
_searchHistory.clear();
});
_saveSearchHistory();
MyToast().tip(
title: '搜索历史已清除',
position: 'center',
type: 'success',
);
}
// 执行搜索
void _performSearch() {
final searchWords = _searchController.text.trim();
if (searchWords.isNotEmpty) {
_addSearchItem(searchWords);
_searchController.clear();
FocusScope.of(context).unfocus();
// 去搜索结果页支持带着搜索文字和搜索tab索引
Get.toNamed('/search-result', arguments: {
'searchWords':searchWords,
'tab':0
});
} else {
MyToast().tip(
title: '请输入搜索内容',
position: 'center',
type: 'error',
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.black,
foregroundColor: Colors.white,
elevation: 0,
title: Container(
height: 40,
decoration: BoxDecoration(
color: Colors.grey[900],
borderRadius: BorderRadius.circular(20),
),
child: TextField(
controller: _searchController,
style: const TextStyle(color: Colors.white, fontSize: 16),
decoration: InputDecoration(
hintText: '请输入内容~',
hintStyle: TextStyle(color: Colors.grey[500], fontSize: 16),
border: InputBorder.none,
prefixIcon: Icon(Icons.search, color: Colors.grey[500], size: 20),
suffixIcon: _searchController.text.isNotEmpty
? IconButton(
icon: Icon(Icons.close, color: Colors.grey[500], size: 20),
onPressed: () {
_searchController.clear();
setState(() {});
},
)
: null,
contentPadding: const EdgeInsets.symmetric(vertical: 10),
),
onSubmitted: (_) => _performSearch(),
onChanged: (_) => setState(() {}),
),
),
actions: [
TextButton(
onPressed: _performSearch,
child: const Text('搜索', style: TextStyle(color: Colors.white, fontSize: 16)),
),
],
),
body: ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 搜索历史
if (_searchHistory.isNotEmpty) ...[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'搜索历史',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold
),
),
TextButton(
onPressed: _clearAllHistory,
child: const Text(
'清除所有',
style: TextStyle(color: Colors.grey, fontSize: 14),
),
),
],
),
const SizedBox(height: 12),
Wrap(
spacing: 8,
runSpacing: 8,
children: List.generate(_searchHistory.length, (index) {
return GestureDetector(
onTap: () {
_searchController.text = _searchHistory[index];
_performSearch();
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.grey[800],
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
_searchHistory[index],
style: const TextStyle(color: Colors.white),
),
const SizedBox(width: 6),
GestureDetector(
onTap: () => _removeSearchItem(index),
child: Icon(Icons.close, size: 16, color: Colors.grey[500]),
),
],
),
),
);
}),
),
const SizedBox(height: 24),
],
],
),
),
),
);
}
}