• IOS开发之自动布局框架设计(三)


    【上集剧情概要:上集我们主要试着用连式结构写了一个简单地布局的设计的demo,首先通过block方式实现链式调用,然后封装添加布局的约束到block里面,实现了上下左右的简单布局】

     好吧,各位观众,接下来抛砖引玉,逐渐去添加一些布局功能的时候到了。。。。。

     首先,我们考虑一个问题,因为上集我们主要是默认相对视图为superview,而且都是用默认偏移量constant,并没有倍数关系,那么我们如何加入toItem和multiplier这两个参数呢???

     用什么方式展示给用户更为好的呢???

     思考中ing..........

     好吧,最直接的办法就是添加两个参数,这样就凑齐了。。。。。

     ok,我把代码封装了一下,变成下面的样子。。。

    #import "UIView+GCFAdditions.h"
    
    @implementation UIView (GCFAdditions)
    
    - (UIView *(^)(UIView *toItem,float multiplier,NSInteger space))left
    {
        return  [self addGCFConstraint:NSLayoutAttributeLeft];
    }
    
    - (UIView *(^)(UIView *toItem,float multiplier,NSInteger space))right
    {
        return  [self addGCFConstraint:NSLayoutAttributeRight];
    }
    
    - (UIView *(^)(UIView *toItem,float multiplier,NSInteger space))top
    {
        return  [self addGCFConstraint:NSLayoutAttributeTop];
    }
    
    - (UIView *(^)(UIView *toItem,float multiplier,NSInteger space))bottom
    {
        return  [self addGCFConstraint:NSLayoutAttributeBottom];
    }
    
    - (UIView *(^)(NSInteger value))width
    {
        return ^(NSInteger value) {
            if (value) {
                NSLog(@"%ld",(long)value);
            } else {
                NSLog(@"%ld",(long)value);
            }
            
            self.translatesAutoresizingMaskIntoConstraints=NO;
            
            NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:value];
            [self addConstraint:constraint];
            
            return self;
        };
    }
    
    - (UIView *(^)(NSInteger value))height
    {
        return ^(NSInteger value) {
            if (value) {
                NSLog(@"%ld",(long)value);
            } else {
                NSLog(@"%ld",(long)value);
            }
            
            self.translatesAutoresizingMaskIntoConstraints=NO;
            
            NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:value];
            [self addConstraint:constraint];
            
            return self;
        };
    }
    
    
    -(UIView *(^)(UIView *toItem,float multiplier,NSInteger space))addGCFConstraint:(NSLayoutAttribute )att
    {
        return ^(UIView *toItem,float multiplier,NSInteger space) {
            if (space) {
                NSLog(@"%ld",(long)space);
            } else {
                NSLog(@"%ld",(long)space);
            }
            
            self.translatesAutoresizingMaskIntoConstraints=NO;
            
            NSLayoutConstraint *constaintTop = [NSLayoutConstraint
                                                constraintWithItem:self
                                                attribute:att
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:toItem
                                                attribute:att
                                                multiplier:1.0
                                                constant:space];
            
            [self.superview addConstraint:constaintTop];
            
            return self;
        };
    }
    
    
    @end

    添加了width和height两个属性

    在调用里面使用变成:

     self.view1.left(self.view,1,50)
                  .right(self.view,1,-50)
                  .top(self.view,1,100)
                  .height(130);
        
        self.view2.left(self.view,1,50)
                  .right(self.view,1,-50)
                  .top(self.view1,1,100)
                  .height(130);
        
        self.view3.left(self.view,1,50)
                  .right(self.view,1,-50)
                  .top(self.view2,1,100)
                  .height(130);

    好了,到这里,基本上可以调用简单地封装了,那么问题来了,其实我们还差一个参数,就是当前view相对于toItem的属性参数是一样的,我们同样要传参数过去吗???

    所以这里考虑到参数过多,如是想要封装起来

    好吧,各位童鞋我们现在来解决下面一个问题,就是如果

    top(self.view1,1,100)

    第一个参数有两种情况:

    如果是UIView的话,默认与当前的属性相同.....

    如果是UIView的属性的话,则使用当前的属性

    -(UIView *(^)(id toItem,float multiplier,NSInteger space))addGCFConstraint:(NSLayoutAttribute )att
    {
        return ^(id toItem,float multiplier,NSInteger space) {
            if (space) {
                NSLog(@"%ld",(long)space);
            } else {
                NSLog(@"%ld",(long)space);
            }
            
            self.translatesAutoresizingMaskIntoConstraints=NO;
            
            if([toItem isKindOfClass:[GCFAttribute class]])
            {
                GCFAttribute *attribute=(GCFAttribute *)toItem;
                NSLayoutConstraint *constaint=[NSLayoutConstraint constraintWithItem:self
                                                                           attribute:att
                                                                           relatedBy:NSLayoutRelationEqual
                                                                              toItem:attribute.view
                                                                           attribute:attribute.attribute
                                                                          multiplier:1.0
                                                                            constant:space];
               [self.superview addConstraint:constaint];
            }
            else
            {
                NSLayoutConstraint *constaint=[NSLayoutConstraint constraintWithItem:self
                                                                           attribute:att
                                                                           relatedBy:NSLayoutRelationEqual
                                                                              toItem:toItem
                                                                           attribute:att
                                                                          multiplier:1.0
                                                                            constant:space];
                [self.superview addConstraint:constaint];
            }
            
            return self;
        };
    }

    这里使用id类型传入参数:

    如果是UIView的话,先转为UIView类型,attribute属性都设置为相同的即可。

    如果是GCFAttribute的话,先转为GCFAttribute类型,attribute属性都设置为GCFAttribute的attribute即可。

    好吧,那GCFAttribute主要做什么呢,主要是将View和attribute封装到一个类里面,这样便于参数的传输。

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface GCFAttribute : NSObject
    
    @property(nonatomic, strong) UIView *view;
    
    @property(nonatomic, assign) NSLayoutAttribute attribute;
    
    - (id)initWithView:(UIView *)view : (NSLayoutAttribute)layoutAttribute;
    
    @end
    #import "GCFAttribute.h"
    
    @implementation GCFAttribute
    
    - (id)initWithView:(UIView *)view : (NSLayoutAttribute)layoutAttribute {
        self = [super init];
        if (!self) return nil;
        
        _attribute =layoutAttribute;
        _view=view;
        
        return self;
    }
    
    @end

     还有个问题需要解决,发现每次都要放三个参数,能不能再减少了呢???

     其实multiplier这个参数很多时候默认为1,那么可以把它提出来吗,答案是肯定的,我们依旧使用Block链式调用的方式

  • 相关阅读:
    Android的读写文件及权限设置
    surfaceView和View的区别
    git的常见问题
    APP的缓存文件放在哪里?
    AndroidStudio遇到过的问题
    订单和支付状态不同步解决方法
    支付宝支付不成功原因
    格式化输出%s和%S的区别
    Android SDK更新下载失败以及Studio首次安装取消自动下载SDK
    SPOJ 104 HIGH
  • 原文地址:https://www.cnblogs.com/guchengfengyun/p/5853222.html
Copyright © 2020-2023  润新知