内部没有高度的 WebView 滚动不起作用
WebView without height inside Scroll not working
在 Flutter 上...我尝试在所有支持滚动的可用容器中添加 Webview,但它在 Android 上不起作用。
ListView(
shrinkWrap: true,
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Expanded(
child: WebView(
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
],
)
如果你想将你的可滚动 WebView 放在其他小部件之间,并且 WebView 将是可滚动的,而其他小部件则不是,那么只需像这样更改 Column 的 ListView:
Column(
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Container(
height: 300,
child: WebView(
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")
),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
)
但是如果你想在 WebView 之上有一些可滚动的小部件,那么试试
CustomScrollView or SliverList.
你能说出你试图做出的确切逻辑是什么吗?
增加:
如果你想有可滚动区域和一些内部的WebView,你必须知道WebView的高度:
ListView(
physics: ClampingScrollPhysics(),
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 10000),
child: WebView(
gestureRecognizers: Set()
..add(
Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),
), // or null
),
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
],
);
WebView的高度可以动态获取,灵感在这里:
https://gist.github.com/PonnamKarthik/877a90917a576ecff613d5169680d02c
感谢 dubace 的解决方案 gist.github.com/PonnamKarthik/877a90917a576ecff613d5169680d02c
问题已解决,现在我们可以在父级可滚动容器中添加 Webview。
导入'dart:convert';
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: 'Flutter Code Sample',
builder: (BuildContext context, Widget navigator) {
return MyStatelessWidget();
},
);
}
}
class MyStatelessWidget extends StatefulWidget {
MyStatelessWidget({Key key}) : super(key: key);
@override
_MyStatelessWidgetState createState() => _MyStatelessWidgetState();
}
class _MyStatelessWidgetState extends State<MyStatelessWidget> {
List<WebViewController> _listController = List();
List<double> _heights =
List<double>.generate(htmlStrings.length, (int index) => 20.0);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: htmlStrings.length,
itemBuilder: (context, index) {
return Container(
height: _heights[index] ?? 100.0,
child: WebView(
initialUrl:
'data:text/html;base64,${base64Encode(const Utf8Encoder().convert(htmlStrings[index]))}',
onPageFinished: (some) async {
double height = double.parse(await _listController[index]
.evaluateJavascript(
"document.documentElement.scrollHeight;"));
setState(() {
_heights[index] = height;
});
},
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) async {
_listController.add(controller);
},
),
);
},
),
);
}
}
final List<String> htmlStrings = [
'''<p>Table shows some compounds and the name of their manufacturing process</p>
<table style="border-collapse: collapse; width: 100%; height: 85px;" border="1">
<tbody>
<tr style="height: 17px;">
<td style="width: 50%; text-align: center; height: 17px;">Compounds/Elements</td>
<td style="width: 50%; text-align: center; height: 17px;">Manufacture process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Nitric acid</td>
<td style="width: 50%; height: 17px;">Ostwald's process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Ammonia</td>
<td style="width: 50%; height: 17px;">Haber's process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Sulphuric acid</td>
<td style="width: 50%; height: 17px;">Contact process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Sodium</td>
<td style="width: 50%; height: 17px;">Down's process</td>
</tr>
</tbody>
</table>''',
'''<p>\(L=[M{L }^{2 }{T }^{-2 }{A }^{-2 }]\)</p>
<p>\(C=[{M }^{-1 }{L }^{-2 }{T }^{4 }{A }^{2 }]\)</p>
<p>\(R=[M{L }^{2 }{T }^{-3 }{A }^{-2 }]\)</p>
<p>\(\therefore \frac {R}{L}=\frac{[M{L }^{2 }{T }^{-2 }{A }^{-2 }]}{[M{L }^{2 }{T }^{-3 }{A }^{-2 }]}=[T]\)</p>''',
'''<p>Displacement(s)\(=\left(13.8\pm0.2\right)m\)</p>
<p>Time(t)\(=\left(4.0\pm0.3\right)s\)</p>
<p>Velocity(v)\(=\frac{13.8}{4.0}=3.45m{s}^{-1}\)</p>
<p>\(\frac{\delta v}{v}=\pm\left(\frac{\delta s}{s}+\frac{\delta t}{t}\right)=\pm\left(\frac{0.2}{13.8}+\frac{0.3}{4.0}\right)=\pm0.0895\)</p>
<p>\(\delta v =\pm0.0895*3.45=\pm0.3\)(rounding off to one place of decimal)</p>
<p>\(v=\left(3.45\pm0.3\right)m{s}^{-1}\)</p>''',
'''<p>The only real numbers satisfying \(x^2=4\) are 2 and -2. But none of them satisfy the final condition, \(x+2=3\). So, there is no real number such that these conditions are met. Hence this is null set.</p>
<p>Note that, for \(x\) to be a memner of \(\{x:p(x),q(x)\}\), <em><strong>both</strong></em> \(p(x)\) and \(q(x)\) should be true.</p>''',
];
第一种方法:-
制作一个完整的可滚动小部件,其中包含 WebView(具有动态高度)和其上方和下方的其他容器。都应该在父 Widget
内滚动
确保 flutter 包:webview_flutter: any
已正确安装。
1.create Future
fxn
String hight;
double webHight =400; //default some value
Future funcThatMakesAsyncCall() async{
var result =
await controller.evaluateJavascript('document.body.scrollHeight');
//here we call javascript for get browser data
setState(() {
hight = result;
},);}
2.we 使用 SingleChildScrollView
滚动方向:Axis.vertical,
3.Inside 使用 Column
4.finally 我们使用 Conatiner
在 Container
中我们使用 WebView
此处Container
代码
Container(
height: webHight+20,
child: WebView(
initialUrl: widget.url,
onPageFinished: (webhight)async{
await funcThatMakesAsyncCall();
setState((){
webHight= double.parse(hight);
});
},
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
),
第二种方法:-
插件版本 :> webview_flutter: ^3.0.4
Column(
children: [
Container(
height: Get.height * 0.1,
color: Colors.amber,
),
Expanded(
// height: 200,
child: WebView(
gestureNavigationEnabled: true,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
},
onWebViewCreated: (WebViewController webViewController) {
bscontroller.webcontroller = webViewController;
},
initialUrl: 'https://flutter.dev',
),
)
],
),
当我再次遇到同样的问题并尝试我的旧答案时,这一次对我来说不起作用,所以我想出了另一种方法
以及对同一问题的第二个答案
一开始我遇到了同样的问题。您可以指定传递哪些手势
使用 gestureRecognizers 参数进入 webView 小部件。下面的代码有助于捕获垂直滚动事件。
WebView(
initialUrl: someUrl,
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer())),
)
我发现这个post对webview也很有用
The Power of WebViews in Flutter
在 Flutter 上...我尝试在所有支持滚动的可用容器中添加 Webview,但它在 Android 上不起作用。
ListView(
shrinkWrap: true,
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Expanded(
child: WebView(
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
],
)
如果你想将你的可滚动 WebView 放在其他小部件之间,并且 WebView 将是可滚动的,而其他小部件则不是,那么只需像这样更改 Column 的 ListView:
Column(
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
Container(
height: 300,
child: WebView(
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")
),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
)
但是如果你想在 WebView 之上有一些可滚动的小部件,那么试试 CustomScrollView or SliverList.
你能说出你试图做出的确切逻辑是什么吗?
增加:
如果你想有可滚动区域和一些内部的WebView,你必须知道WebView的高度:
ListView(
physics: ClampingScrollPhysics(),
children: <Widget>[
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 10000),
child: WebView(
gestureRecognizers: Set()
..add(
Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),
), // or null
),
key: Key("webview1"),
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: "https://flutter.dev/")),
Text("hiiiiiiiiiiiii "),
Text("hiiiiiiiiiiiii "),
],
);
WebView的高度可以动态获取,灵感在这里: https://gist.github.com/PonnamKarthik/877a90917a576ecff613d5169680d02c
感谢 dubace 的解决方案 gist.github.com/PonnamKarthik/877a90917a576ecff613d5169680d02c
问题已解决,现在我们可以在父级可滚动容器中添加 Webview。
导入'dart:convert';
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: 'Flutter Code Sample',
builder: (BuildContext context, Widget navigator) {
return MyStatelessWidget();
},
);
}
}
class MyStatelessWidget extends StatefulWidget {
MyStatelessWidget({Key key}) : super(key: key);
@override
_MyStatelessWidgetState createState() => _MyStatelessWidgetState();
}
class _MyStatelessWidgetState extends State<MyStatelessWidget> {
List<WebViewController> _listController = List();
List<double> _heights =
List<double>.generate(htmlStrings.length, (int index) => 20.0);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: htmlStrings.length,
itemBuilder: (context, index) {
return Container(
height: _heights[index] ?? 100.0,
child: WebView(
initialUrl:
'data:text/html;base64,${base64Encode(const Utf8Encoder().convert(htmlStrings[index]))}',
onPageFinished: (some) async {
double height = double.parse(await _listController[index]
.evaluateJavascript(
"document.documentElement.scrollHeight;"));
setState(() {
_heights[index] = height;
});
},
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) async {
_listController.add(controller);
},
),
);
},
),
);
}
}
final List<String> htmlStrings = [
'''<p>Table shows some compounds and the name of their manufacturing process</p>
<table style="border-collapse: collapse; width: 100%; height: 85px;" border="1">
<tbody>
<tr style="height: 17px;">
<td style="width: 50%; text-align: center; height: 17px;">Compounds/Elements</td>
<td style="width: 50%; text-align: center; height: 17px;">Manufacture process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Nitric acid</td>
<td style="width: 50%; height: 17px;">Ostwald's process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Ammonia</td>
<td style="width: 50%; height: 17px;">Haber's process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Sulphuric acid</td>
<td style="width: 50%; height: 17px;">Contact process</td>
</tr>
<tr style="height: 17px;">
<td style="width: 50%; height: 17px;">Sodium</td>
<td style="width: 50%; height: 17px;">Down's process</td>
</tr>
</tbody>
</table>''',
'''<p>\(L=[M{L }^{2 }{T }^{-2 }{A }^{-2 }]\)</p>
<p>\(C=[{M }^{-1 }{L }^{-2 }{T }^{4 }{A }^{2 }]\)</p>
<p>\(R=[M{L }^{2 }{T }^{-3 }{A }^{-2 }]\)</p>
<p>\(\therefore \frac {R}{L}=\frac{[M{L }^{2 }{T }^{-2 }{A }^{-2 }]}{[M{L }^{2 }{T }^{-3 }{A }^{-2 }]}=[T]\)</p>''',
'''<p>Displacement(s)\(=\left(13.8\pm0.2\right)m\)</p>
<p>Time(t)\(=\left(4.0\pm0.3\right)s\)</p>
<p>Velocity(v)\(=\frac{13.8}{4.0}=3.45m{s}^{-1}\)</p>
<p>\(\frac{\delta v}{v}=\pm\left(\frac{\delta s}{s}+\frac{\delta t}{t}\right)=\pm\left(\frac{0.2}{13.8}+\frac{0.3}{4.0}\right)=\pm0.0895\)</p>
<p>\(\delta v =\pm0.0895*3.45=\pm0.3\)(rounding off to one place of decimal)</p>
<p>\(v=\left(3.45\pm0.3\right)m{s}^{-1}\)</p>''',
'''<p>The only real numbers satisfying \(x^2=4\) are 2 and -2. But none of them satisfy the final condition, \(x+2=3\). So, there is no real number such that these conditions are met. Hence this is null set.</p>
<p>Note that, for \(x\) to be a memner of \(\{x:p(x),q(x)\}\), <em><strong>both</strong></em> \(p(x)\) and \(q(x)\) should be true.</p>''',
];
第一种方法:-
制作一个完整的可滚动小部件,其中包含 WebView(具有动态高度)和其上方和下方的其他容器。都应该在父 Widget
内滚动确保 flutter 包:webview_flutter: any
已正确安装。
1.create Future
fxn
String hight;
double webHight =400; //default some value
Future funcThatMakesAsyncCall() async{
var result =
await controller.evaluateJavascript('document.body.scrollHeight');
//here we call javascript for get browser data
setState(() {
hight = result;
},);}
2.we 使用 SingleChildScrollView
滚动方向:Axis.vertical,
3.Inside 使用 Column
4.finally 我们使用 Conatiner
在 Container
中我们使用 WebView
此处Container
代码
Container(
height: webHight+20,
child: WebView(
initialUrl: widget.url,
onPageFinished: (webhight)async{
await funcThatMakesAsyncCall();
setState((){
webHight= double.parse(hight);
});
},
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
},
),
),
第二种方法:-
插件版本 :> webview_flutter: ^3.0.4
Column(
children: [
Container(
height: Get.height * 0.1,
color: Colors.amber,
),
Expanded(
// height: 200,
child: WebView(
gestureNavigationEnabled: true,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
),
},
onWebViewCreated: (WebViewController webViewController) {
bscontroller.webcontroller = webViewController;
},
initialUrl: 'https://flutter.dev',
),
)
],
),
当我再次遇到同样的问题并尝试我的旧答案时,这一次对我来说不起作用,所以我想出了另一种方法
以及对同一问题的第二个答案
一开始我遇到了同样的问题。您可以指定传递哪些手势 使用 gestureRecognizers 参数进入 webView 小部件。下面的代码有助于捕获垂直滚动事件。
WebView(
initialUrl: someUrl,
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer())),
)
我发现这个post对webview也很有用 The Power of WebViews in Flutter