Flutter showSearch 與 AnimatedIcon 的使用

Flutter程式設計開發 發表於 2019-10-13

Flutter 搜尋頁實現

在一般的 App 頁面,可能都需要搜尋功能,常見的就是在主頁上面有一個搜尋欄,點選會跳轉到一個搜尋頁面。

Flutter  showSearch 與  AnimatedIcon 的使用

在 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  showSearch 與  AnimatedIcon 的使用

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  showSearch 與  AnimatedIcon 的使用

github

最後

歡迎關注「Flutter 程式設計開發」微信公眾號 。

Flutter  showSearch 與  AnimatedIcon 的使用