我有一个正在绘制的图表 UIScrollView. 。是一大块 UIView 使用自定义子类 CATiledLayer 作为它的层。

当我放大和缩小时 UIScrollView, ,我希望图表能够动态调整大小,就像我从 viewForZoomingInScrollView. 。但是,图形会在新的缩放级别重新绘制自身,并且我想将变换比例重置为 1x1,以便下次用户缩放时,变换从当前视图开始。如果我将转换重置为 Identity scrollViewDidEndZooming, ,它在模拟器中工作,但抛出一个 EXC_BAD_ACCSES 在设备上。

这甚至不能完全解决模拟器上的问题,因为下次用户缩放时,变换会将自身重置为它所处的任何缩放级别,因此看起来,例如,如果我缩放到 2 倍,突然就变成4倍了当我完成缩放时,它最终达到正确的比例,但缩放的实际行为看起来很糟糕。

首先:如何让图形在缩放后以 1x1 的标准比例重新绘制,以及如何在整个过程中实现平滑缩放?

编辑: 新发现该错误似乎是“[CALayer retainCount]: message sent to deallocated instance"

我自己从来不会释放任何层。之前,我什至没有删除任何视图或任何内容。缩放和旋转时都会引发此错误。如果我在旋转之前删除对象并在之后重新添加它,它不会抛出异常。这不是缩放选项。

有帮助吗?

解决方案

我不能帮你的崩溃,不是告诉你检查并确保您不会无意中自动释放视图或代码中的某处层等。我已经看到了模拟器处理自动释放的定时不同于在设备上(通常当线程都参与)。

在视图缩放是UIScrollView我碰到的一个问题,虽然。在捏缩放事件,UIScrollView将带您在viewForZoomingInScrollView:委托方法指定的视图和应用转换到它。此变换提供的视图的平滑缩放,而不必重新绘制每个帧。在变焦操作结束后,您的委托方法scrollViewDidEndZooming:withView:atScale:将被调用,并给你一个机会在新的比例因子做你的看法更优质的渲染。一般情况下,它的建议,你重置您的视图变换被CGAffineTransformIdentity,然后让你的观点在新的大小规模手动重绘自己。

然而,这导致因为UIScrollView不会出现来监视内容视图变换的问题,所以在下一变焦操作它设置到任何整体规模因素是内容视图的变换。既然你手动重绘你的观点在最后的比例因子,它化合物缩放,这是你所看到的。

作为一种变通方法中,我使用UIView子类为我的内容考虑到与下面的方法确定:

- (void)setTransformWithoutScaling:(CGAffineTransform)newTransform;
{
    [super setTransform:newTransform];
}

- (void)setTransform:(CGAffineTransform)newValue;
{
    [super setTransform:CGAffineTransformScale(newValue, 1.0f / previousScale, 1.0f / previousScale)];
}

其中previousScale是视图的浮实例变量。然后我实现缩放委托方法如下:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale;
{
    [contentView setTransformWithoutScaling:CGAffineTransformIdentity];
// Code to manually redraw view at new scale here
    contentView.previousScale = scale;
    scrollView.contentSize = contentView.frame.size;
}

通过这样做,发送到内容视图的变换是基于在该视图最后重绘的比例调整。当捏缩放完成后,通过绕过正常setTransform:方法调整变换重置为1.0的比例。这似乎提供正确的缩放行为,同时让你的变焦完成绘制清晰的视图。

UPDATE(23/7/2010):iPhone OS 3.2和以上已经改变的滚动视图的行为在问候变焦。现在,UIScrollView将遵循一致性改变你应用到内容视图,并仅提供-scrollViewDidEndZooming:withView:atScale:的相对比例因子。因此,对于一个子类UIView上述代码仅需要运行比3.2更旧iPhone OS版本的装置。

其他提示

感谢之前所有的答案,这是我的解决方案。
实施 UIScrollViewDelegate 方法:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return tmv;
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    CGPoint contentOffset = [tmvScrollView contentOffset];   
    CGSize  contentSize   = [tmvScrollView contentSize];
     CGSize  containerSize = [tmv frame].size;

    tmvScrollView.maximumZoomScale = tmvScrollView.maximumZoomScale / scale;
    tmvScrollView.minimumZoomScale = tmvScrollView.minimumZoomScale / scale;

    previousScale *= scale;

    [tmvScrollView setZoomScale:1.0f];

    [tmvScrollView setContentOffset:contentOffset];
    [tmvScrollView setContentSize:contentSize];
    [tmv setFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];  

    [tmv reloadData];
}
  • 电视 是我的 UIView 的子类
  • tmvScrollView — UIScrollView 的出口
  • 最大缩放比例最小缩放比例
  • 创造 以前的规模 实例变量并将其值设置为 1.0f

