IBInspectable / IBDesignable可視化控件編程講解/使用/封裝

前言:

在之前咱們使用xib,SB,nib 設置一個view的圓角 邊框須要經過一下界面很是的繁瑣,因此通常狀況下更傾向於使用代碼來設置反而更加簡單git

014.png

在如今 IBInspectable 屬性完全的解決了這個問題:在 Xcode 6,你如今能夠指定任何屬性做爲可檢查項 來設置對應的屬性編程

正題:

1、iOS8新特性IBDesignable(swift)/IBInspectable(oc),能夠直接在XIB或者Storyboard中直接,設置UI類的屬性。

例如:UIView.layer.borderWidth、borderColor、cornerRadius這些屬性在XIB上是不能直接設置的,可是 IBDesignable/IBInspectable,利用runtime機制,就能夠把這些屬性映射到XIB上了,同時咱們UI類的自定義屬性也能夠映射上 去。swift

2、IB_DESIGNABLE 的具體使用方法:

 IB_DESIGNABLE的功能就是讓XCode動態渲染出該類圖形化界面;iphone

   使用IB_DESIGNABLE的方式,把該宏加在自定義類的前面;ui

固然還須要設置下xib的動態刷新要否則可能沒法實時顯示  具體設置見下圖atom

 

3、下邊附上自定義的demo代碼 裏邊簡單的實現了邊框和 圓角的可視化修改

使用時候能夠需將   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

 

4、IBInspectable / IBDesignable封裝(導入項目以後能夠對UIView 、UILabel、UIButton、UIImageView、UITextField使用)

 首先代碼部分.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

感受寫的不錯的話能夠關注我哦

相關文章
相關標籤/搜索