iOS 不规则View

//
//  IrregularBorderView.h
//  IrregularBorderView
//
//  Created by Fan HouCheng on 15/8/28.
//  Copyright (c) 2015年 Fan HouCheng. All rights reserved.
//
#define BORDER_WIDTH 2
#define LINE_VIEW_TAG 9999
#import <UIKit/UIKit.h>
@interface IrregularBorderView : UIView

@property (nonatomic, assign)  UIColor *borderColor;
/**
 *  生成IrregularBorderView
 *
 *  @param unitSize    单位宽高
 *  @param borderColor 边框颜色
 *  @param frames      组成IrregularBorderView的子view的Frame
 *
 *  @return <#return value description#>
 */
+ (id)createViewWithUnit:(CGSize)unitSize borderColor:(CGFloat [3])borderColor frames:(NSValue *)frames, ...;

/**
 *  给View的子view添加边框
 *
 *  @param mView       父view
 *  @param unitSize    单位宽高
 *  @param borderColor 边框颜色
 */
+ (void)borderViewsInView:(UIView *)mView unitSize:(CGSize)unitSize borderColor:(CGFloat [3])borderColor;

/**
 *  组成IrregularBorderView的子view的Tap事件
 *
 *  @param tap tap事件
 */
- (void)addTapBlock:(void(^)(UIView *))tap;
@end
#import "IrregularBorderView.h"

@interface IrregularBorderView ()<UIGestureRecognizerDelegate>
{
    void (^tapBlock)( UIView * );
}
@property (nonatomic, assign) CGSize unitSize;//ListView的显示状态
@end


@implementation IrregularBorderView

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    for (UIView *view1 in self.subviews){
        if (![view1 isKindOfClass:[UIImageView class]]) {
            BOOL contains = CGRectContainsPoint(view1.frame, point);
            if (contains) {
                return YES;
            }
        }
    }
    return NO;
}

-(void)handleTapFrom:(UITapGestureRecognizer*)recognizer
{
    if (tapBlock) {
        tapBlock(recognizer.view);
    }
}

- (void)addTapBlock:(void(^)(UIView *))tap{
    tapBlock = tap;
}

+(id)createViewWithUnit:(CGSize)unitSize borderColor:(CGFloat [3])borderColor frames:(NSValue *)frames, ...{
    if(unitSize.height <= 0 || unitSize.width <= 0){
        return nil;
    }
    IrregularBorderView *viewSelf = [[IrregularBorderView alloc] init];
    viewSelf.unitSize = unitSize;
    CGSize sizeMax = CGSizeMake(0, 0);//所有frame占据的区域的最大宽度和高度
    CGPoint pointMin = CGPointMake([frames CGRectValue].origin.x, [frames CGRectValue].origin.y);//所有frame占据的区域的最原点
    
    NSMutableArray *arrArgs = [[NSMutableArray alloc] initWithCapacity:0];
    va_list args;
    va_start(args, frames);
    if (frames){
        //将第一个参数添加到array
        NSValue * prev = frames;
        [arrArgs addObject:prev];
        
        NSValue * frameVal;
        while ((frameVal = va_arg(args, NSValue *))){
            [arrArgs addObject:frameVal];
        }
    }
    va_end(args);

    //所有frame占据的区域的最原点
   for (NSValue *frameVal in arrArgs){
        CGRect frame = [frameVal CGRectValue];
        //计算最原点
        if (frame.origin.x < pointMin.x) {
            pointMin.x = frame.origin.x;
        }
        if (frame.origin.y < pointMin.y) {
            pointMin.y = frame.origin.y;
        }

        UIView *view = [[UIView alloc] initWithFrame:frame];
       UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:viewSelf action:@selector(handleTapFrom:)];
       
       [view addGestureRecognizer:tapRecognizer];
       tapRecognizer.numberOfTapsRequired = 1;
       tapRecognizer.delegate = viewSelf;
        [viewSelf addSubview:view];
        [view setBackgroundColor:[self randomColor]];
    }
    //所有frame占据的区域的最大宽度和高度
    for (NSValue *frameVal in arrArgs){
        //依次取得所有参数
        CGRect frame = [frameVal CGRectValue];
        CGFloat right = frame.origin.x - pointMin.x + frame.size.width;
        CGFloat bottom = frame.origin.y - pointMin.y + frame.size.height;
        if (right > sizeMax.width) {
            sizeMax.width = right;
        }
        if (bottom > sizeMax.height) {
            sizeMax.height = bottom;
        }
    }
    
    CGRect frame = CGRectMake(0, 0, sizeMax.width+ BORDER_WIDTH, sizeMax.height+ BORDER_WIDTH) ;
    [viewSelf setBackgroundColor:[UIColor clearColor]];
    viewSelf.frame = frame;
    for (UIView *view1 in viewSelf.subviews){
        CGRect frame1 = view1.frame;
        frame1.origin.x = frame1.origin.x  - pointMin.x + BORDER_WIDTH/2;
        frame1.origin.y = frame1.origin.y  - pointMin.y + BORDER_WIDTH/2;
        view1.frame = frame1;
    }
    [IrregularBorderView drawBorder:viewSelf unitSize:unitSize borderColor:borderColor];
    return viewSelf;
}

