iOS 自定义签名控件

1. UKAutographView

UKAutographView控件用来实现自定义签名功能,UKAutographView实现UIView

@interface UKAutographView()

// path记录当前绘制路径
@property(nonatomic, strong) UIBezierPath *path;
// paths记录所有绘制路径
@property(nonatomic, strong) NSMutableArray<UIBezierPath *> *paths;
// points记录所有绘制路径上的点
@property(nonatomic, strong) NSMutableArray<NSValue *> *points;

// 宽高比,默认1.25
@property(nonatomic, assign) CGFloat imageRatio;

@end

UKAutographView有两个功能,

  • 记录所有的绘制点,在touchesBegan初始化当前绘制路径,在touchesMoved里面往当前绘制路径里面添加绘制点。
  • drawRect:(CGRect)rect方法里面绘制签名。
@implementation UKAutographView

- (instancetype)init {
    self = [super init];
    if (self) {
        self.paths = [[NSMutableArray alloc] init];
        self.points = [[NSMutableArray alloc] init];
        self.imageRatio = 1.25;
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 1.获取触摸对象
    UITouch *touch = touches.anyObject;
        
    // 2.获取触摸点
    CGPoint locP = [touch locationInView:touch.view];
        
    //3.创建绘图路径
    self.path = [[UIBezierPath alloc] init];
    self.path.lineWidth = 6;
    self.path.lineCapStyle = kCGLineCapRound;
    self.path.lineJoinStyle = kCGLineJoinRound;
        
    // 4.添加子路径
    [self.path moveToPoint:locP];
    [self.points addObject:[NSValue valueWithCGPoint:locP]];
        
    // 5.把path添加到数组中
    [self.paths addObject:self.path];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch *touch = touches.anyObject;
    CGPoint locP = [touch locationInView:touch.view];
    
    [self.path addLineToPoint:locP];
    [self.points addObject:[NSValue valueWithCGPoint:locP]];
    
    [self setNeedsDisplay];
    
    if (self.delegate) {
        [self.delegate autographViewDidBegin:self];
    }
}

- (void)drawRect:(CGRect)rect {
    //设置颜色
    [[UIColor blackColor] set];

    for (UIBezierPath *path in self.paths) {
        [path stroke];
    }
}

@end

UKAutographView其他方法

// 设置生成签名的宽高比
- (void)setImageRatio:(CGFloat)ratio {
    _imageRatio = ratio;
}

// 清空已有签名
- (void)clear {
    [self.paths removeAllObjects];
    [self.points removeAllObjects];
    
    [self setNeedsDisplay];
}

// 获取当前签名
- (UIImage *)save {
    CGPoint point = self.points.firstObject.CGPointValue;
    CGFloat left = point.x;
    CGFloat right = point.x;
    CGFloat top = point.y;
    CGFloat bottom = point.y;
    
    for (NSValue *pointValue in self.points) {
        CGPoint point = pointValue.CGPointValue;
        if (point.x < left) {
            left = point.x;
        } else if (point.x > right) {
            right = point.x;
        }
        
        if (point.y < top) {
            top = point.y;
        } else if (point.y > bottom) {
            bottom = point.y;
        }
    }
    CGFloat height = bottom - top;
    CGFloat width = right - left;
    
    if (width / height > self.imageRatio) {
        CGFloat newHeight = width / self.imageRatio;
        top -= (newHeight - height) / 2;
        bottom = top + newHeight;
    } else {
        CGFloat newWidth = height * self.imageRatio;
        left -= (newWidth - width) / 2;
        right = left + newWidth;
    }
    
    CGRect imageRect = CGRectMake(left - 1, top - 1, right - left + 2, bottom - top + 2);

    // 开启上下文 参数1:CGSize size 尺寸, 参数2:BOOL opaque 透明度, 参数3:CGFloat scale 比例
    UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, [UIScreen mainScreen].scale);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextTranslateCTM(context, -imageRect.origin.x, -imageRect.origin.y);
    
    // 获取图像
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    CGContextRestoreGState(context);
    
    UIImage *saveImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
        
    return saveImage;
}

2. 签名界面

为了保持签名的范围,我们会让签名界面保持横屏状态

- (UIView *)contentView {
    if (!_contentView) {
        CGFloat width = kScreenHeight - kStatusBarHeight - 50 - kBottomSafeHeight;
        CGFloat height = kScreenWidth;
        CGPoint center = CGPointMake(height/2, kStatusBarHeight + 50 + width / 2);
        
        _contentView = [[UIView alloc] initWithFrame:CGRectMake(center.x - width/2, center.y - height/2, width, height)];
        [_contentView setTransform:CGAffineTransformMakeRotation(M_PI_2)];
    }
    return _contentView;
}

效果如下

iOS 自定义签名控件_第1张图片

绘制过程中主要有三个事件,

// 重签按钮,清空签名并显示提示栏,提交按钮置灰
- (void)reSignClick:(UIButton *)sender {
    [self.autographView clear];
    self.confirmButton.enabled = NO;
    self.tipsLabel.hidden = NO;
    self.showImageView.hidden = YES;
}

// 提交按钮,在左上角显示手势签名
- (void)confirmClick:(UIButton *)sender {
    UIImage *autographImage = [self.autographView save];
    self.showImageView.image = autographImage;
    self.showImageView.hidden = NO;
}

#pragma mark - UKAutographViewDelegate -
// 开始绘制,隐藏提示栏,可以提交签名
- (void)autographViewDidBegin:(UKAutographView *)autographView {
    self.confirmButton.enabled = YES;
    self.tipsLabel.hidden = YES;
    self.showImageView.hidden = YES;
}

效果如下

iOS 自定义签名控件_第2张图片

你可能感兴趣的:(iOS,控件,ios,自定义签名控件)