1

在我的 iPad 应用程序Universal Combat Log(新布局分支)中,我有一个 UIView 子类(UCLLineChartView),它包含一个 UIScrollView,而滚动视图又包含另一个 UIView 子类(ChartView)。ChartView 有多个子层,每个子层用于添加到图表中的每一行数据。UCLLineChartView 绘制轴和标记。这些视图/层的内容完全是自定义绘制的,没有使用任何库存视图(例如 UIImageView)。

我在缩放时遇到问题——它像图像一样缩放 ChartView,这使得绘制的线条变得模糊和拉伸。我希望这条线保持清晰,最好是在用户进行缩放时,但经过 3 天的黑客攻击,我无法让它工作。

如果我覆盖 ChartView 上的 setTransform 以从变换中获取比例因子但不调用[super setTransform],则滚动视图的 zoomScale 保持为 1。我尝试保留给定的变换并覆盖变换方法以返回它。我尝试通过更改 ChartView 的中心和边界来复制 setTransform 的效果,但我无法完全正确地获得行为,而且它似乎仍然没有影响滚动视图的 zoomScale。似乎滚动视图的缩放比例取决于 setTransform 的效果,但我无法确定如何。

任何帮助将不胜感激。

4

2 回答 2

1

您需要做的是更新contentScaleFactorchartView 的。您可以通过在scrollViewDidEndZooming:withView:atScale:或 中添加以下代码来做到这一点scrollViewDidZoom:

CGFloat newScale = scrollView.zoomScale * [[UIScreen mainScreen] scale];
[self.chartView setContentScaleFactor:newScale];
于 2012-11-14T15:44:01.383 回答
0

我已经找到了一个解决我的问题的方法,这个方法并不太严重。在你的 UIScrollViewDelegate 中:

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
    [_contentView beginZoom];
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    CGSize size = scrollView.bounds.size;
    CGPoint contentOffset = _scrollView.contentOffset;

    CGFloat newScale = _contentView.scale;
    newScale = MAX(newScale, kMinZoomScale);
    newScale = MIN(newScale, kMaxZoomScale);

    [_scrollView setZoomScale:1.0 animated:NO];
    _scrollView.minimumZoomScale = kMinZoomScale / newScale;
    _scrollView.maximumZoomScale = kMaxZoomScale / newScale;

    _contentView.scale = newScale;

    CGSize newContentSize = CGSizeMake(size.width * newScale, size.height);

    _contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height);
    _scrollView.contentSize = newContentSize;

    [_scrollView setContentOffset:contentOffset animated:NO];

    [_contentView updateForNewSize];
    [_contentView setNeedsDisplay];
}

在您的内容视图中,声明一个 scale 属性和以下方法:

- (void)beginZoom
{
    _sizeAtZoomStart = CGSizeApplyAffineTransform(self.frame.size, CGAffineTransformMakeScale(1/self.scale, 1));
    _scaleAtZoomStart = self.scale;
}

- (void)setTransform:(CGAffineTransform)transform
{
    self.scale = _scaleAtZoomStart * transform.a;
    self.frame = CGRectMake(0, 0, _sizeAtZoomStart.width * self.scale, _sizeAtZoomStart.height);

    [self updateForNewSize];
    [self setNeedsDisplay];
}

如果您的内容视图使用子图层,您需要通过将以下内容添加到子图层的委托来禁用它们的隐式动画:

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
    // prevent animation of the individual layers so that zooming doesn't cause weird jitter
    return (id<CAAction>)[NSNull null];
}

这里的基本思想是重写的 setTransform 使用变换矩阵中的比例因子来计算内容视图的新比例因子,然后相应地调整内容视图的大小。滚动视图自动调整内容偏移以保持内容视图居中。

scrollViewDidEndZooming 代码保持缩放有界。

例如,在旋转设备时处理调整滚动视图的大小会更加复杂。

于 2012-11-16T05:39:22.230 回答