当前位置: 首页 > news >正文

flutter自定义地图Marker完美展示图片

世人都说雪景美

寒风冻脚无人疼

只道是一身正气

结论

参考Flutter集成高德地图并添加自定义Maker先实现自定义Marker。如果自定义Marker中用到了图片,那么会碰到图片没有被绘制到Marker的问题,此时需要通过precacheImage来预加载图片,从而解决此问题。

一、 背景

在高德地图上需要展示每一辆单车的电量。而amap_flutter_map确没有提供自定义Marker的方法,只有一个static BitmapDescriptor *fromBytes*(Uint8List byteData). 所以需要将定制的Widget转为图片,然后图片转为字节流,来实现自定义Marker

二、 自定义Marker

1. 定义widget

创建业务需求的widget,如下:

static Future<Widget> _createMarkerView(BuildContext context, String name,String imageName,{bool selected = false, MarkerTitleType markerTitleType = MarkerTitleType.small}) async {var height = markerTitleType.height;if (selected) {height *= 2;}var width = markerTitleType.width;return Container(height: height,constraints: BoxConstraints(minWidth: width),alignment: Alignment.center,decoration: BoxDecoration(image: DecorationImage(image: AssetImage(imageName)),),child: Directionality(textDirection: TextDirection.ltr,child: Text(name,style: TextStyle(fontSize: selected ? 22 : 14, color: Colors.white),maxLines: 1,overflow: TextOverflow.ellipsis,textAlign: TextAlign.center,),),);}

很简单的一个背景图片和一个标题。其中这个图片,因为是从Images资源中加载,会偶现加载失败的问题。

展示失败

2. widgetByteData

不展示widget到窗口,直接将widget保存为图片。代码如下:

  static Future<ByteData?> widgetToByteData(Widget widget, String imageName,{Alignment alignment = Alignment.center,Size size = const Size(double.maxFinite, double.maxFinite),double devicePixelRatio = 1.0,double pixelRatio = 1.0,required BuildContext context}) async {RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();RenderView renderView = RenderView(child: RenderPositionedBox(alignment: alignment, child: repaintBoundary),configuration: ViewConfiguration(size: size,devicePixelRatio: devicePixelRatio,),view: View.of(context),);PipelineOwner pipelineOwner = PipelineOwner();pipelineOwner.rootNode = renderView;renderView.prepareInitialFrame();BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());RenderObjectToWidgetElement rootElement = RenderObjectToWidgetAdapter(container: repaintBoundary,child: widget,).attachToRenderTree(buildOwner);await precacheImage(AssetImage(imageName), rootElement);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;}

其中的 await precacheImage(AssetImage(imageName), rootElement); 是解决图片偶现加载失败的关键。

3. 返回BitmapDescriptor

创建Marker的时候需要一个BitmapDescriptor,代码如下:

var data = await MapConverting.widgetToByteData(view, imageName,context: context,devicePixelRatio: AMapUtil.devicePixelRatio,pixelRatio: AMapUtil.devicePixelRatio,size: Size(selected ? width * 1.5 : width, selected ? height * 1.2 : height));var uInt8List = data?.buffer.asUint8List();if (null != uInt8List) {bitmapDescriptor = BitmapDescriptor.fromBytes(uInt8List);_createdBitmapDescriptor[key] = bitmapDescriptor;} else {bitmapDescriptor = await BitmapDescriptor.fromAssetImage(imageConfiguration, MyImages.imagesIcParkingNormal);}return bitmapDescriptor;

为了方便BitmapDescriptor的管理,可以创建一个BitmapDescriptorFactory类,添加一个static final Map<String, BitmapDescriptor> *_createdBitmapDescriptor* = {};将创建过的自定义BitmapDescriptorFactory做一个全局缓存,来解决重复创建的问题。

三、precacheImage使用注意

precacheImage函数中有一个参数是context,理解为缓存图片仅仅是在此context中生效。

尝试过在首页,业务主页,地图页面对需要使用到的图片进行缓存,都失效了,只有在RenderObjectToWidgetElement创建自定义widget时,将precacheImage缓存,才能生效。

参考: Flutter集成高德地图并添加自定义Maker

相关文章:

  • springboot(ssm电商应用系统 在线购物系统Java系统
  • Java 栈和队列的交互实现
  • Vue3使用 xx UI解决布局高度自适应
  • 机器视觉系统选型-高图像精度
  • 旅游景区项目信息化建设运营方案:PPT47页,附下载
  • ChatGPT如何计算token数?
  • 在Windows系统平台下部署运行服务端Idea工程的jar服务
  • 摄像头画面作为电脑桌面背景
  • 14:00面试,14:08就出来了,问的问题有点变态。。。
  • 【小白专用】php pdo sqlsrv 类,php连接sqlserver
  • 如何用 CleanMyMac 来保护 Mac 隐私
  • pyCharm 创建一个FastApi web项目,实现接口调用
  • English phrase
  • SQL server 数据库 sql常用语句
  • Achronix提供由FPGA赋能的智能网卡(SmartNIC)解决方案来打破智能网络性能极限
  • “大数据应用场景”之隔壁老王(连载四)
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 4个实用的微服务测试策略
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • express + mock 让前后台并行开发
  • PV统计优化设计
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 分布式事物理论与实践
  • 机器学习学习笔记一
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 使用docker-compose进行多节点部署
  • 使用权重正则化较少模型过拟合
  • 为视图添加丝滑的水波纹
  • 转载:[译] 内容加速黑科技趣谈
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • (02)Hive SQL编译成MapReduce任务的过程
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (ZT)薛涌:谈贫说富
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (力扣)1314.矩阵区域和
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (推荐)叮当——中文语音对话机器人
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .gitignore文件设置了忽略但不生效
  • .NET Core跨平台微服务学习资源
  • .net 流——流的类型体系简单介绍
  • .net 托管代码与非托管代码
  • .net6 webapi log4net完整配置使用流程
  • .NetCore项目nginx发布
  • @KafkaListener注解详解(一)| 常用参数详解
  • [20180129]bash显示path环境变量.txt
  • [AutoSAR系列] 1.3 AutoSar 架构
  • [BZOJ] 2044: 三维导弹拦截
  • [C++]STL之map