在以前我们使用xib,SB,nib 设置一个view的圆角 边框需要通过一下界面非常的繁琐,所以一般情况下更倾向于使用代码来设置反而更加简单
在现在 IBInspectable 属性彻底的解决了这个问题:在 Xcode 6,你现在可以指定任何属性作为可检查项 来设置对应的属性
一、iOS8新特性IBDesignable(swift)/IBInspectable(oc),可以直接在XIB或者Storyboard中直接,设置UI类的属性。
例如:UIView.layer.borderWidth、borderColor、cornerRadius这些属性在XIB上是不能直接设置的,但是 IBDesignable/IBInspectable,利用runtime机制,就可以把这些属性映射到XIB上了,同时我们UI类的自定义属性也可以映射上 去。
IB_DESIGNABLE
的 宏
的功能就是让XCode 动态渲染
出该类图形化界面;
使用 IB_DESIGNABLE
的方式,把该宏加在自定义类的前面;
当然还需要设置下xib的动态刷新要不然可能无法实时显示 具体设置见下图
使用时候可以需将 view对应的class 改为customView
//CustomView.h文件 #import <UIKit/UIKit.h> IBInspectable @interface CustomView : UIView @property (nonatomic, assign)IBInspectable CGFloat cornerRadius; @property (nonatomic, assign)IBInspectable CGFloat BoderWidth; @property (nonatomic, assign)IBInspectable UIColor *BoderColor; @end //CustomView.m文件 #import "CustomView.h" IB_DESIGNABLE @implementation CustomView - (void)setCornerRadius:(CGFloat)cornerRadius{ _cornerRadius = cornerRadius; self.layer.cornerRadius = _cornerRadius; } -(void)setBoderColor:(UIColor *)BoderColor { _BoderColor = BoderColor; self.layer.borderColor = _BoderColor.CGColor; } -(void)setBoderWidth:(CGFloat)BoderWidth { _BoderWidth = BoderWidth; self.layer.borderWidth = _BoderWidth; } @end
首先代码部分
// // UIView+LCUtils.h // iceTearsTest // // Created by 冰泪 on 16/5/19. // Copyright © 2016年 冰泪. All rights reserved. // #import <UIKit/UIKit.h> IBInspectable @interface CustomView : UIView @property (nonatomic, assign)IBInspectable CGFloat cornerRadius; @property (nonatomic, assign)IBInspectable CGFloat BoderWidth; @property (nonatomic, assign)IBInspectable UIColor *BoderColor; @end // // UIView+LCUtils.m // iceTearsTest // // Created by 冰泪 on 16/5/19. // Copyright © 2016年 冰泪. All rights reserved. // #import "UIView+LCUtils.h" #import <objc/runtime.h> @interface LCEdgeLayer : CALayer @property(nonatomic) UIEdgeInsets edges; @property(nonatomic) UIColor *leftColor; @property(nonatomic) UIColor *topColor; @property(nonatomic) UIColor *rightColor; @property(nonatomic) UIColor *bottomColor; @property(nonatomic) BOOL widthUnitInPixel; @end @implementation LCEdgeLayer - (void)setLeftColor:(UIColor *)leftColor { _leftColor = leftColor; [self setNeedsDisplay]; } - (void)setRightColor:(UIColor *)rightColor { _rightColor = rightColor; [self setNeedsDisplay]; } - (void)setTopColor:(UIColor *)topColor { _topColor = topColor; [self setNeedsDisplay]; } - (void)setBottomColor:(UIColor *)bottomColor { _bottomColor = bottomColor; [self setNeedsDisplay]; } - (void)setEdges:(UIEdgeInsets)edges { _edges = edges; [self setNeedsDisplay]; } -(void)setWidthUnitInPixel:(BOOL)widthUnitInPixel{ _widthUnitInPixel = widthUnitInPixel; [self setNeedsDisplay]; } - (void)drawInContext:(CGContextRef)ctx { const CGFloat ONE_PIXEL_WIDTH = 1.0 / self.contentsScale; if (_edges.left > 0 && _leftColor) { CGContextSetFillColorWithColor(ctx, _leftColor.CGColor); CGRect rect = self.bounds; if (_widthUnitInPixel) rect.size.width = _edges.left * ONE_PIXEL_WIDTH; else rect.size.width = _edges.left; CGContextFillRect(ctx, rect); } if (_edges.top > 0 && _topColor) { CGContextSetFillColorWithColor(ctx, _topColor.CGColor); CGRect rect = self.bounds; if (_widthUnitInPixel) rect.size.height = _edges.top * ONE_PIXEL_WIDTH; else rect.size.height = _edges.top; CGContextFillRect(ctx, rect); } if (_edges.right > 0 && _rightColor) { CGContextSetFillColorWithColor(ctx, _rightColor.CGColor); CGRect rect = self.bounds; if (_widthUnitInPixel){ rect.origin.x += (rect.size.width - _edges.right * ONE_PIXEL_WIDTH); rect.size.width = _edges.right * ONE_PIXEL_WIDTH; } else{ rect.origin.x += (rect.size.width - _edges.right); rect.size.width = _edges.right; } CGContextFillRect(ctx, rect); } if (_edges.bottom > 0 && _bottomColor) { CGContextSetFillColorWithColor(ctx, _bottomColor.CGColor); CGRect rect = self.bounds; if (_widthUnitInPixel){ rect.origin.y += (rect.size.height - _edges.bottom * ONE_PIXEL_WIDTH); rect.size.height = _edges.bottom * ONE_PIXEL_WIDTH; } else{ rect.origin.y += (rect.size.height - _edges.bottom); rect.size.height = _edges.bottom; } CGContextFillRect(ctx, rect); } } @end @interface CALayer (Edge) -(LCEdgeLayer*) lc_findEdgeLayer; -(LCEdgeLayer*) lc_ensureEdgeLayer; @end @implementation CALayer (Hook) #if !TARGET_INTERFACE_BUILDER + (void)load { Method m1 = class_getInstanceMethod(self, @selector(lc_layoutSublayers)); Method m2 = class_getInstanceMethod(self, @selector(layoutSublayers)); method_exchangeImplementations(m1, m2); } - (void)lc_layoutSublayers { [self lc_layoutSublayers]; [self lc_findEdgeLayer].frame = self.bounds; } #endif -(LCEdgeLayer*) lc_findEdgeLayer { for (CALayer *layer in self.sublayers) { if ([layer isKindOfClass:LCEdgeLayer.class]) { return (LCEdgeLayer*)layer; } } return nil; } -(LCEdgeLayer*) lc_ensureEdgeLayer{ return [self lc_findEdgeLayer] ?: ({ LCEdgeLayer * edgeLayer = [LCEdgeLayer layer]; edgeLayer.contentsScale = [UIScreen mainScreen].scale;; edgeLayer.frame = self.bounds; edgeLayer.needsDisplayOnBoundsChange = YES; [self insertSublayer:edgeLayer atIndex:0]; edgeLayer; }); } @end @implementation UIView (Edge) #pragma -mark WIDTH - (CGFloat)edgeWidthLeft_lc{ return [self.layer lc_findEdgeLayer].edges.left; } -(void)setEdgeWidthLeft_lc:(CGFloat)edgeWidthLeft_lc{ LCEdgeLayer * layer = [self.layer lc_ensureEdgeLayer]; UIEdgeInsets edges = layer.edges; edges.left = edgeWidthLeft_lc; layer.edges = edges; } - (CGFloat)edgeWidthRight_lc{ return [self.layer lc_findEdgeLayer].edges.right; } -(void)setEdgeWidthRight_lc:(CGFloat)edgeWidthRight_lc{ LCEdgeLayer * layer = [self.layer lc_ensureEdgeLayer]; UIEdgeInsets edges = layer.edges; edges.right = edgeWidthRight_lc; layer.edges = edges; } - (CGFloat)edgeWidthTop_lc{ return [self.layer lc_findEdgeLayer].edges.top; } -(void)setEdgeWidthTop_lc:(CGFloat)edgeWidthTop_lc{ LCEdgeLayer * layer = [self.layer lc_ensureEdgeLayer]; UIEdgeInsets edges = layer.edges; edges.top = edgeWidthTop_lc; layer.edges = edges; } - (CGFloat)edgeWidthBottom_lc{ return [self.layer lc_findEdgeLayer].edges.bottom; } -(void)setEdgeWidthBottom_lc:(CGFloat)edgeWidthBottom_lc{ LCEdgeLayer * layer = [self.layer lc_ensureEdgeLayer]; UIEdgeInsets edges = layer.edges; edges.bottom = edgeWidthBottom_lc; layer.edges = edges; } - (BOOL)edgeWidthUnitInPixel_lc{ return [self.layer lc_findEdgeLayer].widthUnitInPixel; } -(void)setEdgeWidthUnitInPixel_lc:(BOOL)edgeWidthUnitInPixel_lc{ [self.layer lc_ensureEdgeLayer].widthUnitInPixel = edgeWidthUnitInPixel_lc; } - (CGFloat)edgeZPosition_lc{ return [self.layer lc_findEdgeLayer].zPosition; } -(void)setEdgeZPosition_lc:(CGFloat)edgeZPosition_lc{ LCEdgeLayer * layer = [self.layer lc_ensureEdgeLayer]; layer.zPosition = edgeZPosition_lc; #if TARGET_INTERFACE_BUILDER [layer removeFromSuperlayer]; for(CALayer * sub in self.layer.sublayers){ if(edgeZPosition_lc <= sub.zPosition){ [self.layer insertSublayer:layer below:sub]; break; } } if(!layer.superlayer) [self.layer addSublayer:layer]; #endif } #pragma -mark COLOR -(UIColor *)edgeColorLeft_lc{ return [self.layer lc_findEdgeLayer].leftColor; } -(void)setEdgeColorLeft_lc:(UIColor *)edgeColorLeft_lc{ [self.layer lc_ensureEdgeLayer].leftColor = edgeColorLeft_lc; } -(UIColor *)edgeColorRight_lc{ return [self.layer lc_findEdgeLayer].rightColor; } -(void)setEdgeColorRight_lc:(UIColor *)edgeColorRight_lc{ [self.layer lc_ensureEdgeLayer].rightColor = edgeColorRight_lc; } -(UIColor *)edgeColorTop_lc{ return [self.layer lc_findEdgeLayer].topColor; } -(void)setEdgeColorTop_lc:(UIColor *)edgeColorTop_lc{ [self.layer lc_ensureEdgeLayer].topColor = edgeColorTop_lc; } -(UIColor *)edgeColorBottom_lc{ return [self.layer lc_findEdgeLayer].bottomColor; } -(void)setEdgeColorBottom_lc:(UIColor *)edgeColorBottom_lc{ [self.layer lc_ensureEdgeLayer].bottomColor = edgeColorBottom_lc; } @end @implementation UIView(Border) -(UIColor *)borderColor_lc{ return [UIColor colorWithCGColor:self.layer.borderColor]; } -(void)setBorderColor_lc:(UIColor *)borderColor_lc{ self.layer.borderColor = borderColor_lc.CGColor; } -(CGFloat)borderWidth_lc{ return [objc_getAssociatedObject(self, _cmd) floatValue]; } -(void)setBorderWidth_lc:(CGFloat)borderWidth_lc{ objc_setAssociatedObject(self, @selector(borderWidth_lc), @(borderWidth_lc), OBJC_ASSOCIATION_RETAIN); if(self.borderWidthUnitInPixel_l) self.layer.borderWidth = borderWidth_lc / [UIScreen mainScreen].scale; else self.layer.borderWidth = borderWidth_lc; } -(BOOL)borderWidthUnitInPixel_l{ return [objc_getAssociatedObject(self, _cmd) boolValue]; } -(void)setBorderWidthUnitInPixel_l:(BOOL)borderWidthUnitInPixel_l{ objc_setAssociatedObject(self, @selector(borderWidthUnitInPixel_l), @(borderWidthUnitInPixel_l), OBJC_ASSOCIATION_RETAIN); if(borderWidthUnitInPixel_l) self.layer.borderWidth = self.borderWidth_lc / [UIScreen mainScreen].scale; else self.layer.borderWidth = self.borderWidth_lc; } -(CGFloat)borderCornerRadius_lc{ return self.layer.cornerRadius; } -(void)setBorderCornerRadius_lc:(CGFloat)borderCornerRadius_lc{ self.layer.cornerRadius = borderCornerRadius_lc; } -(UIColor *)borderLayerColor_lc{ return [UIColor colorWithCGColor: self.layer.backgroundColor]; } -(void)setBorderLayerColor_lc:(UIColor *)borderLayerColor_lc{ self.layer.backgroundColor = borderLayerColor_lc.CGColor; } -(BOOL)clipsToBounds_lc{ return self.clipsToBounds; } -(void)setClipsToBounds_lc:(BOOL)clipToBounds_lc{ self.clipsToBounds = clipToBounds_lc; } -(UIColor *)shadowColor_lc{ return [UIColor colorWithCGColor:self.layer.shadowColor]; } -(void)setShadowColor_lc:(UIColor *)shadowColor_lc{ self.layer.shadowColor = shadowColor_lc.CGColor; } -(CGFloat)shadowOpacity_lc{ return self.layer.shadowOpacity; } -(void)setShadowOpacity_lc:(CGFloat)shadowOpacity_lc{ self.layer.shadowOpacity = shadowOpacity_lc; } -(CGFloat)shadowRadius_lc{ return self.layer.shadowRadius; } -(void)setShadowRadius_lc:(CGFloat)shadowRadius_lc{ self.layer.shadowRadius = shadowRadius_lc; } -(CGPoint)shadowOffset_lc{ CGSize size = self.layer.shadowOffset; return CGPointMake(size.width, size.height); } -(void)setShadowOffset_lc:(CGPoint)shadowOffset_lc{ self.layer.shadowOffset = #if TARGET_INTERFACE_BUILDER CGSizeMake(shadowOffset_lc.x, -shadowOffset_lc.y); #else CGSizeMake(shadowOffset_lc.x, shadowOffset_lc.y); #endif } @end @interface LCLayoutConstraint : NSLayoutConstraint + (instancetype) constraintOfZeroAttribute:(NSLayoutAttribute) attr toView:(UIView*)view; @end @implementation LCLayoutConstraint + (instancetype) constraintOfZeroAttribute:(NSLayoutAttribute) attr toView:(UIView*)view{ return [self constraintWithItem:view attribute:attr relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0]; } @end @implementation UIView(Visibility) - (LCLayoutConstraint*) findConstraintByAttribute:(NSLayoutAttribute)attr{ for(NSLayoutConstraint * con in self.constraints){ if([con isKindOfClass:LCLayoutConstraint.class] && con.firstAttribute == attr) return (LCLayoutConstraint*)con; } return nil; } - (LCLayoutConstraint*) ensureConstraintByAttribute:(NSLayoutAttribute)attr{ return [self findConstraintByAttribute:attr] ?:({ LCLayoutConstraint *con = [LCLayoutConstraint constraintOfZeroAttribute:attr toView:self]; [self addConstraint:con]; con; }); } - (BOOL)goneHorizontal_lc{ return [self findConstraintByAttribute:NSLayoutAttributeWidth]; } -(void)setGoneHorizontal_lc:(BOOL)goneHorizontal_lc{ if(goneHorizontal_lc){ [self ensureConstraintByAttribute:NSLayoutAttributeWidth]; }else{ NSLayoutConstraint * cons = [self findConstraintByAttribute:NSLayoutAttributeWidth]; if(cons) [self removeConstraint:cons]; } } -(BOOL)goneVertical_lc{ return [self findConstraintByAttribute:NSLayoutAttributeHeight]; } -(void)setGoneVertical_lc:(BOOL)goneVertical_lc{ if(goneVertical_lc){ [self ensureConstraintByAttribute:NSLayoutAttributeHeight]; }else{ NSLayoutConstraint * cons = [self findConstraintByAttribute:NSLayoutAttributeHeight]; if(cons) [self removeConstraint:cons]; } } @end @implementation UIView(Xib) + (UIView*) lc_loadXibIntoView:(UIView *)view owner:(UIView *) owner{ NSString * xibName = NSStringFromClass(self); NSBundle * bundle = [NSBundle bundleForClass:self]; UIView * contentView; @try{ contentView = [bundle loadNibNamed:xibName owner:owner options:nil].firstObject; }@catch(NSException * e){ #if TARGET_INTERFACE_BUILDER @try{ contentView = [bundle loadNibNamed:[xibName stringByAppendingString:@"~iphone"] owner:owner options:nil].firstObject; }@catch(NSException * e){ contentView = [bundle loadNibNamed:[xibName stringByAppendingString:@"~ipad"] owner:owner options:nil].firstObject; } #else @throw e; #endif } //required if we manually add sub view with constraints contentView.translatesAutoresizingMaskIntoConstraints = NO; [view addSubview:contentView]; [view addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1 constant:0]]; [view addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeLeft multiplier:1 constant:0]]; [view addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeRight multiplier:1 constant:0]]; [view addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeBottom multiplier:1 constant:0]]; return contentView; } @end //set custom class to __cls to preview in IB @interface __UIView : UIView @end IB_DESIGNABLE @implementation __UIView @end @interface __UILabel : UILabel @end IB_DESIGNABLE @implementation __UILabel @end @interface __UIButton : UIButton @end IB_DESIGNABLE @implementation __UIButton @end @interface __UIImageView : UIImageView @end IB_DESIGNABLE @implementation __UIImageView @end @interface __UITextField : UITextField @end IB_DESIGNABLE @implementation __UITextField @end
该代码可用于
UIView 、UILabel、UIButton、UIImageView、UITextField
可以设置独立的上、下、左、右、边框,四边的边框, 阴影,圆角
使用时候也非常简单
1、导入UIView+LCUtils.h/UIView+LCUtils.m 文件到项目中
2、只需要把对应的类换成__UIView(前边是两个下划线_) 、__UILabel、__UIButton、__UIImageView、__UITextField 其余地方不用做任何更改 和正常的写法一样即可 通过SB/xib/nib 的可视化面板来进行对边框 /圆角 /阴影的快速设置,能为我们编程节省很多时间
然后在设置里边将出现以下菜单选项 可以设置不同的属性
上边数据显示不是很全可以以代码作为参考 很好明白对应的是什么意思
//左边框
@property(nonatomic) IBInspectable CGFloat edgeWidthLeft_lc;
@property(nonatomic) IBInspectable UIColor * edgeColorLeft_lc;
//顶边框
@property(nonatomic) IBInspectable CGFloat edgeWidthTop_lc;
@property(nonatomic) IBInspectable UIColor * edgeColorTop_lc;
//右边框
@property(nonatomic) IBInspectable CGFloat edgeWidthRight_lc;
@property(nonatomic) IBInspectable UIColor * edgeColorRight_lc;
//下边框
@property(nonatomic) IBInspectable CGFloat edgeWidthBottom_lc;
@property(nonatomic) IBInspectable UIColor * edgeColorBottom_lc;
//边框开关
@property(nonatomic) IBInspectable BOOL edgeWidthUnitInPixel_lc;
@property(nonatomic) IBInspectable CGFloat edgeZPosition_lc;
@end
@interface UIView(Border)
//边框 颜色 宽度 以及是否开启边框
@property(nonatomic) IBInspectable UIColor * borderColor_lc;
@property(nonatomic) IBInspectable CGFloat borderWidth_lc;
@property(nonatomic) IBInspectable BOOL borderWidthUnitInPixel_l;
//圆角
@property(nonatomic) IBInspectable CGFloat borderCornerRadius_lc;
@property(nonatomic) IBInspectable UIColor * borderLayerColor_lc;
@property(nonatomic) IBInspectable BOOL clipsToBounds_lc;
//阴影
@property(nonatomic) IBInspectable UIColor * shadowColor_lc;//shadowColor阴影颜色
@property(nonatomic) IBInspectable CGFloat shadowOpacity_lc;//阴影透明度,默认0
@property(nonatomic) IBInspectable CGFloat shadowRadius_lc;//阴影半径,默认3
@property(nonatomic) IBInspectable CGPoint shadowOffset_lc;//shadowOffset阴影偏移,x向右偏移4,y向下偏移4,默认(0, -3),这个跟shadowRadius配合使
@end
最后附上demo http://git.oschina.net/zhfeiyue/CustomView1
转载请注明出处谢谢: http://my.oschina.net/iceTear/blog/679949
感觉写的不错的话可以关注我哦