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

网友投稿 419 2022-06-15


在移动端产品的开发过程中,很多时候我们需要在某个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 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 @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

核心代码截屏如下:

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

另外,学习了上边的方法后,我们最好能明白以下几个问题:

(1).为什么要用分类来实现绘制的机制?

(2).runtime是否是真的懂?

(3).在drawRect:方法的末尾为什么仍然调用drawRect:?(会不会循环调用?为啥不是直接调用drawRect:)

文/iOSWH__(简书作者)


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:软件开发所经历的生命周期(软件开发生命周期的第一步是什么)
下一篇:为什么开发与测试老掐架呢(开发和测试吵架)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~