非常适合我。

BR,尤金。

我只是希望负载重置为默认缩放比例,因为当我放大它,滚动型是有下一次相同的缩放比例,直到它被释放。

-(void) viewWillAppear:(BOOL)animated {
      [self.scrollView setZoomScale:1.0f];
}

改变了游戏。

我的详细讨论如何的UIScrollView(为什么)在 github.com/andreyvit/ScrollingMadness/缩放作品

(将链接还包含了如何编程方式放大UIScrollView的描述,如何效仿图片库式传呼+变焦+滚动,实例项目和ZoomScrollView类,封装了一些神奇的放大。)

引用:

的UIScrollView没有一个“当前缩放级别”的概念,因为每个子视图包含可能有它自己当前的缩放级别。请注意,在没有的UIScrollView领域保持当前的缩放级别。但是我们知道,有人存储缩放级别,因为如果你捏缩放子视图,然后重置其转化为CGAffineTransformIdentity,然后再捏,你会发现子视图以前的缩放级别已经恢复。

事实上,如果你看一下拆卸,它是存储自己的缩放级别(内UIGestureInfo指向的对象由_gestureInfo场)的UIView。它也有一套很好的无证方法,如zoomScalesetZoomScale:animated:。 (请注意,它也有一堆旋转相关的方法,也许我们正在旋转的姿态支持不久的某一天。)

不过,如果我们只是为了变焦创建一个新的UIView和添加我们真正的可缩放视图作为其子,我们将始终与缩放级别1.0开始。我的纲领性缩放的实现是基于这种伎俩。

一种相当可靠的方法,适用于 iOS 3.2 和 4.0 及更高版本,如下所示。您必须准备好以任何请求的比例提供可缩放视图(滚动视图的主要子视图)。然后在 scrollViewDidEndZooming: 您将删除此视图的模糊比例转换版本,并将其替换为按新比例绘制的新视图。

你会需要:

  • 用于维持先前规模的 ivar;我们称之为 oldScale

  • 一种识别可扩展视图的方法,既适用于 viewForZoomingInScrollView: 并为 scrollViewDidEndZooming:;在这里,我要应用一个标签(999)

  • 创建可缩放视图、对其进行标记并将其插入滚动视图的方法(这里我将其称为 addNewScalableViewAtScale:)。请记住,它必须根据比例执行所有操作 - 它调整视图及其子视图或绘图的大小,并调整滚动视图的 contentSize 的大小以匹配。

  • minimumZoomScale 和maximumZoomScale 的常量。这些是必需的,因为当我们用详细的较大版本替换缩放视图时,系统会认为当前比例为 1,因此我们必须欺骗它以允许用户将视图缩小。

那好吧。创建滚动视图时,您可以按比例 1.0 插入可缩放视图。这可能在你的 viewDidLoad, , 例如 (sv 是滚动视图):

[self addNewScalableViewAtScale: 1.0];
sv.minimumZoomScale = MIN;
sv.maximumZoomScale = MAX;
self->oldScale = 1.0;
sv.delegate = self;

然后在你的 scrollViewDidEndZooming: 你做同样的事情,但补偿规模的变化:

UIView* v = [sv viewWithTag:999];
[v removeFromSuperview];
CGFloat newscale = scale * self->oldScale;
self->oldScale = newscale;
[self addNewScalableViewAtScale:newscale];
sv.minimumZoomScale = MIN / newscale;
sv.maximumZoomScale = MAX / newscale;

请注意,由Brad提供的解决方案,虽然有一个问题:如果你一直编程放大(让我们在双击事件时说的),并让用户手动(扩分)缩小,一段时间后,真实比例之间的差异而规模的UIScrollView是跟踪将增长过大,所以previousScale会在某个时刻掉出的浮法的精度,这将最终导致不可预知的行为

<强>夫特4 * 和<强>的Xcode 9.3

到它的初始状态滚动视图缩放比例设置为0,将重置您的滚动视图。

self.scrollView.setZoomScale(0.0, animated: true)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top