+(void)borderViewsInView:(UIView *)mView unitSize:(CGSize)unitSize borderColor:(CGFloat [3])borderColor{
    if(unitSize.height <= 0 || unitSize.width <= 0){
        return ;
    }
    CGRect frame =  mView.frame;
    CGRect tempFrame = mView.frame;
    tempFrame.origin.x = 0;
    tempFrame.origin.y = 0;
    mView.frame = tempFrame;
    [IrregularBorderView drawBorder:mView unitSize:unitSize borderColor:borderColor];
    mView.frame = frame;
}

+(UIColor *) randomColor
{
    CGFloat hue = ( arc4random() % 256 / 256.0 ); //0.0 to 1.0
    CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0,away from white
    CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; //0.5 to 1.0,away from black
    return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:0.3];
}

/**
 *  以unitSize把整条线打散,以方便移除重复的线(重复的线就是不用画的线)
 *
 *  @param unitSize  最小宽高单位
 *  @param fromP     起始点
 *  @param toP       结束点
 *  @param direction 方向(暂时无用)
 *
 *  @return 打散的最小unitSize的线
 */
+(NSMutableArray *)toUnitLine:(CGSize) unitSize fromP:(CGPoint)fromP toP:(CGPoint)toP direction:(int)direction{
 
    NSMutableArray *arr = [[NSMutableArray alloc]initWithCapacity:0];
    BOOL hasRemain = YES;
    while(hasRemain){
        NSValue *fromVal = [NSValue valueWithCGPoint:fromP];
        CGPoint toPoint = fromP;
        if (fromP.y == toP.y) {
            toPoint.x = toPoint.x + unitSize.width;
            if (toPoint.x >= toP.x) {
                toPoint.x = toP.x;
                hasRemain = NO;
            }else{
                fromP.x = toPoint.x;
            }
        }else{
            toPoint.y = toPoint.y + unitSize.height;
            if (toPoint.y >= toP.y) {
                toPoint.y = toP.y;
                hasRemain = NO;
            }else{
                fromP.y = toPoint.y;
            }
        }
        
        NSValue *toVal = [NSValue valueWithCGPoint:toPoint];
        [arr addObject:[[NSMutableArray alloc]initWithObjects:fromVal, toVal, [NSNumber numberWithBool:NO] , [NSNumber numberWithFloat:direction],nil]];
    }
    return arr;
}

/**
 *  描绘边框
 *
 *  @param view        需要描绘边框的父view
 *  @param unitSize    最小宽高单位
 *  @param borderColor 边框颜色
 */
