Flutter-语法总结
-
获取屏幕宽高:
import 'dart:ui'; // 手机屏幕的大小(逻辑分辨率) final width = MediaQuery.of(context).size.width; final height = MediaQuery.of(context).size.height; // 手机的物理分辨率 final physicalWidth = window.physicalSize.width; final physicalHeight = window.physicalSize.height; // 分辨率 var resolution = physicalWidth * physicalHeight; // 获取dpr final dpr = window.devicePixelRatio; // 屏幕的物理宽度、高度 final width = physicalWidth / dpr; final height = physicalHeight / dpr; print('屏幕宽高: $width * $height'); // 状态栏的高度 final statusHeight = window.padding.top / dpr; print('状态栏的高度: $statusHeight'); // 不同手机尺寸的屏幕的状态栏高度不一致,需要获取状态栏高度 // 设置上边距: MediaQueryData.fromWindow(window).padding.top // 使用时候设置上边距: return Scaffold( body:Container( padding: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top), child: Test("你瞅啥"), ) );
-
配置
WebView
:Widget _logicMapView() { initViewsAnchor(); return Visibility( visible: state.logicMapUrl.length > 0, child: SizedBox( width: MediaQuery.of(context).size.width, // height: 400, height: (MediaQuery.of(context).size.height - _goodsInfoHeightOffsetY - 20), child: Column( children: [ Expanded( child: WebView( initialUrl: state.logicMapUrl, //需要打开的url //是否支持js 默认是不支持的, javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController controller) { //页面加载的时候可以获取到controller可以用来reload等操作 state.logicMapWebController = controller; }, //加载js方法到页面内,js通过此来调用flutter的方法 javascriptChannels: { JavascriptChannel(name: "Resize", onMessageReceived: (JavascriptMessage message) { setState(() { state.logicMapHeight = double.parse(message.message); }); }), }, onPageStarted: (String url) { }, onPageFinished: (String url) { print("你瞅啥:onPageFinished:$state.logicMapWebController"); //调用JS得到实际高度 state.logicMapWebController.evaluateJavascript("document.documentElement.scrollHeight;").then((result){ setState(() { if (state.logicMapHeight != double.parse(result)) { state.logicMapHeight = double.parse(result); } // state.logicMapHeight = 500; }); }); state.logicMapWebController.evaluateJavascript("document.documentElement.body.scrollHeight;").then((result){ print("你瞅啥:evaluateJavascript:body:scrollHeight:"); setState(() { print("你瞅啥:setState:scrollHeight:body:result:$result"); if (state.logicMapHeight != double.parse(result)) { state.logicMapHeight = double.parse(result); } // state.logicMapHeight = 500; }); }); }, //拦截页面url navigationDelegate: (NavigationRequest request) { if (request.url.startsWith('alipays:') || request.url.startsWith('weixin:')) { _openPay(context, request.url); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ), ), ], ), ), ); }
-
WebView
高度计算:flutter一个界面内多个组件,如ListView包裹着一个Text和一个webview,此时,必须计算出webview的高度,才可正常显示,否则程序会因webview没给出高度而layout崩溃。
以下为解决方案:
- 使用SizedBox进行包裹webview:
Widget buildWebView() { return SizedBox( width: _webWidth, height: _webHeight, child: WebView( zoomEnabled: true, initialUrl: _webViewUrl, javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (controller) { _webController = controller; controller.loadUrl(Uri.dataFromString(_webViewUrl, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString()); }, onPageFinished: (url) async { ///获取webView原始高度 var originalHeight = await _webController!.runJavascriptReturningResult("document.documentElement.clientHeight;"); _originalHeight = double.parse(originalHeight); ///获取webView原始宽度 var originalWidth = await _webController!.runJavascriptReturningResult("document.documentElement.clientWidth;"); _originalWidth = double.parse(originalWidth); ///计算等比例 图片高度 /// W1/H1 = W2/H2; /// H2 = H1 * W2 / W1; setState(() { _webHeight = _originalHeight! * _webWidth / _originalWidth!; }); }, ), );
}
```
2. 获取webview内html原始宽度和高度,已知屏幕宽度,求出需要的比例高度
公式:
```
final double _webWidth = WYSizeFit.screenWidth!;// webview 已知屏幕宽度
double _webHeight = 100;// 求 webview高度
double? _originalWidth;//原宽度
double? _originalHeight;//原高度
```
```
onPageFinished: (url) async {
///获取webView原始高度
var originalHeight = await _webController!.runJavascriptReturningResult("document.documentElement.clientHeight;");
_originalHeight = double.parse(originalHeight);
///获取webView原始宽度
var originalWidth = await _webController!.runJavascriptReturningResult("document.documentElement.clientWidth;");
_originalWidth = double.parse(originalWidth);
///计算等比例 图片高度
/// W1/H1 = W2/H2;
/// H2 = H1 * W2 / W1;
setState(() {
_webHeight = _originalHeight! * _webWidth / _originalWidth!;
});
}
```
完整代码:
```
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:jd_shop/core/models/home/w_y_home_model.dart';
import 'package:jd_shop/utils/network/wy_network.dart';
import 'package:jd_shop/utils/network/wy_network_const.dart';
import 'package:jd_shop/utils/screen_size/wy_screen_size.dart';
import 'package:jd_shop/utils/wy_log/wylog.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WYHomeDetailsHistoryView extends StatefulWidget {
final List1 model;
const WYHomeDetailsHistoryView(this.model,{Key? key}) : super(key: key);
@override
_WYHomeDetailsHistoryViewState createState() => _WYHomeDetailsHistoryViewState();
}
class _WYHomeDetailsHistoryViewState extends State<WYHomeDetailsHistoryView> with AutomaticKeepAliveClientMixin {
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
String _webViewUrl = "";
final double _webWidth = WYSizeFit.screenWidth!;// webview 已知屏幕宽度
double _webHeight = 100;// 求 webview高度
double? _originalWidth;//原宽度
double? _originalHeight;//原高度
WebViewController? _webController;
@override
void initState() {
super.initState();
Map<String,dynamic> params = {
"ProductID" : widget.model.productID,
"devtype" : "3",
};
WYHttpRequest.request(WYNetWorkUrl.GetDetailByProID,params: params,loadingStr: "加载中...").then((value){
setState(() {
_webViewUrl = value["Data"]["info"]["Bewrite"];
});
});
}
@override
Widget build(BuildContext context) {
super.build(context);
if(_webViewUrl.isEmpty){
return Text("");
}
return ListView(
shrinkWrap: true,
children: [
Container(
child: Text("我是顶部文字"),
color: Colors.orange,
width: double.infinity,
height: 100,
),
buildWebView(),
],
);
}
Widget buildWebView() {
return SizedBox(
width: _webWidth,
height: _webHeight,
child: WebView(
zoomEnabled: true,
initialUrl: _webViewUrl,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) {
_webController = controller;
controller.loadUrl(Uri.dataFromString(_webViewUrl,
mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString());
},
onPageFinished: (url) async {
///获取webView原始高度
var originalHeight = await _webController!.runJavascriptReturningResult("document.documentElement.clientHeight;");
_originalHeight = double.parse(originalHeight);
///获取webView原始宽度
var originalWidth = await _webController!.runJavascriptReturningResult("document.documentElement.clientWidth;");
_originalWidth = double.parse(originalWidth);
///计算等比例 图片高度
/// W1/H1 = W2/H2;
/// H2 = H1 * W2 / W1;
setState(() {
_webHeight = _originalHeight! * _webWidth / _originalWidth!;
});
},
),
);
}
@override
void dispose() {
//为了避免内存泄露,需要调用
super.dispose();
}
}
```
-
获取某个
Widget
的宽高、位置:class HomePageState extends State<HomePage> with SingleTickerProviderStateMixin { // 全局定义需要获取的组件的标识key GlobalKey _anchorKey = GlobalKey(); // 需要获取的控件的y double _goodsInfoHeightOffsetY = 0.0; // 获取标识key的位置信息 double initOffsetY(GlobalKey key) { if (key.currentContext == null) { return null; } // 获取标识key的相关信息 RenderBox renderBox = key.currentContext.findRenderObject(); // 获取标识key的位置:offset.dx , offset.dy 就是控件的左上角坐标 var offset = renderBox.localToGlobal(Offset.zero); // 获取标识key的位置:offset.dx , offset.dy 就是控件的左下角坐标 var offset1 = renderBox.localToGlobal(Offset(0.0, renderBox.size.height)); // 获取标识key的大小 var size = renderBox.size; // return renderBox.localToGlobal(Offset.zero).dy; return renderBox.localToGlobal(Offset(0.0, renderBox.size.height)).dy; } // 获取标识key的回调信息 void initViewsAnchor() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { _goodsInfoHeightOffsetY = initOffsetY(_anchorKey); }); } @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; var width = size.width; var height = size.height; return Scaffold( appBar: AppBar( title: Text('Width & Height'), ), body: Center( child: Container( // 需要获取位置的组件,添加key key: _anchorKey, color: Colors.redAccent, width: width / 2, height: height / 2, ), ), ); } Widget _logicMapView() { // 需要根据某个组件确定自己位置时,调用该自定义方法,获取上面组件的位置 initViewsAnchor(); return Visibility( visible: state.logicMapUrl.length > 0, child: SizedBox( width: MediaQuery.of(context).size.width, // 通过获取到的上面组件的位置,来确定新组件的大小 height: (MediaQuery.of(context).size.height - _goodsInfoHeightOffsetY - 20), child: 。。。。。, ), ); } }
-
地址选择器:
# flutter_jd_address_selector: # git: # url: https://github.com/shenhuaxiyuan/flutter_jd_address_selector
-
苹果iOS16,使用自己服务器下载的ipa包,无法安装。
// 可能是 .plist 文件的 Bundle ID 跟ipa包不对应,修改Bundle ID即可。