11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Flutterのキーボードで閉じるボタンを表示する

Posted at

閉じるボタンがほしい

iOSアプリで複数行テキスト入力とかさせようとすると、入力フィールドにフォーカス来た時に表示されるキーボードをどうやって閉じるかが問題になる。この解決策としてよくやるのが、

  • 他の部分タップしたらフォーカス外す。
  • キーボードの上に「閉じる」ボタンを追加する。

前者で良ければ話は終わるが、後者しか手段がない場合にどうするか。iOSネイティブならinputAccessoryViewを使えば良い。Flutterでも同じ機能あれば良い…が、探してもなかった。Androidではあまり問題にならないから仕方ないのかも。
でもきっと解決している方がいるに違いない。ググったけどあまりないなぁ…と思いながら見つけたのがkeyboard_actions。

閉じるボタンがほしいだけ

keyboard_actionsはネイティブに頼らずFlutter/Dartだけで解決していて素晴らしいし、いろいろ機能あるしで感謝感謝なのだが、俺がほしいのは単に「閉じる」ボタンだけなのだ。keyboard_actionsを使ってみると分かるがほどよいタイミングで設定を渡したりしなければならず、もうちょっと楽に書きたい。

なのでこんなコード書いた。

keyboard_actions_helper.dart
import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';

class KeyboardActionsHelper {
  static const defaultCloseWidget =
      Padding(padding: EdgeInsets.all(5.0), child: Text('閉じる'));

  static void setCloseActions({
    @required BuildContext context,
    @required List<FocusNode> focusNodes,
  }) {
    final actions = focusToCloseActions(closeActionFocusNodes: focusNodes);
    final config = actionsToKeyboardBarConfig(actions: actions);
    FormKeyboardActions.setKeyboardActions(context, config);
  }

  static List<KeyboardAction> focusToCloseActions(
      {@required @required List<FocusNode> closeActionFocusNodes}) {
    return closeActionFocusNodes
        .map<KeyboardAction>((focus) =>
            KeyboardAction(focusNode: focus, closeWidget: defaultCloseWidget))
        .toList();
  }

  static KeyboardActionsConfig actionsToKeyboardBarConfig(
      {@required List<KeyboardAction> actions}) {
    return KeyboardActionsConfig(
      keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
      keyboardBarColor: Colors.grey[200],
      nextFocus: false,
      actions: actions,
    );
  }
}

class ConfigurableFormKeyboardActions extends FormKeyboardActions {
  final List<FocusNode> closeActionFocusNodes;

  ConfigurableFormKeyboardActions(
      {this.closeActionFocusNodes, Widget child, bool autoScroll = true})
      : super(child: child, autoScroll: autoScroll);

  @override
  FormKeyboardActionState createState() => ConfigurableFormKeyboardActionState(
      closeActionFocusNodes: closeActionFocusNodes);
}

class ConfigurableFormKeyboardActionState extends FormKeyboardActionState {
  final List<FocusNode> closeActionFocusNodes;

  ConfigurableFormKeyboardActionState({this.closeActionFocusNodes});

  @override
  void initState() {
    super.initState();
    _setupActions();
  }

  void _setupActions() {
    if (closeActionFocusNodes != null) {
      setConfig(
        KeyboardActionsHelper.actionsToKeyboardBarConfig(
          actions: KeyboardActionsHelper.focusToCloseActions(
              closeActionFocusNodes: closeActionFocusNodes),
        ),
      );
    }
  }
}

するとこんな感じでFocusNode渡すだけで済む。

foo.dart

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // ...
      body: ConfigurableFormKeyboardActions(
        closeActionFocusNodes: [_yourFocusNode],
        child: //...

ただそれだけの話であるが、keyboard_actions や日頃お世話になっている皆様への感謝として晒しておきます。

11
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?