我如何在转换后的UIView上重新绘制缩放后的文本



我目前正在实现一个扩展的时间轴。当我缩放到时间轴时,我需要我绘制的文本在处理缩放的UIScrollView中停留在相同的相对位置上。(本质上就像谷歌地图上的大头针)然而,我不想垂直缩放,所以我通过重写来应用转换:

- (void)setTransform:(CGAffineTransform)newValue;
{
    newValue.d = 1.0;
    [super setTransform:newValue];
}

这在保持时间轴垂直固定并允许其水平扩展方面非常有效。但是,我在setNeedsDisplay:

期间调用的方法中绘制文本标签。
for (int i = 1; i < 11; i++)
{
    CGRect newFrame = CGRectMake(i * (512.0/11.0) - (512.0/11.0/2.0), self.frame.size.height - 16.0, 512.0/11.0, 32.0);
    NSString *label = [NSString stringWithFormat:@"%d", i+1];
    [label drawInRect:newFrame withFont:[UIFont systemFontOfSize:14.0]];
}

这将我的文本绘制在滚动视图中的正确位置,并且几乎完美地工作。然而,由于我的转换使缩放视图保持垂直静态,文本水平扩展而不是垂直扩展,因此拉伸得很糟糕。我似乎无法以正确的纵横比重新绘制文本。使用uilabel工作,但是我要渲染和操纵超过1000个这样的标签,所以我更喜欢在drawRect或类似的东西中绘制静态图像。

我试过改变我正在绘制文本的CGRect(值得一试),并且应用CGAffineTransformIdentity是不可能的,因为我已经在转换视图以防止它垂直缩放。我也试过在各种视图中绘制文本,但无济于事,再一次,如果我能避免的话,我宁愿不填充大量的对象。

谢谢你的帮助!

不是在'setTransform:'方法中应用转换,而是截取它被转换的比例,并调整被转换视图的框架的大小。代码(大致)如下:

- (void)setTransform:(CGAffineTransform)newValue;
{   
    // The 'a' value of the transform is the transform's new scale of the view, which is reset after the zooming action completes
    //  newZoomScale should therefore be kept while zooming, and then zoomScale should be updated upon completion
    _newZoomScale = _zoomScale * newValue.a;
    if (_newZoomScale < 1.0)
        _newZoomScale = 1.0;
    // Resize self
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _originalFrame.size.width * _newZoomScale, self.frame.size.height);
}

正如在注释中提到的,CGAffineTransform的转换值在每次新的缩放操作发生时被重置(然而,它的在缩放操作期间被保留)。所以,我在我的UIView子类中保留了两个实例变量(不确定它是否令人难以置信的优雅,但它不是疯狂的可怕):视图被实例化的原始帧,以及视图的"当前"缩放比例(在当前缩放动作之前)。

_originalFrame是为了确定现在缩放帧的适当大小而引用的,_zoomScale(当前缩放操作之前的视图的比例)被设置为_newZoomScale的值,当didFinishZooming回调在包含此UIView的UIScrollView中被调用时。

所有这些都允许UIView的坐标系统在缩放过程中不被转换,所以文本等可以在视图上绘制而没有任何失真。回顾这个解决方案,我敢打赌,您还可以根据拉伸坐标系统来解释转换和绘图。不知道哪个更有效。在setTransform:中我有一点担心没有调用super,但是经过大约6个月的使用和开发,我没有注意到任何不良影响。

最新更新