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

Flutter webview text input gets hidden by soft keyboard

我正在 Android 上进行测试(我也会在 iOS 上验证它是否相同)。

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

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

我自己尝试了一种将 Web 视图放入具有动态高度的 container() 中的技巧。它有点管用。代码如下,重点是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...

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

这对我有用:

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

这里有一个更简单的方法,使用 '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(),
                  ),
                ),
            ),
          ],
        ),
      ),
    );
  }
}

尝试一下,看看它是否能解决您的问题

我的答案有两点。

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

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

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

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()
              : 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(),
        ],
      ),
    );
  }