flutter&firebase でWEBサービス ハッシュタグをchipsで実装
ハッシュタグの実装方法
flutterではChipsでハッシュタグの実装を行います。
以下のサイトを参考にさせて頂きました。
完成イメージ
作成したハッシュタグの実装画面です。
完成後の動作です。
ソースコード
上記の完成イメージになるWidgetです。child要素にtagChipsを設定しています。
Card( color: Colors.white, child: Padding( padding: EdgeInsets.all(8.0), child: tagChips, )),
tagChips
完成したハッシュタグ用のwidgetです。StatelessWidgetで作成しています。
import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; import 'package:stockcodes/model/codeModel.dart'; class TagChips extends StatelessWidget { late FocusNode _textFieldFocusNode; late TextEditingController _inputController; late List<String> _tagStrings; List<Chip> _chipList = []; int _keyNumber = 0; late bool _editflag; bool _firstBuild = true; TagChips(List<String>? tagStrings, bool editflag) { this._tagStrings = tagStrings!; this._editflag = editflag; this._textFieldFocusNode = FocusNode(); this._inputController = TextEditingController(); _inputController.text = ''; } List<String> get tags { _tagStrings = []; _chipList.forEach((chip) { Text text = chip.label as Text; _tagStrings.add(text.data!); }); return _tagStrings; } Key _getKey() { Key chipKey = Key('chip_key_$_keyNumber'); _keyNumber++; return chipKey; } @override Widget build(BuildContext context) { final CodeModel codeModel = Provider.of<CodeModel>(context); //初回だけ実行 if (_firstBuild) { this._tagStrings.forEach((tagstring) { Key keystr = _getKey(); _chipList.add(Chip( key: keystr, backgroundColor: Colors.blue, labelStyle: TextStyle( color: Colors.white, ), label: Text(tagstring), onDeleted: () { if (_editflag) { _chipList.removeWhere((Widget w) => w.key == keystr); codeModel.update(); } }, )); }); _firstBuild = false; } return Container( padding: EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ TextField( focusNode: _textFieldFocusNode, enabled: _editflag, controller: _inputController, decoration: InputDecoration( hintText: 'タグを追加...', ), onSubmitted: (String text) { _inputController.text = ''; Key keystr = _getKey(); _chipList.add( Chip( key: keystr, label: Text(text), backgroundColor: Colors.blue, labelStyle: TextStyle( color: Colors.white, ), onDeleted: () { _chipList.removeWhere((Widget w) => w.key == keystr); codeModel.update(); }, ), ); FocusScope.of(context).requestFocus(_textFieldFocusNode); codeModel.update(); }, ), 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, ), ), ], ), ], ), ); } }
ハマったところ
初回だけ初期値設定
statelessで作ったためか、画面の再描画によりchipsのデータが消えたりする挙動が発生しました。そのため初回だけ値を設定する処理を追加しています。
//初回だけ実行 if (_firstBuild) { this._tagStrings.forEach((tagstring) { Key keystr = _getKey(); _chipList.add(Chip( key: keystr, backgroundColor: Colors.blue, labelStyle: TextStyle( color: Colors.white, ), label: Text(tagstring), onDeleted: () { if (_editflag) { _chipList.removeWhere((Widget w) => w.key == keystr); codeModel.update(); } }, )); }); _firstBuild = false; }
値を返すための関数
chipsに設定した値を最後にリストで返却するのですが、どうやってchipsから値を取得してよいか分からずはまりました。以下のやり方でうまくいっています。
List<String> get tags { _tagStrings = []; _chipList.forEach((chip) { Text text = chip.label as Text; _tagStrings.add(text.data!); }); return _tagStrings; }