blog

Flutter FocusNode フォーカスのこと-(2)

えーと... コメントがないので、ソースコードを見るしかないですね。 この中に親を全部入れるわけです。 まあ、個人的な経験から言うと、アプリケーションレイヤーでは役に立たないでしょう。 ソースコードに...

Apr 30, 2020 · 8 min. read
シェア

前章ではFocusNodeとその周辺を簡単に使いましたが、今日はFocusNodeの全体的な着脱について見ていきます。

flutterの環境は1.17.5のままです。

Focus ファミリーのソースコード解析

添付ファイル

まず、FocusNodeは通常、メイン・オブジェクトです。

工法

  • debugLabel、この名前はデバッグ用なので無視しましょう。
  • onKeyは、一見したところ、イベントを受け取るためのRawKeyEventです。
  • canRequestFocus、つまりフォーカスを受け付けることができます。
  • skipTraversal, トラバーサルを受け入れるかどうか

別の方法を見つけてください。

いくつかキーとなるフィールドがありますが、ひとつひとつは使われないかもしれませんが、知っておいて損はありません。

  • の文脈では、これはコントロールと組み合わされたものであり、それだけを見れば明らかではありません。

  • managerは、これは実際にはflutter環境ではグローバルシングルトンであることを知っていますが、ここではデカップリングのために、どこに渡すかもしれないので、理論的には無視することができます。

  • _descendants、このことも些細なことで、ソースコードには何もありません、このことは、1つの子ノードの子孫と子ノードの深さであり、その後、内部で再帰的です... のすべてのサブノードです。

  • _hasKeyboardToken これがどう機能するのかわからないので、とりあえず置いておきます。

  • 子供たちは、このことは、すべての子ノードですが、どのように瞬間を添付する方法がわからない、それを最初に置く

  • traversalChildren、これは使用されるものの中核であり、このものによってフィルタリングされ、子ノードのトラバーサルを受け入れることができ、ここで、そのペアのコンストラクタ・メソッドです。

私はいくつかのコアフィールドを検索しましたが、私はまだ添付する方法を見つけることができません、全体的なメソッド名ナイスガイを見て、画面は収まりそうもありません、名前を見て、添付に直行

このメソッドはattachmentメソッドのようです。このメソッドに従って、コンテキストをバインドし、キーコールバックをバインドし、attachmentを作成するだけであることに注目してみましょう。

FocusNodesが複数の場所にアタッチされないようにする方法と説明されていますが、どのように機能するのですか?

まあ、正しい場所にあるかどうかをチェックし、そうでなければ新しい親を見つけるということのようです。

Node のツリー構造

これはソースコードの構造を簡単に見たものですが、どのノードが関係しているかを視覚化する体系的な方法ではないでしょう。

単純にFocusNodeのノード関係を出力するメソッドを書いてみます。

import 'package:flutter/material.dart';
class FocusNodePrintExample extends StatefulWidget {
 @override
 _FocusNodePrintExampleState createState() => _FocusNodePrintExampleState();
}
class _FocusNodePrintExampleState extends State<FocusNodePrintExample> {
 FocusNode node = FocusNode(debugLabel: 'the input');
 FocusNode node2 = FocusNode(debugLabel: 'the raised button');
 FocusNode node3 = FocusNode(debugLabel: 'the float button');
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(),
 body: Column(
 children: [
 TextField(
 focusNode: node,
 ),
 RaisedButton(
 onPressed: () {},
 focusNode: node2,
 ),
 ],
 ),
 floatingActionButton: FloatingActionButton(
 focusNode: node3,
 onPressed: () {
 priceAllFocusNode();
 },
 ),
 );
 }
}
void printNode(int level, FocusNode node) {
 print('${'--' * level} $node');
 for (final child in node.children) {
 printNode(level + 1, child);
 }
}
void priceAllFocusNode() {
 printNode(0, FocusManager.instance.rootScope);
}

この ModalScopeState は、各ページが互いに干渉しないように、独自のフォーカス領域を持てるようにするためのものです。この ModalScopeState は、各ページが独自のフォーカス領域を持てるようにするもので、互いに影響し合わないようにします。

これらは、モノが FocusScope を定義し、モノ自体が ModalRoute で定義されます。

また、ModalRouteは各種共通のPageRoute(MaterialPageRoute、CupertinoPageRouteの親クラス)、PopupRoute(DialogRouteの親クラス)であり、まあ、ルートとページのシャッフルもつながっています。 同時に、ダイアログとページでフォーカスが分かれている理由も明らかです。

フォーカスの変更

さて、フォーカスエリアなどを探ったところで、フォーカスが変更されたときに何が起こるかを見てみましょう。 requestFocusメソッドはflutter全体で一度だけ定義されています。

