在移動應用開發中,搜索功能是一個非常重要的功能。無論是電商應用、社交應用還是新聞應用,搜索功能都能幫助用戶快速找到他們需要的內容。在Flutter中,我們可以通過自定義AppBar來實現一個帶有搜索框的AppBar。本文將詳細介紹如何在Flutter中實現一個自定義搜索框AppBar,并探討一些相關的進階技巧。
在開始之前,我們需要先理解Flutter中的AppBar
和SearchBar
的基本概念。
AppBar
是Flutter中常用的一個組件,通常用于顯示應用的標題、導航按鈕、操作按鈕等。AppBar
通常位于屏幕的頂部,并且可以包含多個子組件,如Text
、IconButton
等。
SearchBar
是一個用于輸入搜索關鍵詞的組件。在Flutter中,我們可以使用TextField
來實現一個簡單的搜索框。TextField
允許用戶輸入文本,并且可以通過設置不同的屬性來定制其外觀和行為。
接下來,我們將通過一個簡單的例子來演示如何在Flutter中實現一個帶有搜索框的AppBar。
首先,我們需要創建一個新的Flutter項目。如果你已經有一個項目,可以跳過這一步。
flutter create custom_search_appbar
cd custom_search_appbar
main.dart
文件接下來,我們需要修改lib/main.dart
文件,添加一個帶有搜索框的AppBar。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Search AppBar',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SearchAppBarDemo(),
);
}
}
class SearchAppBarDemo extends StatefulWidget {
@override
_SearchAppBarDemoState createState() => _SearchAppBarDemoState();
}
class _SearchAppBarDemoState extends State<SearchAppBarDemo> {
final TextEditingController _searchController = TextEditingController();
bool _isSearching = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _isSearching
? TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.white70),
),
style: TextStyle(color: Colors.white),
autofocus: true,
)
: Text('Custom Search AppBar'),
actions: [
IconButton(
icon: Icon(_isSearching ? Icons.close : Icons.search),
onPressed: () {
setState(() {
_isSearching = !_isSearching;
if (!_isSearching) {
_searchController.clear();
}
});
},
),
],
),
body: Center(
child: Text('Search results will appear here'),
),
);
}
}
在這個例子中,我們創建了一個SearchAppBarDemo
類,它繼承自StatefulWidget
。在_SearchAppBarDemoState
類中,我們定義了一個TextEditingController
用于控制搜索框的輸入內容,以及一個_isSearching
布爾變量用于控制是否顯示搜索框。
在AppBar
的title
屬性中,我們使用了一個條件語句來判斷是否顯示搜索框。如果_isSearching
為true
,則顯示一個TextField
作為搜索框;否則,顯示一個普通的Text
作為標題。
在AppBar
的actions
屬性中,我們添加了一個IconButton
,用于切換搜索框的顯示狀態。當用戶點擊這個按鈕時,_isSearching
的值會被切換,并且如果搜索框被關閉,搜索框中的內容會被清空。
現在,我們可以運行這個項目,看看效果如何。
flutter run
運行后,你會看到一個帶有搜索框的AppBar。點擊右上角的搜索圖標,搜索框會顯示出來,再次點擊則會關閉搜索框。
在上面的例子中,我們只是實現了一個簡單的搜索框AppBar,但并沒有實現實際的搜索功能。接下來,我們將進一步完善這個例子,添加搜索功能。
首先,我們需要一些數據來進行搜索。我們可以創建一個簡單的列表來模擬數據。
final List<String> _data = [
'Apple',
'Banana',
'Orange',
'Mango',
'Pineapple',
'Strawberry',
'Blueberry',
'Raspberry',
'Watermelon',
'Grape',
];
接下來,我們需要根據用戶輸入的關鍵詞來過濾數據。我們可以使用List
的where
方法來實現這一點。
List<String> _searchResults = [];
void _search(String query) {
setState(() {
_searchResults = _data
.where((item) => item.toLowerCase().contains(query.toLowerCase()))
.toList();
});
}
在這個方法中,我們遍歷_data
列表,并使用contains
方法來判斷每個元素是否包含用戶輸入的關鍵詞。如果包含,則將該元素添加到_searchResults
列表中。
接下來,我們需要在UI中顯示搜索結果。我們可以使用ListView
來顯示搜索結果。
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _searchResults.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchResults[index]),
);
},
),
),
],
),
在這個例子中,我們使用ListView.builder
來動態生成搜索結果列表。itemCount
屬性指定了列表的長度,itemBuilder
屬性則用于生成每個列表項。
最后,我們需要在用戶輸入關鍵詞時調用_search
方法來更新搜索結果。我們可以在TextField
的onChanged
回調中調用_search
方法。
TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.white70),
),
style: TextStyle(color: Colors.white),
autofocus: true,
onChanged: _search,
),
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Search AppBar',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SearchAppBarDemo(),
);
}
}
class SearchAppBarDemo extends StatefulWidget {
@override
_SearchAppBarDemoState createState() => _SearchAppBarDemoState();
}
class _SearchAppBarDemoState extends State<SearchAppBarDemo> {
final TextEditingController _searchController = TextEditingController();
bool _isSearching = false;
final List<String> _data = [
'Apple',
'Banana',
'Orange',
'Mango',
'Pineapple',
'Strawberry',
'Blueberry',
'Raspberry',
'Watermelon',
'Grape',
];
List<String> _searchResults = [];
void _search(String query) {
setState(() {
_searchResults = _data
.where((item) => item.toLowerCase().contains(query.toLowerCase()))
.toList();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _isSearching
? TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.white70),
),
style: TextStyle(color: Colors.white),
autofocus: true,
onChanged: _search,
)
: Text('Custom Search AppBar'),
actions: [
IconButton(
icon: Icon(_isSearching ? Icons.close : Icons.search),
onPressed: () {
setState(() {
_isSearching = !_isSearching;
if (!_isSearching) {
_searchController.clear();
_searchResults.clear();
}
});
},
),
],
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _searchResults.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchResults[index]),
);
},
),
),
],
),
);
}
}
現在,我們可以運行這個項目,看看效果如何。
flutter run
運行后,你會看到一個帶有搜索框的AppBar。當你在搜索框中輸入關鍵詞時,搜索結果會實時更新并顯示在屏幕上。
在上面的例子中,我們已經實現了一個基本的搜索功能。接下來,我們將進一步優化這個例子,使其更加完善。
我們可以添加一個搜索歷史功能,記錄用戶最近搜索的關鍵詞,并在用戶點擊搜索框時顯示這些歷史記錄。
首先,我們需要一個列表來存儲搜索歷史。
final List<String> _searchHistory = [];
接下來,我們需要在用戶搜索時更新搜索歷史。
void _search(String query) {
setState(() {
_searchResults = _data
.where((item) => item.toLowerCase().contains(query.toLowerCase()))
.toList();
if (query.isNotEmpty && !_searchHistory.contains(query)) {
_searchHistory.add(query);
}
});
}
在這個方法中,我們在用戶搜索時檢查搜索歷史中是否已經存在該關鍵詞。如果不存在,則將其添加到搜索歷史中。
接下來,我們需要在用戶點擊搜索框時顯示搜索歷史。我們可以使用一個ListView
來顯示搜索歷史。
body: Column(
children: [
Expanded(
child: _isSearching && _searchController.text.isEmpty
? ListView.builder(
itemCount: _searchHistory.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchHistory[index]),
onTap: () {
setState(() {
_searchController.text = _searchHistory[index];
_search(_searchHistory[index]);
});
},
);
},
)
: ListView.builder(
itemCount: _searchResults.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchResults[index]),
);
},
),
),
],
),
在這個例子中,我們使用了一個條件語句來判斷是否顯示搜索歷史。如果_isSearching
為true
且搜索框為空,則顯示搜索歷史;否則,顯示搜索結果。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Search AppBar',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SearchAppBarDemo(),
);
}
}
class SearchAppBarDemo extends StatefulWidget {
@override
_SearchAppBarDemoState createState() => _SearchAppBarDemoState();
}
class _SearchAppBarDemoState extends State<SearchAppBarDemo> {
final TextEditingController _searchController = TextEditingController();
bool _isSearching = false;
final List<String> _data = [
'Apple',
'Banana',
'Orange',
'Mango',
'Pineapple',
'Strawberry',
'Blueberry',
'Raspberry',
'Watermelon',
'Grape',
];
List<String> _searchResults = [];
final List<String> _searchHistory = [];
void _search(String query) {
setState(() {
_searchResults = _data
.where((item) => item.toLowerCase().contains(query.toLowerCase()))
.toList();
if (query.isNotEmpty && !_searchHistory.contains(query)) {
_searchHistory.add(query);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _isSearching
? TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'Search...',
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.white70),
),
style: TextStyle(color: Colors.white),
autofocus: true,
onChanged: _search,
)
: Text('Custom Search AppBar'),
actions: [
IconButton(
icon: Icon(_isSearching ? Icons.close : Icons.search),
onPressed: () {
setState(() {
_isSearching = !_isSearching;
if (!_isSearching) {
_searchController.clear();
_searchResults.clear();
}
});
},
),
],
),
body: Column(
children: [
Expanded(
child: _isSearching && _searchController.text.isEmpty
? ListView.builder(
itemCount: _searchHistory.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchHistory[index]),
onTap: () {
setState(() {
_searchController.text = _searchHistory[index];
_search(_searchHistory[index]);
});
},
);
},
)
: ListView.builder(
itemCount: _searchResults.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_searchResults[index]),
);
},
),
),
],
),
);
}
}
我們可以添加一個清除搜索歷史的功能,允許用戶清除所有的搜索歷史。
首先,我們需要在搜索歷史列表的頂部添加一個清除按鈕。
ListView.builder(
itemCount: _searchHistory.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
return ListTile(
title: Text('Clear History'),
onTap: () {
setState(() {
_searchHistory.clear();
});
},
);
}
return ListTile(
title: Text(_searchHistory[index - 1]),
onTap: () {
setState(() {
_searchController.text = _searchHistory[index - 1];
_search(_searchHistory[index - 1]);
});
},
);
},
),
在這個例子中,我們在搜索歷史列表的頂部添加了一個ListTile
,用于清除搜索歷史。當用戶點擊這個ListTile
時,_searchHistory
列表會被清空。
”`dart import ‘package:flutter/material.dart’;
void main() { runApp(MyApp()); }
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: ‘Custom Search AppBar’, theme: ThemeData( primarySwatch: Colors.blue, ), home: SearchAppBarDemo(), ); } }
class SearchAppBarDemo extends StatefulWidget { @override _SearchAppBarDemoState createState() => _SearchAppBarDemoState(); }
class _SearchAppBarDemoState extends State
void _search(String query) { setState(() { _searchResults = _data .where((item) => item.toLowerCase().contains(query.toLowerCase())) .toList(); if (query.isNotEmpty && !_searchHistory.contains(query)) { _searchHistory.add(query); } }); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: _isSearching ? TextField( controller: _searchController, decoration: InputDecoration( hintText: ‘Search…’, border: InputBorder.none, hintStyle: TextStyle(color: Colors.white70), ), style: TextStyle(color: Colors.white), autofocus: true, onChanged: _search, ) : Text(‘Custom Search AppBar’), actions: [ IconButton( icon: Icon(_isSearching ? Icons.close : Icons.search), onPressed: () { setState(() { _isSearching = !_isSearching; if (!_isSearching) { _searchController.clear(); _searchResults.clear(); } }); }, ), ], ), body: Column( children: [ Expanded( child: _isSearching && _searchController.text.isEmpty ? ListView.builder( itemCount: _searchHistory.length + 1, itemBuilder: (context, index) { if (index == 0) { return ListTile( title: Text(‘Clear History’), onTap: () { setState(() { _searchHistory.clear(); }); }, ); } return ListTile( title: Text(_searchHistory[index - 1]), onTap: () { setState(() { _search
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。