image.png
高德地圖插件大家想必已經(jīng)不陌生了(不熟的去看上一篇)掠归,按產(chǎn)品需求開發(fā)時需要在地圖上展示自定義的Mark峦失,觀察Mark方法:
(new) Marker Marker({ required LatLng position, double alpha = 1.0, Offset anchor = const Offset(0.5, 1.0), bool clickable = true, bool draggable = false, BitmapDescriptor icon = BitmapDescriptor.defaultMarker, bool infoWindowEnable = true, InfoWindow infoWindow = InfoWindow.noText, double rotation = 0.0, bool visible = true, double zIndex = 0.0, void Function(String)? onTap, void Function(String, LatLng)? onDragEnd, })
發(fā)現(xiàn)并沒有 Mark widget,沒有widget就意味著無法自定義widget迁筛,這可如何是好冈止,但聰明的我又怎會被這小小的難題困住酌媒,百度、谷歌??疑難解答不懂就問這是個好習慣耸弄,找到了解決思路咧虎,以BitmapDescriptor icon為突破口。
通過觀察BitmapDescriptor發(fā)現(xiàn)提供了展示png字節(jié)的方法:
static BitmapDescriptor fromBytes(Uint8List byteData) { return BitmapDescriptor._(<dynamic>['fromBytes', byteData]); }
至此是不是就明了了计呈,只需將自定義的widget轉(zhuǎn)為png在轉(zhuǎn)為ByteData即可砰诵。
wiget->ByteData:
Future<ByteData?> widgetToByteData(Widget widget, {Alignment alignment = Alignment.center, Size size = const Size(double.maxFinite, double.maxFinite), double devicePixelRatio = 1.0, double pixelRatio = 1.0}) async { RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary(); RenderView renderView = RenderView( child: RenderPositionedBox(alignment: alignment, child: repaintBoundary), configuration: ViewConfiguration( size: size, devicePixelRatio: devicePixelRatio, ), window: ui.window, ); PipelineOwner pipelineOwner = PipelineOwner(); pipelineOwner.rootNode = renderView; renderView.prepareInitialFrame(); BuildOwner buildOwner = BuildOwner(focusManager: FocusManager()); RenderObjectToWidgetElement rootElement = RenderObjectToWidgetAdapter( container: repaintBoundary, child: widget, ).attachToRenderTree(buildOwner); buildOwner.buildScope(rootElement); buildOwner.finalizeTree(); pipelineOwner.flushLayout(); pipelineOwner.flushCompositingBits(); pipelineOwner.flushPaint(); ui.Image image = await repaintBoundary.toImage(pixelRatio: pixelRatio); ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); return byteData; }
此方法直接copy拿走,多費一點腦子算我輸捌显,實現(xiàn)思路已OK
附上完整的代碼:
import 'dart:ui' as ui; . . AMapWidget? map; Map<String, Marker> initMarkerMap = <String, Marker>{}; AMapController? _mapController; late BitmapDescriptor icon; ///自定義地圖mark的 widget轉(zhuǎn)字節(jié) Future<ByteData?> widgetToByteData(Widget widget, {Alignment alignment = Alignment.center, Size size = const Size(double.maxFinite, double.maxFinite), double devicePixelRatio = 1.0, double pixelRatio = 1.0}) async { RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary(); RenderView renderView = RenderView( child: RenderPositionedBox(alignment: alignment, child: repaintBoundary), configuration: ViewConfiguration( size: size, devicePixelRatio: devicePixelRatio, ), window: ui.window, ); PipelineOwner pipelineOwner = PipelineOwner(); pipelineOwner.rootNode = renderView; renderView.prepareInitialFrame(); BuildOwner buildOwner = BuildOwner(focusManager: FocusManager()); RenderObjectToWidgetElement rootElement = RenderObjectToWidgetAdapter( container: repaintBoundary, child: widget, ).attachToRenderTree(buildOwner); buildOwner.buildScope(rootElement); buildOwner.finalizeTree(); pipelineOwner.flushLayout(); pipelineOwner.flushCompositingBits(); pipelineOwner.flushPaint(); ui.Image image = await repaintBoundary.toImage(pixelRatio: pixelRatio); ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); return byteData; } ///自定義widget widgetContext( ) { return Container( width: 540.w, height: 180.h, decoration: BoxDecoration( border: Border.all(width: 5.w, color: Color.fromRGBO(236, 253, 255, 1)), color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(70.r), topRight: Radius.circular(70.r), bottomRight: Radius.circular(70.r), bottomLeft: Radius.circular(12.r))), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ··· ], ), ); } ///添加自定義mark addMark() async { ByteData? byteData = await widgetToByteData(widgetContext()); icon = BitmapDescriptor.fromBytes(byteData!.buffer.asUint8List()); Marker marker = Marker( infoWindowEnable: false, position: LatLng(double.parse(item['lat'].toString()), double.parse(item['lng'].toString())), icon: icon, anchor: const Offset(0, 1.0), ); initMarkerMap[marker.id] = marker; } setState(() { map = AMapWidget( mapType: MapType.bus, labelsEnabled: false, onLocationChanged: (argument) { onLocationChangeds(argument); }, myLocationStyleOptions: MyLocationStyleOptions(false), privacyStatement: AmapConfig.amapPrivacyStatement, apiKey: AmapConfig.amapApiKeys, onMapCreated: onMapCreated, markers: Set<Marker>.of(initMarkerMap.values), ); }); } @override void initState() { // TODO: implement initState super.initState(); addMark(); }
如果到此處本文完結(jié)那和別的文章也就沒什么不同之處了茁彭,注意??有兩處坑
a.對于Text的定義要用
Directionality( textDirection: TextDirection.ltr, child:Text('') )
b.自定義的widget只能縱向布局因此可采用富文本來解決橫向布局需求 RichText()
====== 嫖走吧,有良心的就點點贊加個關(guān)注$$ =======