使用Lay Out里面的VFL实现自动布局

 

今天我们讲到了UIViewController,然后就提到了一个横屏和竖屏的时候视图变化问题,刚开始我们学的是一个比较传统的方法,通过判断屏幕当前的状态然后在对view进行重新的调整。在学习的过程中,翔哥又给我们提到了一种新的方法VFL,并且用代码简单的实现了一下,然而并不是很懂。。。然后就自己在网上找了多篇对VFL的使用,不过都不是很明了。然后就自己就总结实践了一下,下面说一下我自己的使用方法。

 

1.先创建两个类,LoginViewController和LoginView,父类分别是UIViewController和UIView。然后将LoginView挂到LoginViewController上。然后再LoginView中添加两个UILabel属性

2.当屏幕旋转的时候视图控制器会向他下面的LoginView发送一个消息,让视图进行重新布局。

3.在LoginView中对View重新布局

 

- (void)layoutSubviews
{
    [self addConstraints:(NSArray *)];
}

 

 

从上面的布局方法中可以看到addConstraints:(NSArray *)需要一个NSArray类型的参数。而下面的方法返回类型正好是NSArray。所以就必须先了解下面的方法:

 

NSLayoutConstraint经常使用的一个方法

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;

参数介绍:

format:字符串类型的。主要是用来约束屏幕在横竖的时候控件或view的位置尺寸的

opts:默认参数,默认写0;具体根据自己想实现的要求去选择枚举值

metrics:是一个字典,里面主要写一些format字符串中要使用到的参数。系统会自动的将format字符串中的参数  在metrics字典中查找和参数名相同的key值,然后使用key值对应得value值。如果,你使用metrics这个字典了,就必须保证format字符串能在里面找到这个key值,否则会报错。

views:又是一个字典。这里面是VFL中所有使用到的view。

 

对format字符串中的格式做一个了解

 

功能        表达式

水平方向          H:

垂直方向          V:

Views         [view]

SuperView      |

关系         >=,==,<=

空间,间隙       -

优先级        @value

代码实现:

在LoginView中添加两个UILabel属性,记得释放哦

 

#import 

@interface LoginView : UIView

@property (nonatomic , retain) UILabel *firstLabel;
@property (nonatomic , retain) UILabel *secLabel;

@end

 

 

在LoginView.m中进行实现:

第一种情况:

1.LoginView中只添加一个控件的时候,我们将firstLabel添加上去

 

 

// 布局视图
- (void)addSubviews
{
    // 设置背景颜色
    self.backgroundColor = [UIColor cyanColor];
    
    // 添加firstLabel
    self.firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 30)];
    self.firstLabel.layer.borderWidth = 1;
    self.firstLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
    self.firstLabel.layer.cornerRadius = 5;
    self.firstLabel.text = @"点我";
    self.firstLabel.textAlignment = NSTextAlignmentCenter;
    
    [self addSubview:self.firstLabel];
    [self.firstLabel release];

}


#pragma mark - 屏幕旋转方法的实现
- (void)layoutSubviews
{
    
    UILabel *fl = self.firstLabel;
    
    fl.translatesAutoresizingMaskIntoConstraints = NO;// 这个必须写否则下面的约束方法不起作用
  
    //firstLabel控件约束
    // 水平方向上的约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[fl]-50-|" options:0 metrics:nil views:@{@"fl":fl}]];
    //垂直方向上的约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[fl(==30)]" options:0 metrics:nil views:@{@"fl":fl}]];
      
}

对约束方法解析:

 

@"H:|-50-[fl]-50-|"其中"H:"是表示这是水平方向上的约束,"|"是表示superView,"-"表示一个间隔空间,这个间隔如果是和superView之间的,那么就是20px,如果是两个同级别的view,比如@"[label]-[label1]",那么这里表示的是8px.
@"V:|-100-[fl(==30)]"其中"V:"中代表这是垂直方向上的约束,"|-100-"这里的意思就是距离头部为100px,相当于y坐标为100。后面的"[fl(==30)]",是指定这个label的高度为30px.y坐标固定了,高度固定了,那这个view的约束就完成了。如果你有需要,你的高度值(或者其他同类型的)可以使用>=,==,<=来表示,甚至你可以组合来用,像上面的30

 

运行结果对比:

使用Lay Out里面的VFL实现自动布局_第1张图片使用Lay Out里面的VFL实现自动布局_第2张图片

 

2.LoginView中有2个控件,也可以由多个控件,上代码:

 

// 布局视图
- (void)addSubviews
{
    // 设置背景颜色
    self.backgroundColor = [UIColor cyanColor];
    
    // 添加firstLabel
    self.firstLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 30)];
    self.firstLabel.layer.borderWidth = 1;
    self.firstLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
    self.firstLabel.layer.cornerRadius = 5;
    self.firstLabel.text = @"点我";
    self.firstLabel.textAlignment = NSTextAlignmentCenter;
    
    [self addSubview:self.firstLabel];
    [self.firstLabel release];
    
    // 添加secLabel
    self.secLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 150, 200, 30)];
    self.secLabel.layer.borderWidth = 1;
    self.secLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
    self.secLabel.layer.cornerRadius = 5;
    
    self.secLabel.text = @"使劲点";
    self.secLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview:self.secLabel ];
    [self.secLabel  release];
    
    
    
}


#pragma mark - 屏幕旋转方法的实现
- (void)layoutSubviews
{
    // 拿到两个控件
    UILabel *fl = self.firstLabel;
    UILabel *sl = self.secLabel;
    
    fl.translatesAutoresizingMaskIntoConstraints = NO;// 这个必须写否则下面的约束方法不起作用
    sl.translatesAutoresizingMaskIntoConstraints = NO;
    
    // metrics参数 和 views参数
    NSDictionary *metrics = @{@"Height":@30 , @"Width":@200};
    NSDictionary *views = NSDictionaryOfVariableBindings(fl,sl);
    
    //firstLabel控件约束
    // 水平方向上的约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[fl]-50-|" options:0 metrics:metrics views:views]];
    //垂直方向上的约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[fl(==Height)]" options:0 metrics:metrics views:views]];
    
    
    // secLabel约束
    // 水平约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-50-[sl(==fl)]" options:0 metrics:metrics views:views]];
    // 垂直约束
    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[fl]-30-[sl(==fl)]" options:0 metrics:metrics views:views]];
    
}

 

 

 

 

当两个控件时,我们可以像添加第一个控件时把第二个控件添加上去;同时也可以把第一个控件作为参照添加第二个控件,上面的方法就是把第一个控件作为参照,对控件重新布局;

首先看一下这个俩个参数:

 

// metrics参数 和 views参数
    NSDictionary *metrics = @{@"Height":@30 , @"Width":@200};
    NSDictionary *views = NSDictionaryOfVariableBindings(fl,sl);

metrics中的参数在VFL中有用到,就是format

 

views主要用在多控件的时候

通过下面的水平和垂直设置实现:第二个控件和第一个控件等高同宽(如下);也可以自己定义宽度和高度

@"H:|-50-[sl(==fl)]"

@"V:[fl]-30-[sl(==fl)]"

 

 

 

 

运行结果对比:

 

 使用Lay Out里面的VFL实现自动布局_第3张图片  

(竖屏)

 

使用Lay Out里面的VFL实现自动布局_第4张图片    

(横屏)

 

 

 

你可能感兴趣的:(OC基础)