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

news2024/11/24 3:58:24

世人都说雪景美

寒风冻脚无人疼

只道是一身正气

结论

参考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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1327186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DC-磁盘配额

2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 在DC2驱动器C:\上设置磁盘配额&#xff0c;限制磁盘空间为5G&#xff0c;警告等级为3G&#xff0c;超出配额限制时记录事件&#xff0c;超出警告等级时记录事件。 配置步骤 验证 查看DC2驱动器C:\的磁盘配额&#xf…

WPF组合控件TreeView+DataGrid之TreeView封装-粉丝专栏

wpf的功能非常强大&#xff0c;很多控件都是原生的&#xff0c;但是要使用TreeViewDataGrid的组合&#xff0c;就需要我们自己去封装实现。 我们需要的效果如图所示&#xff1a; 这2个图都是第三方控件自带的&#xff0c;并且都是收费使用。 现在我们就用原生的控件进行封装一…

APP应用加固指南:如何有效辨别,网络上伪造的地理位置?

目录 地理位置数据的来源 伪造地理位置数据的危害 如何有效辨别模拟器作弊行为&#xff1f; App加固有效防控地理伪造 在数字互联时代&#xff0c;已经离不开地理位置数据。地理位置数据不仅仅是一个简单的坐标&#xff0c;更是一种数字足迹&#xff0c;描绘了人们在数字世界中…

隧道LED照明技术见证大国交通发展,三思陶瓷散热技术强势突围

隧道灯&#xff0c;顾名思义&#xff0c;就是用于公路隧道中照明的灯。随着我们社会经济的不断进步&#xff0c;公路交通网越来越发达&#xff0c;隧道越来越多&#xff0c;隧道中的照明也越来越受到重视。 很多人会想当然地认为&#xff0c;隧道照明和公路、街道照明应该差不…

QpushButton菜单设置 和 右键菜单

一、前言 ​ 在PyQt中&#xff0c;可以通过QMenu和QAction类来创建和管理菜单。QMenu用于定义具体的菜单&#xff0c;而QAction则代表菜单中的具体操作项。 二、点击QPushButton&#xff0c;显示菜单 API QPushButton操作菜单的相关Api QMenu自身相关Api 代码演示 代码&…

你以为出现NoClassDefFoundError错误会是什么原因?

你以为出现NoClassDefFoundError错误会是什么原因&#xff1f; 1、概述2、事情经过3、总结 1、概述 大家好&#xff0c;我是欧阳方超&#xff0c;可以关注我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 同样的错误&#xff0c;非一样的解决方式。NoClassDefFou…

CComboBoxEx

很久以前写的一段代码感觉比较有意思记录下 一、前面是bmp的图像后面是文字 BOOL bRe Img.Create(IDB_BITMAP_Chamfer, 50, 8, RGB(255, 0, 0));mComBoxChamfer.SetImageList(&Img);COMBOBOXEXITEM cbexItem;cbexItem.mask CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_O…

【算法】【动规】最长定差子序列,大数组优化!!

跳转汇总链接 &#x1f449;&#x1f517;动态规划算法汇总链接 优化在后面&#xff01; 2.5 最长定差子序列 &#x1f517;题目链接 给你一个整数数组 arr 和一个整数 difference&#xff0c;请你找出并返回 arr 中最长等差子序列的长度&#xff0c;该子序列中相邻元素之间…

【CF闯关练习】—— 800分段

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;cf闯关练习 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

WPF组合控件TreeView+DataGrid之TreeView封装

&#xff08;关注博主后&#xff0c;在“粉丝专栏”&#xff0c;可免费阅读此文&#xff09; wpf的功能非常强大&#xff0c;很多控件都是原生的&#xff0c;但是要使用TreeViewDataGrid的组合&#xff0c;就需要我们自己去封装实现。 我们需要的效果如图所示&#x…

云上查看容器日志

有时候在云上希望查看容器日志&#xff0c;但web UI界面上看不到日志&#xff0c;怎么办&#xff1f;可以登入容器查看。 该做法适用于各种云上平台&#xff0c;包括华为云、腾讯云等。 首先用ssh登陆宿主机 [rootxxx ~]# 然后用docker列举所有容器&#xff0c;找到你想查看的…

科普-电子合同签署,这三步不能忽视

关于电子合同&#xff0c;许多人认为我自己直接内部发送邮件/传真等发送电子版合同或者我自己创建一个电子合同平台&#xff0c;这种怎么不属于电子合同呢&#xff1f; 在这里给大家科普一个知识点&#xff1a;签电子合同&#xff0c;需要经过这“三个步骤”。 根据《电子签名…

PYthon Pandas 时间序列数据重采样-resample()方法(第23讲)

PYthon Pandas 时间序列数据重采样-resample()方法(第23讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

12、Qt:用QProcess类启动外部程序:简单使用

一、说明 简单使用&#xff1a;在一个函数中&#xff0c;使用QProcess类的临时对象调用可执行文件exe&#xff0c;只有这个exe执行完了&#xff0c;这个函数才往下执行&#xff0c;一次性打印出exe所有输出信息&#xff1b;复杂使用&#xff1a;创建QProcess类的全局对象&…

代码随想录算法训练营Day6 | 454.四数相加||、383.赎金信、35.三个之和、18.四数之和

LeetCode 454 四数相加 || 本题思路&#xff1a; 如果使用暴力的话就是 4 层 for 循环&#xff0c;这个时间复杂度就是 O(n^4) 了。 所以我们可以使用 map &#xff0c;来解决这道题&#xff0c;和之前的两数之和一样&#xff0c;之前是 遍历一个&#xff0c;存进去一个。 如果…

IIC使用方法

IIC模块简介 iic是stm32芯片上的一个外设 有两个外设接口 其中iic1可以重映射 iic2不可以重映射 寄存器组和内部结构 因为iic外设挂载在APB1总线上 所以时钟也是来自于APB1总线 时钟控制寄存器就是控制开关的 发送数据和接收数据都是经过了双缓冲区&#xff08;串行转行 接收 …

蓝桥杯专题-真题版含答案-【扑克牌排列】【取球博弈】【古堡算式】【泊松分酒】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

南京航空航天大学-高等计算机网络复习

计算机网络复习 计算机网络 通信网络 网络提供信息传递服务&#xff08;端用户角度&#xff09; 通信介质&#xff1a;电子和光子&#xff0c;传输介质&#xff1a;fiber……&#xff0c;交换方式&#xff0c;协议&#xff0c;算法&#xff0c;功能&#xff0c;应用 通信网…

【DOM笔记四】事件高级!(注册/删除事件、DOM事件流、事件对象、事件委托、鼠标 / 键盘事件、相关案例)

文章目录 7 事件高级7.1 注册事件概述7.2 删除事件7.3 DOM事件流7.4 事件对象7.5 事件委托7.6 鼠标事件7.6.1 常用的鼠标事件7.6.2 鼠标事件对象 7.7 键盘事件7.7.1 常用的键盘事件7.7.2 键盘事件对象 7 事件高级 7.1 注册事件概述 给元素添加事件&#xff0c;称为注册事件或…

码住不亏!10家程序员接单平台横向对比

很多程序员都在空闲时间想要尝试接单&#xff0c;其实程序员接单在程序员圈子里非常常见&#xff0c;但想要找到一个合适的程序员接单平台却很难&#xff0c;今天给兄弟们整理了18个程序员接单平台的横向对比&#xff0c;希望可以给还在观望的小伙伴一点参考。 程序员客栈 规…