首页 > 编程语言 > 如何为你的UIView添加边缘分割线
2016
04-15

如何为你的UIView添加边缘分割线

在移动端产品的开发过程中,很多时候我们需要在某个View的top或者bottom的位置添加一条分割线。遇到这样的需求你是怎么解决的呢?欢迎各位简友们分享自己的做法。

我们通常的解决方式,就是添加一个subview,到相应的位置;然后把该subview.backgroundColor设置成我们想要的颜色。这样确实解决了,视觉效果上的问题。但是长期下来,我个人还是觉得有点低效...

今天分享的就是我目前所使用的为view添加分割线的方法。总体思路这样的:

(1).首先创建一个继承自UIView类的WHView类(该类名你可以自己指定),添加属性:

@property (nonatomic, retain) UIColor *separatorColor;

(2).接着我们创建一个枚举类型(标识View的哪些位置需要绘制分割线),并为WHView添加属性:

typedef NS_OPTIONS(NSUInteger, WHViewSeparatorMode){
    KWHViewSeparatorModeNone = 1 << 0,
    KWHViewSeparatorModeTop = 1 << 1,
    KWHViewSeparatorModeBottom = 1 << 2,
    KWHViewSeparatorModeLeft = 1 << 3,
    KWHViewSeparatorModeRight = 1 << 4,
    KWHViewSeparatorModeAll = KWHViewSeparatorModeTop |KWHViewSeparatorModeBottom |KWHViewSeparatorModeLeft |KWHViewSeparatorModeRight
};
@property (nonatomic, assign) WHViewSeparatorMode separatorMode;

(3).创建一个WHView的分类WHView (WHViewSeparator),利用runtime机制,替换drawRect:方法。在替换的方法中,绘制边缘线。

完整的代码如下:
WHView.h中代码如下:

#import <UIKit/UIKit.h> typedef NS_OPTIONS(NSUInteger, WHViewSeparatorMode){
    KWHViewSeparatorModeNone = 1 << 0,
    KWHViewSeparatorModeTop = 1 << 1,
    KWHViewSeparatorModeBottom = 1 << 2,
    KWHViewSeparatorModeLeft = 1 << 3,
    KWHViewSeparatorModeRight = 1 << 4,
    KWHViewSeparatorModeAll = KWHViewSeparatorModeTop|KWHViewSeparatorModeBottom|KWHViewSeparatorModeLeft|KWHViewSeparatorModeRight
}; @interface WHView : UIView @property (nonatomic, retain) UIColor *separatorColor; @property (nonatomic, assign) WHViewSeparatorMode separatorMode; @end @interface WHView(WHViewSeparator) @end

WHView.m中代码如下:

#import "WHView.h" #import <objc/runtime.h> @implementation WHView - (instancetype)initWithFrame:(CGRect)frame{ if(self = [super initWithFrame:frame]){ self.backgroundColor = [UIColor whiteColor]; self.separatorMode = KWHViewSeparatorModeNone;
    } return self;
}

- (UIColor *)separatorColor{ if(_separatorColor != nil){ return _separatorColor;
    } return [UIColor lightGrayColor];
}

- (void)setSeparatorMode:(WHViewSeparatorMode)separatorMode{
    _separatorMode = separatorMode;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect{ NSLog(@"______1:drawRect%@", self.class);
} @end #define KWHSeparatorWidth (1.0/[[UIScreen mainScreen] scale]) @implementation WHView(WHViewSeparator) + (void)load{
    [super load]; //在这里替换view的drawRect方法 //替换的目的在于,我们需要在替换过的__drawRect:方法中绘制分割线,绘制完毕再调回原来的drawRect:方法。 static dispatch_once_t predicate; dispatch_once(&predicate, ^{
        Method drawRect = class_getInstanceMethod(self, @selector(drawRect:));
        Method __drawRect = class_getInstanceMethod(self, @selector(__drawRect:));
        method_exchangeImplementations(drawRect, __drawRect);
    });
}

- (void)__drawRect:(CGRect)rect{ NSLog(@"______0:drawRect%@", self.class); CGContextRef contextRef = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(contextRef, KWHSeparatorWidth); CGContextSetStrokeColorWithColor(contextRef, [self.separatorColor CGColor]); CGRect rc = self.frame; //根据NS_OPTIONS枚举类型的特性,为外部设置的_separatorMode,分别绘制。 if(self.separatorMode & KWHViewSeparatorModeTop){ CGContextMoveToPoint(contextRef, 0, 0+KWHSeparatorWidth/2); CGContextAddLineToPoint(contextRef, rc.size.width, 0+KWHSeparatorWidth/2); CGContextDrawPath(contextRef, kCGPathStroke);
    } if(self.separatorMode & KWHViewSeparatorModeBottom){ CGContextMoveToPoint(contextRef, 0, rc.size.height-KWHSeparatorWidth/2); CGContextAddLineToPoint(contextRef, rc.size.width, rc.size.height-KWHSeparatorWidth/2); CGContextDrawPath(contextRef, kCGPathStroke);
    } if(self.separatorMode & KWHViewSeparatorModeLeft){ CGContextMoveToPoint(contextRef, 0+KWHSeparatorWidth/2, 0); CGContextAddLineToPoint(contextRef, 0+KWHSeparatorWidth/2, rc.size.height); CGContextDrawPath(contextRef, kCGPathStroke);
    } if(self.separatorMode & KWHViewSeparatorModeRight){ CGContextMoveToPoint(contextRef, rc.size.width-KWHSeparatorWidth/2, 0); CGContextAddLineToPoint(contextRef, rc.size.width-KWHSeparatorWidth/2, rc.size.height); CGContextDrawPath(contextRef, kCGPathStroke);
    }

    [self __drawRect:rect];
} @end

核心代码截屏如下:


WHViewSeparator.png

至此,我们完成了WHView类的封装。我们设置的默认的分割线的额颜色为[UIColor lightGrayColor];宽度为一个像素,默认类型为无分割线。在实际运用中,我们直接用WHView去初始化我们想要的view,然后设置separatorMode即可。

另外,学习了上边的方法后,我们最好能明白以下几个问题:
(1).为什么要用分类来实现绘制的机制?
(2).runtime是否是真的懂?
(3).在drawRect:方法的末尾为什么仍然调用drawRect:?(会不会循环调用?为啥不是直接调用drawRect:)


文/iOSWH__(简书作者)

编程技巧