UIScrollView 缩放后如何重置? [英] How do I reset after a UIScrollView zoom?

查看:44
本文介绍了UIScrollView 缩放后如何重置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 UIScrollView 中绘制了一个图表.它是一个大型 UIView,使用 CATiledLayer 的自定义子类作为其层.

I have a Graph being drawn inside a UIScrollView. It's one large UIView using a custom subclass of CATiledLayer as its layer.

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

When I zoom in and out of the UIScrollView, I want the graph to resize dynamically like it does when I return the graph from viewForZoomingInScrollView. However, the Graph redraws itself at the new zoom level, and I want to reset the transform scale to 1x1 so that the next time the user zooms, the transform starts from the current view. If I reset the transform to Identity in scrollViewDidEndZooming, it works in the simulator, but throws an EXC_BAD_ACCSES on the device.

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

This doesn't even solve the issue entirely on the simulator either, because the next time the user zooms, the transform resets itself to whatever zoom level it was at, and so it looks like, if I was zoomed to 2x, for example, it's suddenly at 4x. When I finish the zoom, it ends up at the correct scale, but the actual act of zooming looks bad.

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

So first: how do I allow the graph to redraw itself at the standard scale of 1x1 after zooming, and how do I have a smooth zoom throughout?

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

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

I'm never deallocating any layers myself. Before, I wasn't even deleting any views or anything. This error was being thrown on zoom and also on rotate. If I delete the object before rotation and re-add it afterward, it doesn't throw the exception. This is not an option for zooming.

推荐答案

我无法帮助您解决崩溃问题,只能告诉您检查并确保您不会在代码中的某处无意中自动释放视图或图层.我已经看到模拟器处理自动释放的时间与在设备上不同(通常是在涉及线程时).

I can't help you with the crashing, other than tell you to check and make sure you aren't unintentionally autoreleasing a view or layer somewhere within your code. I've seen the simulator handle the timing of autoreleases differently than on the device (most often when threads are involved).

视图缩放是我遇到的 UIScrollView 的一个问题.在捏缩放事件期间,UIScrollView 将获取您在 viewForZoomingInScrollView: 委托方法中指定的视图,并对其应用转换.这种变换提供了视图的平滑缩放,而不必每帧重新绘制它.在缩放操作结束时,您的委托方法 scrollViewDidEndZooming:withView:atScale: 将被调用,并让您有机会以新的比例因子对视图进行更高质量的渲染.通常,建议您将视图上的转换重置为 CGAffineTransformIdentity,然后让您的视图以新的大小比例手动重绘.

The view scaling is an issue with UIScrollView I've run into, though. During a pinch-zooming event, UIScrollView will take the view you specified in the viewForZoomingInScrollView: delegate method and apply a transform to it. This transform provides a smooth scaling of the view without having to redraw it each frame. At the end of the zoom operation, your delegate method scrollViewDidEndZooming:withView:atScale: will be called and give you a chance to do a more high-quality rendering of your view at the new scale factor. Generally, it's suggested that you reset the transform on your view to be CGAffineTransformIdentity and then have your view manually redraw itself at the new size scale.

然而,这会导致一个问题,因为 UIScrollView 似乎没有监控内容视图的变换,所以在下一次缩放操作中,它将内容视图的变换设置为任何整体比例因子.由于您已在最后一个比例因子上手动重绘视图,因此会增加缩放比例,这就是您所看到的.

However, this causes a problem because UIScrollView doesn't appear to monitor the content view transform, so on the next zoom operation it sets the transform of the content view to whatever the overall scale factor is. Since you've manually redrawn your view at the last scale factor, it compounds the scaling, which is what you're seeing.

作为一种解决方法,我将 UIView 子类用于我的内容视图,并定义了以下方法:

As a workaround, I use a UIView subclass for my content view with the following methods defined:

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

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

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

where previousScale is a float instance variable of the view. I then implement the zooming delegate method as follows:

- (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 的比例.这似乎提供了正确的缩放行为,同时让您在缩放完成时绘制清晰的视图.

By doing this, the transforms sent to the content view are adjusted based on the scale at which the view was last redrawn. When the pinch-zooming is done, the transform is reset to a scale of 1.0 by bypassing the adjustment in the normal setTransform: method. This seems to provide the correct scaling behavior while letting you draw a crisp view at the completion of a zoom.

更新(2010 年 7 月 23 日):iPhone OS 3.2 及更高版本更改了滚动视图在缩放方面的行为.现在,UIScrollView 将尊重您应用于内容视图的身份转换,并且仅在 -scrollViewDidEndZooming:withView:atScale: 中提供相对比例因子.因此,上述 UIView 子类的代码仅适用于运行早于 3.2 的 iPhone OS 版本的设备.

UPDATE (7/23/2010): iPhone OS 3.2 and above have changed the behavior of scroll views in regards to zooming. Now, a UIScrollView will respect the identity transform you apply to a content view and only provide the relative scale factor in -scrollViewDidEndZooming:withView:atScale:. Therefore, the above code for a UIView subclass is only necessary for devices running iPhone OS versions older than 3.2.

这篇关于UIScrollView 缩放后如何重置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