Flutter 搜尋頁實現
在一般的 App 頁面,可能都需要搜尋功能,常見的就是在主頁上面有一個搜尋欄,點選會跳轉到一個搜尋頁面。
在 flutter 中,也有這樣的功能實現,主要是通過 showSearch 就能跳轉到一個搜尋頁面。接下來看一下如何實現。
1、自定義 SearchDelegate
使用 flutter 提供的搜尋頁面,需要繼承 SearchDelegate 實現自己的 Delegate。 SearchDelegate 提供了一些方法需要我們自己重寫來實現我們自己的功能。
- buildActions 顯示在最右邊的圖示列表。
- buildLeading 搜尋欄左邊的圖示,一般都是返回。
- buildResults 這個回撥裡進行搜尋和並返回自己的搜尋結果。
- buildSuggestions 返回建議搜尋結果。
示例:
class SearchBarViewDelegate extends SearchDelegate<String>{
String searchHint = "請輸入搜尋內容...";
var sourceList = [
"dart",
"dart 入門",
"flutter",
"flutter 程式設計",
"flutter 程式設計開發",
];
var suggestList = [
"flutter",
"flutter 程式設計開發"
];
@override
String get searchFieldLabel => searchHint;
@override
List<Widget> buildActions(BuildContext context) {
///顯示在最右邊的控制元件列表
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: (){
query = "";
///搜尋建議的內容
showSuggestions(context);
},
),
IconButton(
icon: Icon(Icons.search),
onPressed: ()=>query = "",
)
];
}
///左側帶動畫的控制元件,一般都是返回
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow, progress: transitionAnimation
),
///呼叫 close 關閉 search 介面
onPressed: ()=>close(context,null),
);
}
///展示搜尋結果
@override
Widget buildResults(BuildContext context) {
List<String> result = List();
///模擬搜尋過程
for (var str in sourceList){
///query 就是輸入框的 TextEditingController
if (query.isNotEmpty && str.contains(query)){
result.add(str);
}
}
///展示搜尋結果
return ListView.builder(
itemCount: result.length,
itemBuilder: (BuildContext context, int index)=>ListTile(
title: Text(result[index]),
),
);
}
@override
Widget buildSuggestions(BuildContext context) {
List<String> suggest = query.isEmpty ? suggestList : sourceList.where((input)=>input.startsWith(query)).toList();
return ListView.builder(
itemCount: suggest.length,
itemBuilder: (BuildContext context, int index)=>
InkWell(
child: ListTile(
title: RichText(
text: TextSpan(
text: suggest[index].substring(0, query.length),
style: TextStyle(color: Colors.blue,fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggest[index].substring(query.length),
style: TextStyle(color: Colors.grey),
),
],
),
),
),
onTap: (){
// query.replaceAll("", suggest[index].toString());
searchHint = "";
query = suggest[index].toString();
showResults(context);
},
),
);
}
}
複製程式碼
2、使用自定義 SearchBarViewDelegate 展現搜尋頁面
IconButton(
icon: Icon(Icons.search),
onPressed: (){
showSearch(context: context, delegate: SearchBarViewDelegate());
}
)
複製程式碼
效果:
Flutter AnimatedIcon
在 flutter 中也提供一一種 widiget —— AnimatedIcon 來展示帶動畫的 Icon,可以帶來很好的使用者體驗。在上面的搜尋欄中,返回按鈕用的就是這個 widget。
並不是所有的 Icon 都能展示這種效果,flutter 中,提供的 AnimatedIcons 一共有如下這些:
abstract class AnimatedIcons {
/// The material design add to event icon animation.
static const AnimatedIconData add_event = _$add_event;
/// The material design arrow to menu icon animation.
static const AnimatedIconData arrow_menu = _$arrow_menu;
/// The material design close to menu icon animation.
static const AnimatedIconData close_menu = _$close_menu;
/// The material design ellipsis to search icon animation.
static const AnimatedIconData ellipsis_search = _$ellipsis_search;
/// The material design event to add icon animation.
static const AnimatedIconData event_add = _$event_add;
/// The material design home to menu icon animation.
static const AnimatedIconData home_menu = _$home_menu;
/// The material design list to view icon animation.
static const AnimatedIconData list_view = _$list_view;
/// The material design menu to arrow icon animation.
static const AnimatedIconData menu_arrow = _$menu_arrow;
/// The material design menu to close icon animation.
static const AnimatedIconData menu_close = _$menu_close;
/// The material design menu to home icon animation.
static const AnimatedIconData menu_home = _$menu_home;
/// The material design pause to play icon animation.
static const AnimatedIconData pause_play = _$pause_play;
/// The material design play to pause icon animation.
static const AnimatedIconData play_pause = _$play_pause;
/// The material design search to ellipsis icon animation.
static const AnimatedIconData search_ellipsis = _$search_ellipsis;
/// The material design view to list icon animation.
static const AnimatedIconData view_list = _$view_list;
}
複製程式碼
使用步驟
1、定義 AnimationController 控制動畫
controller = AnimationController(vsync: this)
..drive(Tween(begin: 0, end: 1))
..duration = Duration(milliseconds: 500);
複製程式碼
2、 AnimatedIcon 指定動畫控制器和需要展示的動畫Icon
AnimatedIcon(
icon: AnimatedIcons.play_pause,
progress: controller,
size: 35,
semanticLabel: "play_pause",
),
複製程式碼
3、控制播放
InkWell(
child: _icons[index],
onTap: () {
if (controller.status == AnimationStatus.completed) {
controller.reverse();
} else if (controller.status == AnimationStatus.dismissed) {
controller.forward();
}
},
),
複製程式碼
效果:
最後
歡迎關注「Flutter 程式設計開發」微信公眾號 。