【问题标题】:Draw UIBezierPath on UIImageView for image crop在 UIImageView 上绘制 UIBezierPath 以进行图像裁剪
【发布时间】:2015-12-09 05:45:15
【问题描述】:

我正在开发一个照片编辑应用程序,并且需要用户能够绘制一条路径来裁剪照片。我有一个与 UIView 一起使用的类,用于绘制平滑的 UIBezierPath 线。但是我真的需要将它应用于 UIImageView 以便可以在图像上完成绘图。如果我将类更改为 UIImageView 的子类,则它不再起作用。关于我能做些什么来解决这个问题的任何想法?还是实现相同目标的更好选择?下面是我的实现:

    #import "DrawView.h"

@implementation DrawView
{
    UIBezierPath *path;
}

- (id)initWithCoder:(NSCoder *)aDecoder // (1)
{
    if (self = [super initWithCoder:aDecoder])
    {
        [self setMultipleTouchEnabled:NO]; // (2)
        [self setBackgroundColor:[UIColor whiteColor]];
        path = [UIBezierPath bezierPath];
        [path setLineWidth:2.0];
    }
    return self;
}

- (void)drawRect:(CGRect)rect // (5)
{
    [[UIColor blackColor] setStroke];
    [path stroke];
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path moveToPoint:p];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p]; // (4)
    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

@end

如果我在 touchesBegan 或 touchesMoved 上放置一个断点,它会按预期触发。

【问题讨论】:

    标签: ios objective-c uiimageview uibezierpath


    【解决方案1】:

    第一个问题 - userInteractionEnabled 属性应设置为 YES 以接收触摸事件。

    第二个 - drawRect: 方法不为 UIImageView 子类调用:

    UIImageView 类经过优化,可以将其图像绘制到显示器上。 UIImageView 不会调用 drawRect: 一个子类。如果您的子类需要 自定义绘制代码,建议使用 UIView 作为基础 类。

    所以,DrawView 应该是 UIView 子类,它将在绘制贝塞尔路径之前在 drawRect: 中绘制 UIImage。类似的东西(只更改了部分代码):

    // DrawView.h
    @interface DrawView : UIView
    @property (nonatomic, strong) UIImage* image;
    @end
    
    // DrawView.m    
    @implementation DrawView
    
    - (void)drawRect:(CGRect)rect
    {
        [image drawInRect:self.bounds];
        [[UIColor blackColor] setStroke];
        [path stroke];
    }
    
    @end
    

    【讨论】:

    • 好的,我已经尝试过使用和不使用 userInteractionEnabled,就像我说的那样,即使没有它,我仍然会触发 touchesBegan。但是,您的其他解决方案可能是我需要的。你能更深入地解释你的解决方案吗?感谢您的回复!
    • 这确实有效,但是由于调用 [self setNeedsDisplay]; 它运行非常缓慢;在背景中重绘图像。有没有刷新绘图而不刷新图像?
    • 作为替代解决方案,您可以尝试将 DrawView 放在 Interface Builder 中的 UIImageView 上。在这种情况下,您不应该在 DrawView 中绘制图像。然后,UIImageView 将绘制图像,而 DrawView 将仅绘制贝塞尔路径。此外,您可以使用 -[self setNeedsDisplayInRect:path.bounds] 来最小化要重绘的区域。
    • @BorisVerebsky 这不会导致 DrawView 覆盖 UIImageView 吗?您如何从 DrawView 中看到图像以及顶部的线条?
    • @bakalolo 您需要确保 DrawView 不是不透明的。然后你就可以看到图片和路径了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多