3

我的应用程序正在加载一个大图像(房屋平面图),然后在图像上绘制触摸反应对象(家具、灯具等)。我的应用程序包含一个基本图像文件,但对象来自我数据库中的坐标。

我已经在多次迭代中成功部署了该应用程序,但现在我需要使用更大的基本映像,并且在许多设备上BitmapFactory导致OutOfMemory异常(旧设备和新设备;任何小于 32MB 堆的东西似乎都崩溃了)。我已经阅读了关于 SO 的 157 OOM 问题,但恐怕他们似乎都指向的链接对我没有帮助,因为分辨率/缩放对应用程序的功能至关重要。

我尝试在加载之前测试设备的可用内存,但结果充其量是参差不齐(一些设备,如 Galaxy S3 报告大量堆但仍然崩溃)。我也尝试过降低分辨率,但根据上述测试将图像缩小到安全尺寸时,图像变得无法使用。

有没有另一种方法可以在不使用位图的情况下实现这种设计?我需要:

  • 加载大型基础图像
  • 在基础图像上创建可点击的形状,保持它们相对于基础图像的位置/比例
  • 奖励:在我的应用程序的 iOS 版本中,我可以进行 SVG 样式的文本缩放,因此小对象上的长标签将保留在对象内部,而不是在地图上运行(并且在图像缩放之前将不可见)。在 android 中复制它会让我成为一个快乐的代码猴子。

如果需要,我可以发布代码,但你们之前都看过(几乎所有代码都来自 SO)。

提前感谢您的阅读,以及您可以提供的任何帮助。

4

4 回答 4

3

你有几个选择:

  1. 正如评论所建议的那样,将您的大图像分解为图块,将这些图块加载到数组中,然后移动相机对象并仅加载需要绘制的图块。

  2. 使您的图像变小并使用“android:scaletype”将其放大

  3. Canvas在运行时在对象上绘制直线和曲线。

  4. 使用 OpenGL

适当的解决方案实际上取决于您希望它的外观。平铺需要更多的开发工作,但看起来会更好,请注意正确清理任何未绘制的瓷砖......

动态缩放会更容易,但你不能保证图像不会模糊。

在运行时在对象上绘图Canvas可以很好地工作 - 只需使用不同宽度的线条和圆形和矩形等。

使用 OpenGL 将有最陡峭的学习曲线,并且可能是矫枉过正。这取决于你的目的。

于 2012-12-06T16:57:02.107 回答
0

以下是一些选项:

1)使用瓷砖。使用磁贴并动态加载您的数据。老实说,这是最好的解决方案。使用此解决方案,您可以加载任意大的图像。

我已经成功地将这种方法用于无尽的画布,并且效果很好。您实际上只需要绘制用户直接可见的内容。瓷砖是一种丢弃不需要的碎片的方法。瓦片金字塔(您可以在其中对图像进行预下采样并创建更多瓦片),使您能够以干净快速的方式完成此操作。

2)使用本机代码。本机代码的内存限制与 Java 代码不同。您可以避免分配更多内存。

3) 使用 OpenGL。再说一次,OpenGL 的内存限制与 Java 代码不同。

4)将您的原始计划转换为 SVG 并使用像这样的 SVG 库。

5)使用“大堆”。我强烈反对这样做,因为我认为 largeHeap 很少是解决方案,通常有更清洁的方法来解决问题。

于 2012-12-14T03:27:24.097 回答
0

如果图像是静态的,您可能希望使用这个不错的库:

https://github.com/ManuelPeinado/ImageLayout

如果库不支持图像的自动下采样,你应该自己做,以便为当前设备使用最好的图像(这样你就不会得到 OOM)。

对于 auto-sizing text ,您可能会对下一篇文章有​​所了解:

适用于 Android 的自动调整 TextView

于 2013-07-24T07:42:14.207 回答
0

您可能想研究使用“大堆” http://developer.android.com/reference/android/R.styleable.html#AndroidManifestApplication_largeHeap

于 2012-12-14T03:11:57.807 回答