Flutter webview 文本输入被软键盘隐藏

时间:2021-04-27 15:42:33

标签: flutter webview android-softkeyboard

我正在 Android 上进行测试(我将验证它在 iOS 上也是一样的)。

我的问题是,当我有一个显示条纹结帐页面的 web 视图时,我点击那里的文本条目以在底部附近输入一些内容(邮政编码),然后虚拟键盘覆盖了 web 视图,我无法向上滚动即使在网络视图中。

webview 似乎按预期占据了整个屏幕,但是当软键盘出现时 Flutter 我认为通常会为它腾出空间(缩小屏幕上显示的小部件)。 Webview 似乎只是保持相同的大小。

我自己尝试了将 Web 视图放入具有动态高度的容器 () 中的技巧。它有点工作。代码如下,关键是Container()的这个高度:

height: MediaQuery.of(context).size.height * (MediaQuery.of(context).viewInsets.bottom != 0 ? .7 : 1)

但这有混淆键盘的问题。例如,它以某种方式欺骗键盘不是邮政编码的数字输入类型。看起来它尝试过,但一秒钟后重新绘制到非数字键盘。

为什么 Webview 不尊重手机上的软键盘?

这是我在有状态小部件中的构建:

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Stack(
        children: [
          initialUrl == null
              ? Container()
              : Container(
                  height: MediaQuery.of(context).size.height * (MediaQuery.of(context).viewInsets.bottom != 0 ? .7 : 1),
                  child: WebView(
                    initialUrl: initialUrl,
                    javascriptMode: JavascriptMode.unrestricted,
                    onPageStarted: (controller) {},
                    onPageFinished: (controller) {
                      Future.delayed(Duration(milliseconds: 1234), () {
                        if (mounted) {
                          showLoading = false;
                          setState(() {});
                        }
                      });
                    },
                    navigationDelegate: (NavigationRequest request) {
                      if (request.url.startsWith('https://example.com/success')) {
                        Navigator.of(context).pop('success');
                      } else if (request.url.startsWith('https://example.com/cancel')) {
                        Navigator.of(context).pop('cancel');
                      }
                      return NavigationDecision.navigate;
                    },
                  ),
                ),
          showLoading == true
              ? Center(
                  child: Container(width: 80, height: 80, child: CircularProgressIndicator()),
                )
              : Container(),
        ],
      ),
    );
  }

这是屏幕截图。请注意,在键盘中,您甚至无法滚动 webview 来查看您正在键入的 zip...

enter image description here enter image description here

4 个答案:

答案 0 :(得分:0)

您是否尝试过用 SingleChildScrollView 包装您的小部件?

答案 1 :(得分:0)

这对我有用:

Scaffold(
      body: Stack(
        children: [
          //... widgets that render behind the column
          Align(
            alignment: Alignment.center,
            child: SingleChildScrollView( 
              child: Column(
                 children: [
                    //... login form inputs and buttons
                 ]
              ),
            ),
          ),
        ],
      ),
    );

答案 2 :(得分:0)

这里有一种更简单的方法,使用“gestureRecognizers”属性将滚动手势移动到 Webview 本身:

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Webview Example',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Webview Example'),
        ),
        body: Stack(
          children: [
            //... widgets that render behind the column
            WebView(
              initialUrl: 'https://inputtypes.com',
              javascriptMode: JavascriptMode.unrestricted,
              gestureRecognizers: Set()
                ..add(
                  Factory<DragGestureRecognizer>(
                    () => VerticalDragGestureRecognizer(),
                  ),
                ),
            ),
          ],
        ),
      ),
    );
  }
}

试试看是否能解决您的问题

答案 3 :(得分:0)

我的答案是两件事。

首先使用这一行在显示 webview 的有状态小部件中设置 WebView.platform。请注意,它特定于我当时在 Android 上的测试,所以也许对于你们中的一些人来说,当你们没有看到这个问题时,你们可能在 iOS 上?

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); // <<== THIS
  }

其次,我添加了一个 resizeToAvoidBottomInset 设置为 true 的 Scaffold 并删除了我对它的使用:

height: MediaQuery.of(context).size.height * (MediaQuery.of(context).viewInsets.bottom != 0 ? .7 : 1),`

这是带有 webview 的 body 的代码

@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Stack(
        children: [
          initialUrl == null
              ? Container()
              : Scaffold(
                resizeToAvoidBottomInset: true,
                body: WebView(
                  initialUrl: initialUrl,
                  javascriptMode: JavascriptMode.unrestricted,
                  onPageStarted: (controller) {},
                  onPageFinished: (controller) {
                    Future.delayed(Duration(milliseconds: 1234), () {
                      if (mounted) {
                        showLoading = false;
                        setState(() {});
                      }
                    });
                  },
                  navigationDelegate: (NavigationRequest request) {
                    if (request.url.startsWith('https://example.com/success')) {
                      Navigator.of(context).pop('success');
                    } else if (request.url.startsWith('https://example.com/cancel')) {
                      Navigator.of(context).pop('cancel');
                    }
                    return NavigationDecision.navigate;
                  },
                ),
              ),
          showLoading == true
              ? Center(
                  child: Container(width: 80, height: 80, child: CircularProgressIndicator()),
                )
              : Container(),
        ],
      ),
    );
  }