+ (void)drawBorder:(UIView *)view unitSize:(CGSize) unitSize borderColor:(CGFloat [3])borderColor
{
    //先以unitSize把整条线打散,以方便移除重复的线(重复的线就是不用画的线)
    NSMutableArray *arrVLinePoint = [[NSMutableArray alloc]initWithCapacity:0];
    NSMutableArray *arrHLinePoint = [[NSMutableArray alloc]initWithCapacity:0];
    for (UIView *view1 in view.subviews){
        CGRect frame1 = view1.frame;
        //把所有起始点,结束点统计出来
        //left
        CGPoint fromPoint = frame1.origin;
        fromPoint.x = fromPoint.x;
        CGPoint toPoint = fromPoint;
        toPoint.y = frame1.origin.y + frame1.size.height;
        [arrVLinePoint addObjectsFromArray:[IrregularBorderView toUnitLine:unitSize fromP:fromPoint toP:toPoint direction:0]];
    
        //right
        fromPoint = frame1.origin;
        fromPoint.x = fromPoint.x + frame1.size.width;
        toPoint = fromPoint;
        toPoint.y = frame1.origin.y + frame1.size.height;
        [arrVLinePoint addObjectsFromArray:[IrregularBorderView toUnitLine:unitSize fromP:fromPoint toP:toPoint direction:1]];
 
        //top
        fromPoint = frame1.origin;
        fromPoint.y = fromPoint.y ;
        toPoint = fromPoint;
        toPoint.x = frame1.origin.x + frame1.size.width;
        [arrHLinePoint addObjectsFromArray:[IrregularBorderView toUnitLine:unitSize fromP:fromPoint toP:toPoint  direction:2]];

        //bottom
         fromPoint = frame1.origin;
        fromPoint.y = fromPoint.y + frame1.size.height;
         toPoint = fromPoint;
        toPoint.x = frame1.origin.x + frame1.size.width;
        [arrHLinePoint addObjectsFromArray:[IrregularBorderView toUnitLine:unitSize fromP:fromPoint toP:toPoint  direction:3]];
    }
 
    //把水平线是重复的线表示出来
    for(int i = 0; i < [arrHLinePoint count]; i++){
        NSMutableArray *line1 = [arrHLinePoint objectAtIndex:i];
        
        NSNumber *repeatVal = line1[2];
        BOOL hasRepeat = [repeatVal boolValue];
        if (!hasRepeat) {
            NSValue *fromVal1 = line1[0];
            CGPoint fromPoint1 = [fromVal1 CGPointValue];
            for(int j = i + 1; j < [arrHLinePoint count]; j++){
                NSMutableArray *line2 = [arrHLinePoint objectAtIndex:j];
                NSValue *fromVal2 = line2[0];
                CGPoint fromPoint2 = [fromVal2 CGPointValue];
                
                if(fromPoint1.y == fromPoint2.y){
                    if(fromPoint1.x == fromPoint2.x){
                        line1[2] = [NSNumber numberWithBool:YES];
                        line2[2] = [NSNumber numberWithBool:YES];
                        [arrHLinePoint replaceObjectAtIndex:i withObject:line1];
                        [arrHLinePoint replaceObjectAtIndex:j withObject:line2];
                    }
                }
            }
        }
    }
    //移除水平线重复的线
    for(int i = 0; i < [arrHLinePoint count]; i++){
        NSMutableArray *line1 = [arrHLinePoint objectAtIndex:i];
        NSNumber *repeatVal = line1[2];
        BOOL hasRepeat = [repeatVal boolValue];
        if (hasRepeat) {
            [arrHLinePoint removeObjectAtIndex:i];
            i--;
        }
    }
    
    //连接分散但是实际在之前被打散的水平线(可以不连接,也许划线的时候耗费资源)
    for(int i = 0; i < [arrHLinePoint count]; i++){
        NSMutableArray *line1 = [arrHLinePoint objectAtIndex:i];
        if (line1.count == 0) {
            continue;
        }
        NSValue *toVal1 = line1[1];
        CGPoint toPoint1 = [toVal1 CGPointValue];
        for(int j = i + 1; j < [arrHLinePoint count]; j++){
            NSMutableArray *line2 = [arrHLinePoint objectAtIndex:j];
            if (line2.count == 0) {
                continue;
            }
            NSValue *fromVal2 = line2[0];
            CGPoint fromPoint2 = [fromVal2 CGPointValue];
            NSValue *toVal2 = line2[1];
            CGPoint toPoint2 = [toVal2 CGPointValue];
            
            if(fromPoint2.x == toPoint1.x && fromPoint2.y == toPoint1.y){
                toVal1 = toVal2;
                toPoint1 = toPoint2;
                [line1 replaceObjectAtIndex:1 withObject:toVal2];
                [arrHLinePoint replaceObjectAtIndex:j withObject:[[NSMutableArray alloc] initWithCapacity:0]];
            }
        }
    }
   
    //画水平线
    for(int i = 0 ; i < arrHLinePoint.count; i ++){
        NSMutableArray *line1 = arrHLinePoint[i];
        if (line1.count == 0) {
            continue;
        }
        NSValue *fromVal1 = line1[0];
        CGPoint fromPoint1 = [fromVal1 CGPointValue];
        
        NSValue *toVal1 = line1[1];
        CGPoint toPoint1 = [toVal1 CGPointValue];
        NSNumber *direction = line1[3];
        [IrregularBorderView drawLineInView:view fromPoint:fromPoint1 toPoint:toPoint1 direction:[direction intValue] borderColor:borderColor];
    }
    
    //以下为垂直线
    for(int i = 0; i < [arrVLinePoint count]; i++){
        NSMutableArray *line1 = [arrVLinePoint objectAtIndex:i];
        
        NSNumber *repeatVal = line1[2];
        BOOL hasRepeat = [repeatVal boolValue];
        if (!hasRepeat) {
            NSValue *fromVal1 = line1[0];
            CGPoint fromPoint1 = [fromVal1 CGPointValue];
            for(int j = i + 1; j < [arrVLinePoint count]; j++){
                NSMutableArray *line2 = [arrVLinePoint objectAtIndex:j];
                NSValue *fromVal2 = line2[0];
                CGPoint fromPoint2 = [fromVal2 CGPointValue];
                
                if(fromPoint1.x == fromPoint2.x){
                    if(fromPoint1.y == fromPoint2.y){
                        line1[2] = [NSNumber numberWithBool:YES];
                        line2[2] = [NSNumber numberWithBool:YES];
                        [arrVLinePoint replaceObjectAtIndex:i withObject:line1];
                        [arrVLinePoint replaceObjectAtIndex:j withObject:line2];
                    }
                }
            }
        }
    }
    
    for(int i = 0; i < [arrVLinePoint count]; i++){
        NSMutableArray *line1 = [arrVLinePoint objectAtIndex:i];
        NSNumber *repeatVal = line1[2];
        BOOL hasRepeat = [repeatVal boolValue];
        if (hasRepeat) {
            [arrVLinePoint removeObjectAtIndex:i];
            i--;
        }
    }
    
    for(int i = 0; i < [arrVLinePoint count]; i++){
        NSMutableArray *line1 = [arrVLinePoint objectAtIndex:i];
        if (line1.count == 0) {
            continue;
        }
        NSValue *toVal1 = line1[1];
        CGPoint toPoint1 = [toVal1 CGPointValue];
        for(int j = i + 1; j < [arrVLinePoint count]; j++){
            NSMutableArray *line2 = [arrVLinePoint objectAtIndex:j];
            if (line2.count == 0) {
                continue;
            }
            NSValue *fromVal2 = line2[0];
            CGPoint fromPoint2 = [fromVal2 CGPointValue];
            NSValue *toVal2 = line2[1];
            CGPoint toPoint2 = [toVal2 CGPointValue];
            
            if(fromPoint2.x == toPoint1.x && fromPoint2.y == toPoint1.y){
                toVal1 = toVal2;
                toPoint1 = toPoint2;
                [line1 replaceObjectAtIndex:1 withObject:toVal2];
                [arrVLinePoint replaceObjectAtIndex:j withObject:[[NSMutableArray alloc] initWithCapacity:0]];
            }
        }
    }

    for(int i = 0 ; i < arrVLinePoint.count; i ++){
        NSArray *line1 = arrVLinePoint[i];
        if (line1.count == 0) {
            continue;
        }
        NSValue *fromVal1 = line1[0];
        CGPoint fromPoint1 = [fromVal1 CGPointValue];
        
        NSValue *toVal1 = line1[1];
        CGPoint toPoint1 = [toVal1 CGPointValue];
        
         NSNumber *direction = line1[3];
        [IrregularBorderView drawLineInView:view fromPoint:fromPoint1 toPoint:toPoint1 direction:[direction intValue] borderColor:borderColor];
    }
}

+ (void)drawLineInView:(UIView *)view fromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint direction:(int)direction borderColor:(CGFloat [3])borderColor
{
    if(fromPoint.x == toPoint.x && fromPoint.y == toPoint.y ){
        return;
    }
    UIImageView *imageView = (UIImageView *)[view viewWithTag:LINE_VIEW_TAG];
    if (imageView == nil) {
        imageView=[[UIImageView alloc] initWithFrame:view.frame];
        imageView.tag = LINE_VIEW_TAG;
        [view  addSubview:imageView];
    }
    UIGraphicsBeginImageContext(imageView.frame.size);
    [imageView.image drawInRect:CGRectMake(0, 0, imageView.frame.size.width, imageView.frame.size.height)];
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapSquare);  //边缘样式
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), BORDER_WIDTH);  //线宽
    CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), YES);
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), borderColor[0], borderColor[1], borderColor[2], borderColor[3]);  //颜色
    CGContextBeginPath(UIGraphicsGetCurrentContext());
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), fromPoint.x, fromPoint.y);  //起点坐标
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), toPoint.x, toPoint.y);   //终点坐标
    CGContextStrokePath(UIGraphicsGetCurrentContext());
    imageView.image=UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

@end


你可能感兴趣的:(边框,不规则View)