🦋

Autocompleteをリセットする

2024/05/21に公開

そんなに難しいことなのか?

『四次元年表』の国別検索で、typoを防ぐためにAutocompleteを使いたい。
でも、用が済んだら、その国名にはさっと消えていただきたい。
画面に残っている文字列をいちいち消すのって、めんどくさいじゃないですか、ユーザーとして。
でも、けっこうそういう場面に出くわす。
出くわすたびにイラつく。
でも、自分でつくる側になったら、これができない。
textFieldだったら、controller.clearみたいにできるのに、
なんでAutocompleteではできない?
https://teratail.com/questions/tuqdu7cpops2p2

単純にclearできないなら、言われたとおりに細工するしかない

で、結果としてこちら。
まず、clearボタンと、検索ボタンのついている作り置き。

import 'package:flutter/material.dart';

class AutocompleteWithClear extends StatefulWidget {
  final List<String> options;
  final TextEditingController searchController;
  final VoidCallback onSearch;
  final VoidCallback onPressed;

  const AutocompleteWithClear({
    required this.options,
    required this.searchController,
    required this.onSearch,
    required this.onPressed,
    super.key,
  });

  
  AutocompleteWithClearState createState() => AutocompleteWithClearState();
}

class AutocompleteWithClearState extends State<AutocompleteWithClear> {
  
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return widget.options.where((String option) {
                if (textEditingValue.text.isNotEmpty) {
                  return option.contains(textEditingValue.text[0].toUpperCase() +
                      textEditingValue.text.substring(1).toLowerCase());
                } else {
                  return option.contains(textEditingValue.text);
                }
              });
            },
            onSelected: (String selection) {
              widget.searchController.text = selection;
            },
            fieldViewBuilder: (BuildContext context,
                TextEditingController textEditingController,
                FocusNode focusNode,
                VoidCallback onFieldSubmitted) {
              textEditingController.text = widget.searchController.text;
              textEditingController.addListener(() {
                widget.searchController.text = textEditingController.text;
              });
              return TextField(
                controller: textEditingController,
                focusNode: focusNode,
                decoration: InputDecoration(
                  suffixIcon: IconButton(
                    onPressed: widget.onPressed,
                    icon: const Icon(Icons.clear),
                  ),
                ),
              );
            },
          ),
        ),
        IconButton(
          onPressed: widget.onSearch,
          icon: const Icon(Icons.search),
        ),
      ],
    );
  }
}

使うほうはこちら。
Autocompleteした文字列だけじゃなく、
検索結果も消せるようにしてみました。

  void resetSearch() {
    setState(() {
      searchController.clear();
      listPrincipal = [];
      principalIds = [];
    });
  }

***中略

          Center(
            child: Padding(
              padding: const EdgeInsets.only(left: 30.0,right: 20.0),
              child: Column(
                children: [
                  Text(AppLocalizations.of(context)!.search),
                  AutocompleteWithClear(
                    options: options,
                    searchController: searchController,
                    onSearch: () {
                      fetchPrincipalByLocation(searchController.text);
                    },
                    onPressed: resetSearch,
                  ),
                ],
              ),
            ),
          ),

とりあえず、一ユーザーとして満足

ややこしいcodeの意味を完全に理解した!とは言えないんだけどね。

四次元年表
https://app.laporte.academy
三次元・四次元表示
https://tempo-spaco.web.app
四次元年表の使い方
https://www.youtube.com/@laporte_academy

Flutter大学

Discussion