在之前咱們使用xib,SB,nib 設置一個view的圓角 邊框須要經過一下界面很是的繁瑣,因此通常狀況下更傾向於使用代碼來設置反而更加簡單git
在如今 IBInspectable 屬性完全的解決了這個問題:在 Xcode 6,你如今能夠指定任何屬性做爲可檢查項 來設置對應的屬性編程
例如:UIView.layer.borderWidth、borderColor、cornerRadius這些屬性在XIB上是不能直接設置的,可是 IBDesignable/IBInspectable,利用runtime機制,就能夠把這些屬性映射到XIB上了,同時咱們UI類的自定義屬性也能夠映射上 去。swift
IB_DESIGNABLE
的宏
的功能就是讓XCode動態渲染
出該類圖形化界面;iphone
使用IB_DESIGNABLE
的方式,把該宏加在自定義類的前面;ui
固然還須要設置下xib的動態刷新要否則可能沒法實時顯示 具體設置見下圖atom
使用時候能夠需將 view對應的class 改成customViewspa
//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
首先代碼部分.net
// // 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
該代碼可用於code
UIView 、UILabel、UIButton、UIImageView、UITextFieldblog
能夠設置獨立的上、下、左、右、邊框,四邊的邊框, 陰影,圓角
使用時候也很是簡單
一、導入UIView+LCUtils.h/UIView+LCUtils.m 文件到項目中
二、只須要把對應的類換成__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
感受寫的不錯的話能夠關注我哦