flutter&firebase でWEBサービス ハッシュタグをchipsで実装

ハッシュタグの実装方法

flutterではChipsでハッシュタグの実装を行います。

以下のサイトを参考にさせて頂きました。

https://take424.dev/2021/06/08/flutter%E3%81%A7%E5%90%84%E7%A8%AEchip%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83%88%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B/

完成イメージ

作成したハッシュタグの実装画面です。

完成後の動作です。

ソースコード

上記の完成イメージになる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;
  }

About: ken


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください