Flutter_Webviewキーボードポップアップ問題

Flutter_Webviewキーボードポップアップ問題


webview_flutter ^0.3.7+1 パブリンク

決してwebview_flutter Android上でポップアップキーボードは、githubの上の問題はなく、10月中に正式な19年の節目に、長い時間のために言及された問題#19 718、(すでにプレス時間のとして、masterブランチへのPRを持っていますが、安定した枝学生は)ハを待たなければならないかもしれないが、PRソリューションを前に使用していませんでした... AndroidN コメント

他の学生からのインスピレーション1

隠しテキストフィールドプログラムは、このプログラムのシンプルなアイデアがでていることであるonPageFinish時間TextFieldを聞くことによって、その後、いくつかのjsのコードを挿入WebViewのフォーカスイベントの入力/ TEXTAREAを監視し、その後JSChannelによってのWebViewのTextFieldの後ろに隠れに送られ、間接的にはTextFieldでソフトキーボードを呼び起こすとします入力/テキストエリアに新しい値を設定するために、onChangeイベント

ここで彼のJSのコードは次のとおりです。彼は、イベント/ focusoutのフォーカスイベントを、いくつかのJSを持つサイトのポップ入力メソッドの要素をリッスン必要

inputs = document.getElementsByClassName('search-bar');
                            header=document.getElementsByClassName('site-header');
                            header[0].style.display = 'none';
buttons = document.getElementsByClassName('icon');
                            buttons[0].focus();
                            if (inputs != null) {
                              input = inputs[0];
                              InputValue.postMessage(input.value);
                              input.addEventListener('focus', (_) => {
                                Focus.postMessage('focus');
                              }, true);
                              input.addEventListener('focusout', (_) => {
                                Focus.postMessage('focusout');
                              }, true)
                            }
复制代码

JSChannel:

 javascriptChannels: Set.from(
                          [
                            // Listening for Javascript messages to get Notified of Focuschanges and the current input Value of the Textfield.
                            JavascriptChannel(
                              name: 'Focus',
                              // get notified of focus changes on the input field and open/close the Keyboard.
                              onMessageReceived: (JavascriptMessage focus) {
                                print(focus.message);
                                if (focus.message == 'focus') {
                                  FocusScope.of(context)
                                      .requestFocus(_focusNode);
                                } else if (focus.message == 'focusout') {
                                  _focusNode.unfocus();
                                }
                              },
                            ),
                            JavascriptChannel(
                              name: 'InputValue',
                              // set the value of the native input field to the one on the website to always make sure they have the same input.
                              onMessageReceived: (JavascriptMessage value) {
                                _textController.value =
                                    TextEditingValue(text: value.toString());
                              },
                            )
                          ],
                        ),
复制代码

TextFieldには、ソフトキーボードを表示/非呼び起こすためにfocusNodeにより、イベントはテキストを変更受け取ります

プログラムはよさそうだが、手書きのクラス名は、すべての愚かな監視できる...と、ユーザーが手動で(ソフトキーボード上の[閉じる]ボタンを押す)ポップアップキーボードキーボードを閉じると、もはや出ないソフトキーボードを演奏しません。.. 。

2.自分のプログラムをアップグレード

  1. 受信した後、問題を解決するために、2つのイベントと交互にテキストフィールドを手動でキーボードをオフにすることはできません再喚起
  2. JS注入はフォーカスが/イベントfocusout、クリックイベントをリッスン聞いていない、すべての入力/ textarea要素を監視し、いくつかの利点がありますあなたがイベントを判断するために、再度クリックすることができます2.あなたは、ユーザーの現在のテキスト選択/カーソル位置を取得することができます1。
  3. 必要新しいキーボードを再誘発するかどうかを決定するための記録素子の現在の焦点、

次の簡単なコードの実装:

var inputs = document.getElementsByTagName('input');
var textArea = document.getElementsByTagName('textarea');
var current;

for (var i = 0; i < inputs.length; i++) {
  console.log(i);
  inputs[i].addEventListener('click', (e) => {
    var json = {
      "funcName": "requestFocus",
      "data": {
        "initText": e.target.value,
        "selectionStart":e.target.selectionStart,
        "selectionEnd":e.target.selectionEnd
      }
    };
    json.data.refocus = (document.activeElement == current);
    
    current = e.target;
    var param = JSON.stringify(json);
    console.log(param);
    UserState.postMessage(param);
  })
  
}
for (var i = 0; i < textArea.length; i++) {
  console.log(i);
  textArea[i].addEventListener('click', (e) => {
    var json = {
      "funcName": "requestFocus",
      "data": {
        "initText": e.target.value,
        "selectionStart":e.target.selectionStart,
        "selectionEnd":e.target.selectionEnd
      }
    };
    
    json.data.refocus = (document.activeElement == current);
    
    current = e.target;
    var param = JSON.stringify(json);
    console.log(param);
    
    UserState.postMessage(param);
  })
};
console.log('===JS CODE INJECTED INTO MY WEBVIEW===');
复制代码

UserStateがパラメータjsonString形、data.initText初期テキスト、selectEnd selectStartテキスト選択位置を受信し、jsChannel定義され、リフォーカスをクリック要素がクリックされたときに、エレメントマークを再集中するかどうか決定されます。

