テキスト入力のUXを改善しました

はじめに

こんにちは、アプリチームのルーカス(YOUTRUST / X) です。

今回は仕事で起きた面白いエピソードについて話したいと思います!✨ ある晴れた日に目覚め☀️、美味しいココアを飲んで☕、ストレッチをして🧘‍♀️、MacBookを開いたところ💻、ユートラの「改善要望」というSlackチャンネル💬に、取締役の金子さんから新しいメッセージが届いているのを見つけました🔔。

外のアプリからコピペする度に聞かれちゃうのはどうにもならない?不便やなと。。。

そんなことは今まで考えたことがなかったので、「原因はいったい何だろう🤔?」と思いました。 そして調査後に、実はそれこそがFlutterの特徴だとわかったのです✨。

1つ目の問題

別のFlutterアプリでは、テキストフィールドに何かをペーストすると、そのダイアログが表示される可能性が高いです。ぜひ試してみてください👍!

改善内容①

この現象を解決する方法をお伝えする前に、なぜそれが起きるのかを説明します。 そのため、関連しているFlutterのコードを見てみましょう。

 /// Paste text from [Clipboard].
  @override
  Future<void> pasteText(SelectionChangedCause cause) async {
    if (!_allowPaste) {
      return;
    }
    // Snapshot the input before using `await`.
    // See https://github.com/flutter/flutter/issues/11427
    final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
    if (data == null) {
      return;
    }
    _pasteText(cause, data.text!);
  }

Clipboard.getData が原因です!通常のネイティブアプリでは、クリップボードのデータを直接取得していないため、Flutterの場合にはこのダイアログが表示されるのです。

では、その知識を踏まえて、どうやってそれを解決すればいいのでしょうか💡?実は、意外と簡単な方法があります!contextMenuBuilderを使えば、コンテキストメニューをカスタマイズできます。

基本的に、Flutterは AdaptiveTextSelectionToolbar という独自のコンテキストメニューを使用しています。

 TextField(
      contextMenuBuilder: (BuildContext context, EditableTextState state) {
          return AdaptiveTextSelectionToolbar.editableText(
              editableTextState: editableTextState,
          );
      },
  )

しかし、最近登場したSystemContextMenuを使うことで、ネイティブに近いコンテキストメニューが利用できるようになります。☝️

 TextField(
      contextMenuBuilder:
          (BuildContext context, EditableTextState state) {
              if (SystemContextMenu.isSupported(context)) {
                  return SystemContextMenu.editableText(editableTextState: state);
              }

              return AdaptiveTextSelectionToolbar.editableText(
                  editableTextState: state,
              );
         },
     )

これからはシステム側がコピー&ペーストの機能を管理するようになるため、Clipboard.getDataは使用されなくなります。つまり、あのダイアログが表示されなくなるのです!

これからは、ユーザーにより馴染みやすい体験を提供するために、 contextMenuBuilderの設定を忘れないでください!

第2問題の説明

でも、もう一つの改善点があります。細かい話ではあるのですが、個人的にそれを解決するために色々と調べたので、ぜひ共有したいと思います。 英文字たくさん使っていますので、ある日にアプリでは投稿を書くときに、この現象見つけました。

見られますか?少し拡張しましょう!

実際のデバイスで見るとより見やすいのですが、英字・絵文字・日本語など、それぞれでテキストマーカーの高さが異なっています🔠。 この記事ですべてを詳しく説明すると長くなりすぎるので、簡単に言うと、Flutterはテキストをレンダリングする際にさまざまな特徴がある、ということです。

割と目立たない設定なので、多くのFlutterエンジニアに聞いてみたのですが、 あまり触られることのない部分らしく、ほとんどの人が解決方法を知りませんでした🤔。

改善内容②

ところが、去年のFlutterConでAndreaさん*1Raofuさん*2に話を伺ったところ、ようやく一緒に解決ことができました。 そして、下の行を追加するだけで、テキストマーカーのサイズがそろうようになるのです。

 TextField(
     selectionHeightStyle: BoxHeightStyle.strut,
 )

面白いことに、その後Andreaさんも自分のブログで、この件について書かれていました。

最後に

今回ご紹介した設定は、どれもFlutter アプリで、Flutter アプリで簡単に適用できるものばかりです。小さな改善であっても、ユーザー体験を向上させることが可能です。

YOUTRUSTでは、エンジニアを募集しています。興味がある方はぜひご応募ください✨!

herp.careers

*1:有名なFlutterブログ書いてる方

*2:FlutterとDartのGDE