🐬

【Flutter】AppBarを検索バーにする方法

2022/08/06に公開

はじめに

AppBar をカスタマイズしてみました。以下の完成品を作る手順を解説します。


準備

プロジェクトを開始したらlib/main.dartを以下のようにかんたんに書き換えます。

main.dart
import 'package:flutter/material.dart';
import 'package:zenn/search_bar.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const Scaffold(
        appBar: SearchBar(),
        body: Center(
          child: Text('Hello'),
        ),
      ),
    );
  }
}

Scaffold中のappBarで、カスタマイズするSearchBarを生成しています。

AppBar のカスタマイズ

appBarクラスはPreferredSizeWidgetで宣言されているので、
カスタマイズする際もPreferredSizeWidgetを実装する必要があります。

search_bar.dart
import 'package:flutter/material.dart';

class SearchBar extends StatefulWidget implements PreferredSizeWidget {
  const SearchBar({Key? key}) : super(key: key);

  
  State<SearchBar> createState() => SearchBarState();

  
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

検索バーの実装

まずは要点を。
検索バー自体はAppBartitleプロバティを書き換えて実装しています。

search_bar.dart
class SearchBarState extends State<SearchBar> {
  final _controller = TextEditingController();

  void _submission(text) {
    setState(() {
      _controller.clear();
      if (kDebugMode) {
        print(text);
      }
  });
}

  
  Widget build(BuildContext context) {
    return AppBar(
      title: SizedBox(
        ...
          child: TextField(
            controller: _controller,
            decoration: const InputDecoration(
              hintText: 'Search Text',
              prefixIcon: Icon(Icons.search),
              suffixIcon: Icon(Icons.clear),
              ...
            ),
            onSubmitted: (text) => _submission(text),
          ),
        ...

TextFieldは便利なcontollerプロパティがあり、TextEditingControllerをいれてあげるだけでコントローラから入力値などを取得できます。

検索バーによくある両端の『🔎』や『❌』はdecorationプロバティのInputDecorationで設定でき、それぞれprefixIconsuffixIconになります。プレースホルダーはhintTextプロバティで設定します。

ただ大抵の場合『❌』は入力値のクリアなどを割り当てている場合が多く、その際には別途ButtonIconなどで実装する必要がでてきます。

最後のonSubmittedTextFieldに入力された値を処理するプロバティで、引数には入力した値がString型として渡されます。

今回はTextField入力値の削除と入力値のコンソールへの出力を_submittion()で実行しています。

onSubmitted: (text) => _submission(text)の書き方については、前回書いた記事でほんのちょっとだけ触れています。

最終的なコード

体裁を整えた最終的なコードは以下のとおりです。

search_bar.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class SearchBar extends StatefulWidget implements PreferredSizeWidget {
  const SearchBar({Key? key}) : super(key: key);

  
  State<SearchBar> createState() => SearchBarState();

  
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

class SearchBarState extends State<SearchBar> {
  final _controller = TextEditingController();

  void _submission(text) {
    setState(() {
      _controller.clear();
      if (kDebugMode) {
        print(text);
      }
    });
  }

  
  Widget build(BuildContext context) {
    return AppBar(
      title: SizedBox(
        height: 40,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            border: Border.all(color: Colors.blue),
            borderRadius: BorderRadius.circular(8.0),
          ),
          child: Center(
            child: Container(
              width: 340,
              margin: const EdgeInsets.symmetric(vertical: 10.0),
              child: TextField(
                controller: _controller,
                decoration: const InputDecoration(
                  hintText: 'Search Text',
                  prefixIcon: Icon(Icons.search),
                  suffixIcon: Icon(Icons.clear),
                  contentPadding: EdgeInsets.only(left: 8.0),
                  enabledBorder: InputBorder.none,
                  focusedBorder: InputBorder.none,
                  isDense: true,
                ),
                onSubmitted: (text) => _submission(text),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

この例はシンプルなものですが、入力値のクリアや、入力値をタグとしてテキストフィールド内に表示させる(横並びにする)といった機能を実装するとなるとちょっと面倒なことになります(RowStackExpandedSingleChildScrollViewあたりをゴニョゴニョする)。

他にもTextFieldにはonChangedなどおもしろいプロバティもありますので調べてみるといいと思います。

まとめ

  • PreferredSizeWidgetを実装してAppBarをカスタマイズする。
  • TextEditingController()を用いることでTextFieldの入力値をかんたんに操作できる。
GitHubで編集を提案

Discussion