*  先判断是不是refocus,发送给channel
复制代码

showAndroidKeyboardは私が書かれているPlatformChannelは、ソフトキーボードを表示することで、受信したデータJSChannelを処理する次に、あなたはまた、私が改善している、ここに書いていない、コードを簡略化することができ、作者に連絡してください...また、ピットに強化インチ

  • キーを交互にフォーカスTextFieldを取得することで、TextFieldのとき - の後にフォーカスを取得し、いくつかの編集のため、ユーザーが手動でソフトキーボードをシャットダウンし、この時間FocusScop.of(コンテキスト).requestFocus(focusNodeA)は、キーボードを呼び起こすことができない、あなたは別のものを必要とするので、 TextFieldの-B​​要求が集中し、
  • showAndroidKeyboardは()フォーカスfocusNodeを取得していないいくつかのケースでスタンバイに、我々は手動呼び起こす集中する必要があります
  • キーボードイベントは、良い解決策ではありません隠します
bool refocus = data['refocus'] as bool;
    if (_focusNode2.hasFocus) {
      if (!refocus) FocusScope.of(context).requestFocus(_focusNode1);
      //FocusScope.of(context).requestFocus(_focusNode);
      if (!_focusNode1.hasFocus) {
        //hideAndroidKeyboard();
        showAndroidKeyboard();
      }
      //把初始文本设置给隐藏TextField
      String initText = data['initText'];
      var selectionStart = data['selectionStart'];
      var selectionEnd = data['selectionEnd'];

      int end = initText.length;
      int start = initText.length;
      if (selectionEnd is int) {
        end = selectionEnd;
      }
      if (selectionStart is int) {
        start = selectionEnd;
      }
      print(selectionEnd);
      textController1.value = TextEditingValue(
        text: initText,
        selection: TextSelection(baseOffset: start, extentOffset: end),
      );
      //TextField请求显示键盘
      FocusScope.of(context).requestFocus(_focusNode1);
    } else {
      if (!refocus) FocusScope.of(context).requestFocus(_focusNode2);
      //FocusScope.of(context).requestFocus(_focusNode);
      if (!_focusNode2.hasFocus) {
        //hideAndroidKeyboard();
        showAndroidKeyboard();
      }
      //把初始文本设置给隐藏TextField
      String initText = data['initText'];
      var selectionStart = data['selectionStart'];
      var selectionEnd = data['selectionEnd'];

      int end = initText.length;
      int start = initText.length;
      if (selectionEnd is int) {
        end = selectionEnd;
      }
      if (selectionStart is int) {
        start = selectionEnd;
      }
      print(selectionEnd);
      textController2.value = TextEditingValue(
        text: initText,
        selection: TextSelection(baseOffset: start, extentOffset: end),
      );
      //TextField请求显示键盘
      FocusScope.of(context).requestFocus(_focusNode2);
    }
复制代码

WebViewのTextFieldの後ろに隠れて

return Stack(
                  children: <Widget>[
                    TextField(
                      autofocus: false,
                      focusNode: _focusNode1,
                      controller: textController1,
                      onChanged: (text) {
                        controller.evaluateJavascript('''
                         if(current != null){
                          current.value = '${textController1.text}';
                          current.selectionStart = ${textController1.selection.start};
                          current.selectionEnd = ${textController1.selection.end};
                          current.dispatchEvent(new Event('input'));
                         }
                        ''');
                      },
                      onSubmitted: (text) {
                        controller.evaluateJavascript('''
                        if(current != null)
                          current.submit();
                        ''');
                        _focusNode1.unfocus();
                      },
                    ),
                    TextField(
                      autofocus: false,
                      focusNode: _focusNode2,
                      controller: textController2,
                      onChanged: (text) {
                        controller.evaluateJavascript('''
                         if(current != null){
                          current.value = '${textController2.text}';
                          current.selectionStart = ${textController2.selection.start};
                          current.selectionEnd = ${textController2.selection.end};
                          current.dispatchEvent(new Event('input'));
                         }
                        ''');
                      },
                      onSubmitted: (text) {
                        controller.evaluateJavascript('''
                        if(current != null)
                          current.submit();
                        ''');
                        _focusNode2.unfocus();
                      },
                    ),
                    WebView(....)
                  ]
  );
复制代码
  • 現在の要素のテキスト/選択の焦点のテキストフィールドのonChange適応では、その要素の変化をトリガする入力イベントを送信しcurrent.dispatchEvent(new Event('input'));、我々はよく理解している必要があります。

WebViewのは、実際にこのような大きな欠陥を持っている、Googleはあまりにもピットであると言っているが、この方法の1.0.0にないバージョン番号は、すべての後に、方法はありません...それは、このようなソフトキーボードの機能を非表示にするには、空白をクリックするだけで、一時的な解決策であり、手動で、またはそれ以上はまだ可能であり、キーボードの下に隠されたボタンなどの一部の入力ラベルを持っていることだけWebViewの単純なテキスト入力を使用して実装されていません。

ます。https://juejin.im/post/5cfa30b56fb9a07ebf4b6097で再現

おすすめ

転載: blog.csdn.net/weixin_34293141/article/details/91470579