调整 UIView 的大小并在 drawRect 中动态调整绘图的大小

Posted

技术标签:

【中文标题】调整 UIView 的大小并在 drawRect 中动态调整绘图的大小【英文标题】:Resizing a UIView and dynamically resizing the drawing in drawRect 【发布时间】:2015-10-18 11:10:14 【问题描述】:

我有一个 UIView,我想通过 UISlider 调整其大小。我的 UISlider 范围设置为 1.0-2.0。目前我正在使用 CGAffineTransform 调整视图的大小。

截图:

我在自定义 UIView 中完成:

- (void)drawRect:(CGRect)rect 

    NSLog(@"Draw rect called");


    //// Square Drawing
    UIBezierPath* squarePath = [UIBezierPath bezierPathWithRect: CGRectMake(8, 8, 50, 50)];
    [UIColor.whiteColor setFill];
    [squarePath fill];


    //// Right top Drawing
    UIBezierPath* rightTopPath = [UIBezierPath bezierPathWithRect: CGRectMake(57, 13, 9, 10)];
    [UIColor.whiteColor setStroke];
    rightTopPath.lineWidth = 1;
    [rightTopPath stroke];


    //// Top left Drawing
    UIBezierPath* topLeftPath = [UIBezierPath bezierPathWithRect: CGRectMake(13, 0, 17.5, 9)];
    [UIColor.whiteColor setStroke];
    topLeftPath.lineWidth = 1;
    [topLeftPath stroke];


    //// Top right Drawing
    UIBezierPath* topRightPath = [UIBezierPath bezierPathWithRect: CGRectMake(35, 0, 17.5, 9)];
    [UIColor.whiteColor setStroke];
    topRightPath.lineWidth = 1;
    [topRightPath stroke];


    //// Right middle Drawing
    UIBezierPath* rightMiddlePath = [UIBezierPath bezierPathWithRect: CGRectMake(57, 28, 9, 10)];
    [UIColor.whiteColor setStroke];
    rightMiddlePath.lineWidth = 1;
    [rightMiddlePath stroke];


    //// Right bottom Drawing
    UIBezierPath* rightBottomPath = [UIBezierPath bezierPathWithRect: CGRectMake(57, 43, 9, 10)];
    [UIColor.whiteColor setStroke];
    rightBottomPath.lineWidth = 1;
    [rightBottomPath stroke];



滑块代码:

- (IBAction)changeValue:(id)sender 


    CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, self.slider.value, self.slider.value);
    self.square.transform = transform;


这可以正常工作,但是当我调整大小时,绘图会出现质量损失,因为我实际上并没有动态更改绘图的大小。我真正想做的是动态改变绘图的大小。我将如何实现这一目标?我是否需要先调整框架大小,然后调用[self.square setNeedsDisplay] 传递乘数?

编辑:

所以我厌倦了这种方法,现在当我移动滑块时:

- (IBAction)changeValue:(id)sender 


  CGRect newFrame = CGRectMake(20, 20, 72*self.slider2.value, 72*self.slider2.value);
self.square.frame = newFrame;
[self.square resizeAt:self.slider2.value];




所以我现在只是更改帧大小,然后将滑块值传递到视图并调用:

-(void)resizeAt: (float)multiply

    self.size=multiply;
    self.transform = CGAffineTransformScale(CGAffineTransformIdentity, self.size, self.size);
    [self setNeedsDisplay];


drawRect 中发生的事情的一个例子:

UIBezierPath* squarePath = [UIBezierPath bezierPathWithRect: CGRectMake(11, 11, 50, 50)];
    [squarePath applyTransform:self.transform];
    [UIColor.whiteColor setFill];
    [squarePath fill];

但是图像看起来不清晰或“重绘”

【问题讨论】:

【参考方案1】:

考虑使用 0.0 到 1.0 范围内的点创建贝塞尔路径,然后将变换直接应用于每个贝塞尔路径。转换的比例显然会改变,因为您将路径缩放到完整视图大小,而不是相对大小。

因为您缩放路径而不是已经渲染的视图,所以路径渲染仍然干净准确。

【讨论】:

如何缩放路径?在我使用 CGAffineTransform 之前。我可以将此对象应用于 UIBezierPaths 吗? 是的,您将对所有路径应用类似的变换,然后绘制它们。不会对视图应用任何变换。 为什么要将范围从 0.0 更改为 1.0? 因此您可以可靠地缩放到任何视图大小(很容易)——技术上不需要,但将来更易于维护 所以我正在使用来自 UISlider 的数字创建一个 CGAffineTransform,然后我调用 setNeedsDisplay,这会强制重绘并将转换应用于每个单独的 UIBezierPath。它正在调整大小,但看起来仍然模糊,就像它没有被重绘一样。 (编辑我的问题)。我做错了吗?

以上是关于调整 UIView 的大小并在 drawRect 中动态调整绘图的大小的主要内容,如果未能解决你的问题,请参考以下文章

iOS UIView drawRect 调整大小动画

调整 UIView 的大小,以便我绘制的任何内容都可见 - Objective C

如何在drawRect中获取UIView大小

使用 Interface Builder 动态调整 UILabel 的大小并在其下方重新定位 UIView

仅在 UIView 顶部的圆角

旋转 UIView 并在旋转后保持纵横比