タグやフィルターなどの細々とした情報を簡単に追加削除する Chip を Wrap 内で使って折り返す方法
Material Design ではタグ、フィルター、あるいはメールの宛先などの個別のデータなどは Chip というコンポーネントで受け持つことになっています。
Flutter の Material Components にも Chip ウィジェットがあって、ここで実装例を示すように簡単に使うことができます。 追加や削除はとても簡単です。ただ、複数のチップを並べるために、並び順に折り返したりする必要があって、それには一工夫必要です。
ここでは、Wrap というウィジェットと組み合わせることで、Chip が増えてきたときに二列以上に折り返して並べています。
基本的に Wrap の children プロパティに Chip のリストを渡せばよいだけです。 それから並べる向きや間隔に関するプロパティを設定します。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
debugPaintSizeEnabled = false;
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _State();
}
}
class _State extends State<MyApp> {
var _textFieldFocusNode;
var _inputController = TextEditingController();
var _chipList = List<Chip>();
var _keyNumber = 0;
@override
void initState() {
_textFieldFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
_textFieldFocusNode.dispose();
super.dispose();
}
void _onSubmitted(String text) {
setState(() {
_inputController.text = '';
_addChip(text);
FocusScope.of(context).requestFocus(_textFieldFocusNode);
});
}
void _addChip(String text) {
var chipKey = Key('chip_key_$_keyNumber');
_keyNumber++;
_chipList.add(
Chip(
key: chipKey,
label: Text(text),
onDeleted: () => _deleteChip(chipKey),
),
);
}
void _deleteChip(Key chipKey) {
setState(() => _chipList.removeWhere((Widget w) => w.key == chipKey));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chip Test'),
),
body: Container(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextField(
focusNode: _textFieldFocusNode,
autofocus: true,
controller: _inputController,
decoration: InputDecoration(
hintText: 'Enter Tag...',
),
onSubmitted: _onSubmitted,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Wrap(
alignment: WrapAlignment.start,
spacing: 8.0,
runSpacing: 0.0,
direction: Axis.horizontal,
children: _chipList,
),
),
],
),
],
),
),
);
}
}
少しコードが増えてしまっていますが、テキストフィールドにフォーカスを移したり、Chip のリストに Chip を追加したり削除したりする部分が大半です。
Wrap ウィジェットに関して言えば、children プロパティに Chip のリストを渡しているだけです。