【Flutter】AppBarを検索バーにする方法
はじめに
AppBar をカスタマイズしてみました。以下の完成品を作る手順を解説します。
準備
プロジェクトを開始したらlib/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
を実装する必要があります。
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);
}
検索バーの実装
まずは要点を。
検索バー自体はAppBar
のtitle
プロバティを書き換えて実装しています。
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
で設定でき、それぞれprefixIcon
、suffixIcon
になります。プレースホルダーはhintText
プロバティで設定します。
ただ大抵の場合『❌』は入力値のクリアなどを割り当てている場合が多く、その際には別途ButtonIcon
などで実装する必要がでてきます。
最後のonSubmitted
はTextField
に入力された値を処理するプロバティで、引数には入力した値がString
型として渡されます。
今回はTextField
入力値の削除と入力値のコンソールへの出力を_submittion()
で実行しています。
onSubmitted: (text) => _submission(text)
の書き方については、前回書いた記事でほんのちょっとだけ触れています。
最終的なコード
体裁を整えた最終的なコードは以下のとおりです。
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),
),
),
),
),
),
);
}
}
この例はシンプルなものですが、入力値のクリアや、入力値をタグとしてテキストフィールド内に表示させる(横並びにする)といった機能を実装するとなるとちょっと面倒なことになります(Row
やStack
、Expanded
、SingleChildScrollView
あたりをゴニョゴニョする)。
他にもTextField
にはonChanged
などおもしろいプロバティもありますので調べてみるといいと思います。
まとめ
-
PreferredSizeWidget
を実装してAppBar
をカスタマイズする。 -
TextEditingController()
を用いることでTextField
の入力値をかんたんに操作できる。
Discussion