ご覧のように、これは入力パラメータを取ることができ、それは別のノードですが、現在のノードの親に属するなど、そのノードに制約があります。 もちろん、パラメータを渡さなければ、単なる _doRequestFocus の呼び出しになります。

_requestFocusWhenReparented次に、親ノードが空の場合、それは、フォーカスを要求するために再アタッチされたときに名前があるはず参照してください、trueに設定され、言い換えれば、最初の簿記は、ここの私の個人的な理解は、新しいページを開いた場合、古いページ全体がフォーカスの外にあるため、しかし、古いページがフォアグラウンドに戻るときに、このことが真であることを検出し、フォーカスを再要求するということです。

意味の順序の最後に現在の親フォーカスを追加し、特定の役割は明らかではありません

そして

if (hasPrimaryFocus && (_manager._markedForFocus == null || _manager._markedForFocus == this)) {
 return;
}

hasPrimaryFocusは、それが現在のプライマリフォーカスであることを意味します。 markedForFocusは、それが適用されているが、まだアクティブではないことを意味し、ダーティマーカーに似ています。

_hasKeyboardToken = true;
assert(_focusDebug('Node requesting focus: $this'));
_markNextFocus(this);

キーボードトークンを取得し、次のフォーカスを自分のものとしてマークする、という比較的単純なものです。

次に、FocusScopeNode のこのメソッドの実装を見てください。

マネージャーが採点をするように手配すればいいだけのことです。

manager の処理は

ちょうど今_markNextFocusメソッドがあり、このメソッドは、このメソッドに従うように、マネージャを呼び出します管理クラスのシングルトンのマネージャが何をしたかを確認するには、次のとおりです。

現在の主戦場であれば問題ありません。

そうでない場合は、updateメソッドを呼び出します。

これは単なるフラグ・メソッドで、アプリケーションはコールバックでfocusChangeを実行します。

分離

FocusAttachmentで、すでにアタッチされている場合は、それをアンフォーカスし、マネージャーでそれをデタッチドとしてマークし、親と子の関連付けを解除し、_node._attachmentを空にします。 これはライフサイクルのようなもので、バインディングで行ったことは、当然、バインディングを解除するときには逆に行わなければならないと考えることができます。

ソフトキーボードのポップアップに関する問題

何人かの学生は、フォーカスに関連するものを読んだ後に奇妙に感じるでしょう、なぜソフトキーボードのものがない、半日のフォーカスについて話して、ああソフトキーボードのポップアップロジックを見ないのですか?

というのも、前のセクションはあくまでフォーカスのセクションであり、先ほども述べたように、flutterではフォーカスを得るのはテキスト入力だけでなく、理論上フォーカスを得る可能性のあるコントロールであれば何でもいいのです。

逆引き

逆にどうやって調べるの? フラッターネイティブのやり取りはすべてSystemChannelsを通して行われることがわかりました。

ソフトキーボードはtextInputから入力します。

まあ、チャンネルなんですが、これにはメソッドがあるんです。

フォワード・コールとコールバックをカプセル化したクラスがあります。

名前の意味は、編集状態、アクション(ソフトキーボードか何かでエンター?)カーソルの更新、クローズ。 詳しくは書きません。

updateEditingState

これは通常のonChangedコールバックに相当します。

performAction

この名称は基本的に、さまざまなキーボードのEnterキー機能に対応していることを物語っています。

updateFloatingCursor

基本的には、クリックか何かでカーソルの位置が変わるだけです。

connectionClosed

ソフトキーボードからコールバックを切り離して、これ以上言うことはありません。

コントロールにフォーカスがあるとき、ソフトキーボードポップアップのロジックである TextInput の show メソッドを呼び出すことができます。

このとき、生徒の中には、「根拠はわかるけど、なぜこの方法が発動するんですか? この人はなぜそんなにイライラするのかと言いますと......」。

まあ、ソースコードの観点から言えば、ソースはあります。

この三重苦の末に、focusNode自体がChangeNotifierであり、これが変化すると、当然コールバックメソッドに通知され、この通知を呼び出すメソッドがあることを知っているマネージャは、当然キーボードがポップアップします。

あとがき

この投稿は、ソースコードにおけるフォーカスとソフトキーボードのポップアップについてです!

上の写真

Read next

ROS Robotics - 複数のノードを起動するための起動を記述する

1.add source to bashrc 2.write startup launch 3.add some Tips しかし、起動時にrvizのノード名が重複する問題が発生したので、レーダー起動のRVIZを停止するか、RVIZを起動するノード名を変更して重複を防ぎました。

Apr 30, 2020 · 2 min read