在 UIScrollView 中缩放和滚动大图像
Posted
技术标签:
【中文标题】在 UIScrollView 中缩放和滚动大图像【英文标题】:Zooming and Scrolling large images in UIScrollView 【发布时间】:2011-11-11 13:36:12 【问题描述】:我已经被困在这个问题上很长一段时间了。我查看了许多其他答案以及 Apple 的示例。
我想知道的是如何在 UIScrollView 中加载大图像,并能够像照片应用一样对它们进行分页和放大。
我正在开发一个需要滚动浏览大图像的应用程序(大,我的意思是大于 1024 x 1024 的图像)。我已经实现了与照片应用程序类似的功能。但是,现在我使用的是大图像,我会收到内存警告和其他东西。我知道我收到警告的原因,并且我知道我需要平铺图像。
Apple 的示例演示了使用已经存在的小图像进行平铺。我的应用程序将下载多个图像,将它们保存在磁盘上,用户稍后将能够查看它们。因此,我无法使用其他程序剪切图像。
我需要一些可以平铺全尺寸图像的东西。任何帮助将不胜感激。此外,正如我之前提到的,我知道我必须对 Tiling 做一些事情。但是,我是新手,如果答案包含一些示例代码,我将不胜感激,我可以将其用作起点。
我查看了其他问题,但似乎没有一个问题得到我满意的回答,因此,我再次问这个问题。
再次感谢!
【问题讨论】:
【参考方案1】:要使用平铺,您需要在视图中使用 CaTiledLayer。谷歌搜索它会给你很好的信息。基本上你声明 UIVIew 正在使用它,声明一些级别的缩放细节,在 drawRect 中你会收到每个图块作为 rect 参数。
要平铺图像,请加载 UIImage(它使用内存,但比显示它要少得多)并用于您想要的每个平铺:
UIGraphicsBeginImageContextWithOptions(tileSize, YES, 1);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -tileSize.width * columnNumber, -tileSize.height*rowNumber);
[img drawInRect:CGRectMake(0, 0, tileSize.width, tileSize.height)];
UIImage* imgCut = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
并保存 imgCut。如果您在 CATiledLayer 中使用不同级别的细节,您可能希望生成具有不同缩放比例的平铺。
【讨论】:
非常感谢您的回复。 :) 所以,如果我得到这个正确,我子类化 UIView 并将它传递给 UIImage (img
变量)。假设这个 UIView 和苹果 PhotoScroller 应用中的 TilingView 是一样的,那么,如果我把你的代码放到苹果 PhotoScroller 应用的- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col
方法中,我会得到我的图像的平铺版本吗?
我建议在显示图像之前生成图块并将它们保存在缓存目录中,这样您就可以在创建它们之后释放大图像并且您将准备好所有图块。我不知道那个例子,但看起来这个方法会返回行、列和比例的适当平铺图像,所以它应该可以工作
所以我需要在完成下载图像或将图像加载到屏幕上时异步创建图块(通过剪切图像)?
您可以即时执行此操作,但这意味着将大图像保存在内存中并每次都计算它们,这很慢。所以是的,我认为最好在下载图像后生成图块,异步与否(取决于您的应用要求)。
嗯。好吧,非常感谢您的回复。抱歉回复晚了,我周末不在。你说的对。我需要剪切图像,要么下采样并保存它们,要么对它们进行预剪切。对于我的申请目的,它们都没有任何意义。因此,我要求我的后端工程师为我提供缩略图 + 全尺寸图像。这样,在快速滚动时,我使用缩略图。用户停止滚动的那一刻,我切换到实际的全尺寸图像。因此,我的内存使用量下降了,性能也得到了很好的提升。 :)以上是关于在 UIScrollView 中缩放和滚动大图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在我的应用重新启动时动态恢复 UIScrollView 的缩放级别和位置?