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(),
],
),
);
}
我正在 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(),
],
),
);
}