Início
Conheça mais
Enviar pesquisa
Carregar
Entrar
Cadastre-se
Anúncio
Check these out next
Jenkins 再入門
Jumpei Miyata
新しくなったモノビットエンジンを使って10万人規模のサーバを構築するノウハウを公開!2017年10月27日モノビットエンジン勉強会
モノビット エンジン
Flutter
Dave Chao
Introduction to flutter
Wan Muzaffar Wan Hashim
.NET Core 3.0 + Windows 10 で WPF 開発
一希 大田
Android Fragment
Kan-Han (John) Lu
C#エンジニアのためのdocker kubernetesハンズオン (再)
Takayoshi Tanaka
イベント駆動プログラミングとI/O多重化
Gosuke Miyashita
1
de
31
Top clipped slide
怎樣在 Flutter app 中使用 Google Maps
9 de Feb de 2023
•
0 gostou
0 gostaram
×
Seja o primeiro a gostar disto
mostrar mais
•
162 visualizações
visualizações
×
Vistos totais
0
No Slideshare
0
De incorporações
0
Número de incorporações
0
Baixar agora
Baixar para ler offline
Denunciar
Tecnologia
放置地圖 Widget 新增 Marker 新增 Polyline 計算 zoom level 顯示 information window 移動地圖、設定樣式 其他…
Weizhong Yang
Seguir
Software engineer em KKBOX
Anúncio
Anúncio
Anúncio
Recomendados
導入 Flutter 前你應該知道的事
Weizhong Yang
6K visualizações
•
43 slides
Use Symfony Messenger Component and CQRS!
Žilvinas Kuusas
799 visualizações
•
48 slides
20150530 めとべや東京 Reactive Property + Livetで作るWPFアプリ
Takayoshi Tanaka
1.1K visualizações
•
47 slides
Flutter 踩雷心得
Weizhong Yang
5.9K visualizações
•
41 slides
WkWebViewのキャッシュについて調べた
firewood
19.9K visualizações
•
23 slides
Packer
Nitesh Saini
509 visualizações
•
33 slides
Mais conteúdo relacionado
Apresentações para você
(20)
Jenkins 再入門
Jumpei Miyata
•
67.7K visualizações
新しくなったモノビットエンジンを使って10万人規模のサーバを構築するノウハウを公開!2017年10月27日モノビットエンジン勉強会
モノビット エンジン
•
9.5K visualizações
Flutter
Dave Chao
•
294 visualizações
Introduction to flutter
Wan Muzaffar Wan Hashim
•
1.6K visualizações
.NET Core 3.0 + Windows 10 で WPF 開発
一希 大田
•
11.1K visualizações
Android Fragment
Kan-Han (John) Lu
•
1.6K visualizações
C#エンジニアのためのdocker kubernetesハンズオン (再)
Takayoshi Tanaka
•
2.8K visualizações
イベント駆動プログラミングとI/O多重化
Gosuke Miyashita
•
15.2K visualizações
SharePointアドイン開発 Line風Chat アドイン
Akihiro Ehara
•
1.6K visualizações
C#/WPFで作るデスクトップマスコット入門
Fujikido
•
31.9K visualizações
Flutter workshop
Narayan Vyas
•
184 visualizações
Cesiumを動かしてみよう
Kazutaka ishizaki
•
26.5K visualizações
Packer by HashiCorp
Łukasz Cieśluk
•
3.2K visualizações
Android カスタムROMの作り方
Masahiro Hidaka
•
41K visualizações
Multibranch pipelineでいろいろ学んだこと
Recruit Lifestyle Co., Ltd.
•
1.9K visualizações
Wpfと非同期
yone64
•
8.7K visualizações
テスト自動化ツール[Selenium]を検討してみて
裕史 川松
•
7.6K visualizações
Exploring Thermal Related Stuff in iDevices using Open-Source Tool
Koan-Sin Tan
•
2.4K visualizações
Ansible - Hands on Training
Mehmet Ali Aydın
•
5.6K visualizações
モバイル通信を使わない 近接端末間通信対戦のレシピ
NakamuraTaro
•
1.6K visualizações
Similar a 怎樣在 Flutter app 中使用 Google Maps
(20)
再接再勵學 Swift 程式設計
政斌 楊
•
601 visualizações
I os 07
信嘉 陳
•
673 visualizações
2016輕鬆開發自有網路地圖工作坊 進階班 0701
family
•
835 visualizações
Google map api接口整理
lileinba
•
988 visualizações
Responsive Web UI Design
jay li
•
4.4K visualizações
Html5移动web应用开发(PhoneGap)
amd6400
•
588 visualizações
Html5移动web应用开发(PhoneGap)
amd6400
•
1K visualizações
Study mapapi v0.1
Paul Yang
•
365 visualizações
I os 02
信嘉 陳
•
458 visualizações
AngularJS training in Luster
Jason Chung
•
13.9K visualizações
Android 智慧型手機程式設計
Kyle Lin
•
867 visualizações
Behind Tetris5
Junwen Sun
•
859 visualizações
Anroid development part.1
RANK LIU
•
1K visualizações
行動商務實務 - PhoneGap Advance
My own sweet home!
•
557 visualizações
I os 01
信嘉 陳
•
520 visualizações
Introduction to corona sdk
馬 萬圳
•
144.5K visualizações
HTML5移动WEB应用程序开发(PhoneGap)
amd6400
•
679 visualizações
HTML5移动应用开发分享会(PhoneGap)
amd6400
•
749 visualizações
2021laravelconftwslides12
LiviaLiaoFontech
•
101 visualizações
給 iOS 工程師的 Flutter 開發
Weizhong Yang
•
7.8K visualizações
Anúncio
Mais de Weizhong Yang
(20)
Flutter BLE
Weizhong Yang
•
152 visualizações
關於延長役期這件事情
Weizhong Yang
•
862 visualizações
Dart null safety
Weizhong Yang
•
703 visualizações
Github Actions
Weizhong Yang
•
945 visualizações
iPlayground: CarPlay and MFI Hearing Aids
Weizhong Yang
•
924 visualizações
CocoaPods private repo
Weizhong Yang
•
1.6K visualizações
那些年被蘋果 Ban 掉的 API
Weizhong Yang
•
3.2K visualizações
給 iOS 工程師的 Vue.js 開發
Weizhong Yang
•
10.3K visualizações
苦集滅道:透過開發客製 Sketch Plug-in 改善產品設計流程
Weizhong Yang
•
3.3K visualizações
使用 switch/case 重構程式碼
Weizhong Yang
•
8.5K visualizações
怎樣寫出比較沒有問題的 Code
Weizhong Yang
•
13.3K visualizações
貪食蛇
Weizhong Yang
•
5.4K visualizações
Aspect Oriented Programming
Weizhong Yang
•
2.6K visualizações
Mac OS X 與 iOS 的 Audio API
Weizhong Yang
•
2.9K visualizações
Html 5 native drag
Weizhong Yang
•
971 visualizações
Retina mac
Weizhong Yang
•
1.1K visualizações
Python 的文件系統
Weizhong Yang
•
789 visualizações
Input Method Kit
Weizhong Yang
•
3.3K visualizações
Refactoring
Weizhong Yang
•
816 visualizações
Core animation
Weizhong Yang
•
1.8K visualizações
Último
(20)
49133383-Final (1).pdf
AryanAmeen1
•
1 visão
留信网认证可查【内华达大学拉斯维加斯分校文凭证书毕业证购买】
32lkhng
•
2 visualizações
留信网认证可查【切斯特大学文凭证书毕业证购买】
12da12
•
2 visualizações
☀️【路易斯维尔大学毕业证成绩单留学生首选】
2125nuh
•
2 visualizações
留信网认证可查【威斯康星大学白水分校文凭证书毕业证购买】
hh123hh1
•
2 visualizações
☀️【斯图加特大学毕业证成绩单留学生首选】
bjd42as
•
2 visualizações
☀️【阿卡迪亚大学毕业证成绩单留学生首选】
15sad
•
2 visualizações
CMMC合規需求調查問卷.pptx
jacklee422407
•
3 visualizações
留信网认证可查【加州州立大学圣贝纳迪诺分校文凭证书毕业证购买】
32lkhng
•
2 visualizações
☀️【杜塞尔多夫大学毕业证成绩单留学生首选】
bjd42as
•
2 visualizações
Configuration of Meter_Data_Management_Systems.pdf
Bhekumuzi Xaba
•
3 visualizações
☀️【巴斯大学毕业证成绩单留学生首选】
25mjhd12
•
2 visualizações
☀️【肯塔基大学毕业证成绩单留学生首选】
2125nuh
•
2 visualizações
在哪里可以办美国大学文凭《麦纳特州立大学毕业证成绩单仿制》
efagvah
•
3 visualizações
☀️【北卡罗来纳大学教堂山分校毕业证成绩单留学生首选】
2125nuh
•
3 visualizações
Expecto Patronum! Stable Diffusion!
William Chong
•
5 visualizações
☀️【北英属哥伦比亚大学毕业证成绩单留学生首选】
bjd42as
•
2 visualizações
①【拉筹伯大学毕业证文凭学位证书|工艺完美复刻】
vgh215w
•
2 visualizações
留信网认证可查【中央昆士兰大学文凭证书毕业证购买】
khh123kj
•
4 visualizações
Kevin Lognone Agenda at the European Innovation Week 2023 歐盟創新週
Kevin Lognoné
•
2 visualizações
Anúncio
怎樣在 Flutter app 中使用 Google Maps
怎樣在 Flutter App
中整合 Google Maps Weizhong Yang a.k.a zonble zonble@gmail.com
關於我 Weizhong Yang a.k.a
zonble • 最近⼗年都在做 App 開發 • Flutter GDE (2019-) • Developer Manager at Cerence Inc (2020-) • iOS Developer Lead at KKBOX (2011-2020) • 今年做的事:講了⼀場 Flutter Desktop plugin 開發,下半年常跑⾦⾨,開始重 寫⼆⼗年前的《防區狀況三⽣效》的新章… • Twitter @zonble
還記得我去年的題⽬? 總之,今年我們把去年題⽬裡頭的那個 App 商品化了
Cerence Link
這個 App 有哪些功能? •
顯示 ODB 傳來的讀數(速度、溫度等) • 在地圖上顯示⽬前⾞⼦與⼿機的位置 • 顯示 Journey(每次⾞⼦上⽕/熄⽕之間的駕駛紀錄) • 路徑規劃: • 怎樣⾛到我的⾞⼦? • 怎樣去加油站/維修站/⾃訂地點? • Geo Fence 規劃(在某個區域開⾞時發出警告) • Curfew 規劃(在某個時間開⾞發出警告) • 各種警告—急彎、急停、撞擊、進⼊ Geo Fence
這個 App ⼤量需要顯示地圖
Agenda • 放置地圖 Widget •
新增 Marker • 新增 Polyline • 計算 zoom level • 顯示 information window • 移動地圖、設定樣式 • 其他…
會⽤到哪些 package? • google_maps_ fl utter:
The o ffi cial package • custom_info_window: Show custom window in the map • google_place: Google Place API • google_maps_utils: 地圖相關計算功能 • fl utter_polyline_points: encode/decode Google polyline string
基本導⼊ • 更新 pubspec.yaml •
加⼊ google_maps_ fl utter • fl utter pub get • 需要⼀些平台權限,例如使⽤ GPS 等,需要在 iOS 的 Info Plist 以及 Android 的 Manifest 裡頭加上對應設定 • Android 上需要安裝 Google Maps App
基本⽤法 GoogleMap( minMaxZoomPreference: MinMaxZoomPreference(0, 16), initialCameraPosition:
LatLng(…..), mapType: MapType.normal, mapToolbarEnabled: false, zoomControlsEnabled: false, rotateGesturesEnabled: false, scrollGesturesEnabled: false, zoomGesturesEnabled: false, myLocationButtonEnabled: false, )
Platform View • Google
Maps Widget 是⼀個 Platform View • 將 Native View 包進 Flutter 中 • 現在我們也可以在 Platform View 上重疊任意的 Flutter Widget
加上 Marker fi nal startPoint
= await BitmapDescriptor.fromAssetImage( ImageCon fi guration(size: Size(100, 100)), ‘asset/image.png’); var markers = []; fi nal startPoint = Marker( markerId: MarkerId('pin-start'), icon: _startPoint, anchor: O ff set(0.5, 0.5), position: LatLng(….)), zIndex: 10, ); markers.add(startPoint); GoogleMap(markers:markers); Image 的載⼊可以使⽤ Future Builder 需要注意載⼊的解析度(@2x、@3x)
放置 SVG Marker import
'dart:ui' as ui; import ‘package: fl utter_svg/ fl utter_svg.dart'; static Future<BitmapDescriptor?> bitmapDescriptorFromSvgAsset( BuildContext context, String assetName, Size size) async { // Read SVG fi le as String String svgString = await DefaultAssetBundle.of(context).loadString(assetNa me); // Create DrawableRoot from SVG String DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, 'a'); // toPicture() and toImage() don't seem to be pixel ratio aware, so we calculate the actual sizes here MediaQueryData queryData = MediaQuery.of(context); double devicePixelRatio = queryData.devicePixelRatio; double width = size.width * devicePixelRatio; // where 32 is your SVG's original width double height = size.height * devicePixelRatio; // same thing // Convert to ui.Picture ui.Picture picture = svgDrawableRoot.toPicture(size: Size(width, height)); ui.Image image = await picture.toImage(width.toInt(), height.toInt()); ByteData? bytes = await image.toByteData(format: ui.ImageByteFormat.png); fi nal bu ff er = bytes?.bu ff er; if (bu ff er != null) { return BitmapDescriptor.fromBytes(bu ff er.asUint8List()); } return null; }
加上 Polyline fi nal points
= <LatLng>[……]; var lines = <Polyline>{}; fi nal line = Polyline( polylineId: PolylineId('planning_route'), color: planningRouteColor, width: 6, points: points, ); lines.add(line); GoogleMap(polylines: polylines);
根據 route 計算
zoom level num latRad(lat) { var sin = math.sin(lat * math.pi / 180); var radX2 = math.log((1 + sin) / (1 - sin)) / 2; return math.max(math.min(radX2, math.pi), -math.pi) / 2; } num zoom(mapPx, worldPx, fraction) { if (fraction == 0) { return 21; } fi nal left = math.log(mapPx / worldPx / fraction); fi nal result = (left. fl oor() / math.ln2); return result; } List<num> _getRegion(num screenWidth, num screenHeight) { num zoomMax = 16.0; num? minLong = ….; num? maxLong = ….; num? minLat = ….; num? maxLat = ….; fi nal latFraction = (latRad(maxLat) - latRad(minLat)) / math.pi; fi nal lngDi ff = maxLong - minLong; fi nal lngFraction = ((lngDi ff < 0) ? (lngDi ff + 360) : lngDi ff ) / 360; num latZoom = zoom(screenHeight, 256, latFraction); num lngZoom = zoom(screenWidth, 256, lngFraction); fi nal zoomLevel = math.min(math.min(latZoom, lngZoom) * 0.99, zoomMax); fi nal centerLat = (maxLat + minLat) / 2; fi nal centerLong = (maxLong + minLong) / 2; return [centerLat, centerLong, zoomLevel]; }
Custom Info Window custom_info_window https://pub.dev/packages/custom_info_window
Custom Info Window Stack( children:
[ PreloadMapWrapper( child: GoogleMap( onCameraMove: (position) { _customInfoWindowController.onCameraMove?.call(); }, onMapCreated: (GoogleMapController controller) { _customInfoWindowController.googleMapController = controller; _mapController = controller; }, ), ), CustomInfoWindow( controller: _customInfoWindowController, width: 274, height: 189, o ff set: 30, ), ], ); var _customInfoWindowController = CustomInfoWindowController(); _customInfoWindowController.addInfoWindow?.call(window, LatLng(…)); _customInfoWindowController.hideInfoWindow?.call();
Circle fi nal pin =
Circle( circleId: CircleId('circle'), radius: radius.toDouble(), fi llColor: …., strokeColor: …., center: location, ); fi nal circles = <Circle>{}; circles.add(pin); GoogleMap( circles: circles )
如何更新地圖內容 • 可以透過 setState()
更新包含 GoogleMap Widget 的 Widget • 如果使⽤ Bloc,可以將 GoogleMap Widget 放在 BlocBuilder 中 • 以上⽅式可以修改有哪些 Marker、Polyline 與 Circle,不會改變地圖的 zoom level 與中央位置
移動地圖 Future<void> goTo(num latitude,
num longitude) async { fi nal position = CameraPosition( target: LatLng(latitude.toDouble(), longitude.toDouble()), zoom: zoomLevel, ); _mapController?.animateCamera(CameraUpdate.newCameraPosition(position)); } GoogleMapController? _mapController GoogleMap( onMapCreated: (GoogleMapController controller) { _mapController = controller; }, ),
進階設置 • liteModeEnabled:⽤在完全靜態的地圖上 • indoorViewEnabled:顯示室內導航 •
tra ffi cEnabled:顯示交通狀況 • buildingsEnabled:顯示建築物模型
設定地圖樣式 • GoogleMap Widget
本身 沒有 light/dark mode • ⽽是設置整個 Map 樣式 的 JSON • https:// console.cloud.google.co m/projectselector2/ google/maps-apis/studio/ styles?pli=1
設定地圖樣式 rootBundle.loadString('assets/map_style.txt').then((string) { _mapStyle =
string; }); GoogleMap( onMapCreated: (GoogleMapController controller) { mapController = controller; mapController.setMapStyle(_mapStyle); } ); 這個 Future 也可以考慮放在 FutureBuilder 裡頭
疑難雜症 • Android 上,如果
App 放在背景再回到前景,之後 GoogleMap Widget 可 能畫⾯花掉,或是有奇怪的狀況 • 可以⽤ WidgetsBindingObserver 偵測回到前景重繪 (didChangeAppLifecycleState) • 重新 Build GoogleMap Widget 也不⾒得會重繪 • 但是呼叫 setMapStyle ⼀定可以重繪
地點搜尋
地點搜尋 fi nal _googlePlace =
GooglePlace(kGooglePlacesApikey); Future<TextSearchResponse?> _callGooglePlaceAPI(String keyword, { required double lat, required double lng }) async { return await _googlePlace.search.getTextSearch(keyword, location: Location(lat: lat, lng: lng), ); }
路徑規劃
路徑規劃 PolylineResult result =
await PolylinePoints().getRouteBetweenCoordinates( kGoogleDirectionsApiKey, PointLatLng(lat1, lng1), PointLatLng(lat2, lng2), travelMode: TravelMode.driving, ); import 'package: fl utter_polyline_points/ fl utter_polyline_points.dart';
路徑偏移(Route deviation) • 判斷⽬前的
GPS 位置是否偏移規劃的路徑 • 可以使⽤ google_map_polyutil • 呼叫 PolyUtils.isLocationOnEdgeTolerance,判斷座標是否在路徑上 • 還有其他⼯具
Recap • 放置地圖 Widget •
新增 Marker • 新增 Polyline • 計算 zoom level • 顯示 information window • 移動地圖、設定樣式 • 其他…
That’s all 謝謝⼤家
Anúncio