import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../../providers/weather_provider.dart'; class WeatherSearchScreen extends StatefulWidget { const WeatherSearchScreen({super.key}); @override State createState() => _WeatherSearchScreenState(); } class _WeatherSearchScreenState extends State { final TextEditingController _searchController = TextEditingController(); List> _searchResults = []; bool _isSearching = false; @override void dispose() { _searchController.dispose(); super.dispose(); } Future _searchCities(String query) async { if (query.isEmpty) { setState(() { _searchResults = []; }); return; } setState(() { _isSearching = true; }); try { final results = await context.read().searchCities(query); setState(() { _searchResults = results; }); } finally { setState(() { _isSearching = false; }); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.pop(context), ), title: const Text( 'Search City', style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), ), body: Column( children: [ // 搜索框 Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: Colors.grey[900], borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.grey[700]!, width: 1), ), child: TextField( controller: _searchController, style: const TextStyle(color: Colors.white), decoration: InputDecoration( hintText: 'Enter city name...', hintStyle: TextStyle(color: Colors.grey[400]), border: InputBorder.none, icon: Icon(Icons.search, color: Colors.grey[400]), suffixIcon: _searchController.text.isNotEmpty ? IconButton( icon: Icon(Icons.clear, color: Colors.grey[400]), onPressed: () { _searchController.clear(); _searchCities(''); }, ) : null, ), onChanged: (value) { setState(() {}); // 更新清除按钮显示 _searchCities(value); }, onSubmitted: _searchCities, ), ), // 搜索结果 Expanded(child: _buildSearchResults()), ], ), ); } Widget _buildSearchResults() { if (_isSearching) { return const Center( child: CircularProgressIndicator(color: Colors.pinkAccent), ); } if (_searchController.text.isEmpty) { return _buildRecentAndFavorites(); } if (_searchResults.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.search_off, size: 64, color: Colors.grey[400]), const SizedBox(height: 16), Text( 'No cities found', style: TextStyle(color: Colors.grey[400], fontSize: 16), ), const SizedBox(height: 8), Text( 'Try different keywords', style: TextStyle(color: Colors.grey[500], fontSize: 14), ), ], ), ); } return ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: _searchResults.length, itemBuilder: (context, index) { final city = _searchResults[index]; return _buildCityItem( name: city['name'] ?? '', region: city['region'] ?? '', country: city['country'] ?? '', onTap: () => _selectCity(city['name'] ?? ''), ); }, ); } Widget _buildRecentAndFavorites() { return Consumer( builder: (context, weatherProvider, child) { return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 收藏位置 if (weatherProvider.favoriteLocations.isNotEmpty) ...[ _buildSectionTitle('Favorite Locations'), const SizedBox(height: 12), ...weatherProvider.favoriteLocations.map( (location) => _buildCityItem( name: location, region: '', country: '', isFavorite: true, onTap: () => _selectCity(location), ), ), const SizedBox(height: 24), ], // 热门城市 _buildSectionTitle('Popular Cities'), const SizedBox(height: 12), ..._getPopularCities().map( (city) => _buildCityItem( name: city['name']!, region: city['region']!, country: city['country']!, onTap: () => _selectCity(city['name']!), ), ), ], ), ); }, ); } Widget _buildSectionTitle(String title) { return Text( title, style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ); } Widget _buildCityItem({ required String name, required String region, required String country, bool isFavorite = false, required VoidCallback onTap, }) { return Container( margin: const EdgeInsets.only(bottom: 8), child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), tileColor: Colors.grey[900], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), leading: Icon( isFavorite ? Icons.favorite : Icons.location_on, color: isFavorite ? Colors.red : Colors.pinkAccent, ), title: Text( name, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500, ), ), subtitle: region.isNotEmpty || country.isNotEmpty ? Text( [region, country].where((s) => s.isNotEmpty).join(', '), style: TextStyle(color: Colors.grey[400], fontSize: 14), ) : null, trailing: const Icon( Icons.arrow_forward_ios, color: Colors.grey, size: 16, ), onTap: onTap, ), ); } List> _getPopularCities() { return [ {'name': 'New York', 'region': 'New York', 'country': 'USA'}, {'name': 'Los Angeles', 'region': 'California', 'country': 'USA'}, {'name': 'Chicago', 'region': 'Illinois', 'country': 'USA'}, {'name': 'Houston', 'region': 'Texas', 'country': 'USA'}, {'name': 'Phoenix', 'region': 'Arizona', 'country': 'USA'}, {'name': 'Philadelphia', 'region': 'Pennsylvania', 'country': 'USA'}, {'name': 'San Antonio', 'region': 'Texas', 'country': 'USA'}, {'name': 'San Diego', 'region': 'California', 'country': 'USA'}, {'name': 'Dallas', 'region': 'Texas', 'country': 'USA'}, {'name': 'San Jose', 'region': 'California', 'country': 'USA'}, {'name': 'Austin', 'region': 'Texas', 'country': 'USA'}, {'name': 'Jacksonville', 'region': 'Florida', 'country': 'USA'}, {'name': 'Fort Worth', 'region': 'Texas', 'country': 'USA'}, {'name': 'Columbus', 'region': 'Ohio', 'country': 'USA'}, {'name': 'San Francisco', 'region': 'California', 'country': 'USA'}, ]; } void _selectCity(String cityName) { // 获取选中城市的天气 context.read().getWeatherByCity(cityName); // 返回到天气主页面 Navigator.pop(context); } }