iOS 纯代码VFL动态布局

其实已经有很多介绍VFL的文章,但在这里我也想记录下自己的理解,给需要的朋友一点帮助,如有错误,欢迎指出。

与VFL很重要的两个很重要的方法是:

1、

/*format: 是VFL字符串。

opts:设置VFL语句中的视图相互间的对齐方式,一般默认传0即可。

metrics:字典。一般是把VFL字符串中涉及到的高度、宽带等数据参数转为字典存到metrics中。在format中,高度、宽度等数据参数就用metrics中的key代替,然后编译器解析时会自动替换metrics中的值value。

views:  字典。把format中所有相关的视图控件放入这个字典。

*/

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


2、

/*

   view1:需要被设置的那个控件

   attr1:即view1需要被设置的属性

   relation:设置的属性关系,共有三种关系可供选择

   view2:被view1所参照的对象

   attr2:即view2需要被设置的属性,一般与attr1一样

   multiplier:比例关系

   c:不多解释了。

总之,记住它们的关系一般是:view1.attr1=view2.attr2*multiplier+c

当然此时,relation参数是NSLayoutRelationEqual,也就是相当于“=”。

*/

+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;


第一个方法是生成一组约束,第二个方法是生成一个约束。一般来说简单的静态布局用第一个方法就差不多够用了,但它们两结合使用会有更好的效果,而且相比之下第二个方法能更好的设置控件之间的相对比例关系。


VFL语句的组成:

1、“H"、"V"。其中,H表示这是个水平方向上的约束(默认情况下可以不写);V表示这是个垂直方向上的约束。

2、"|"。表示所设置视图的父视图superview。

3、"[xxview对象名]"。这个括号里面放置你要设置的视图xxview对象。

4、"-"。表示间距。

5、"@"。表示优先级


VFL语句操作注意项:

1、设置约束的控件需要设置translatesAutoresizingMaskIntoConstraints=NO

2、添加约束方法:addConstraints

3、删除约束方法:removeConstraint、removeConstraints

4、修改约束方法:我是先删除某个属性约束,然后再重新设置这个属性约束。不知道还有没其他好的方法,欢迎大家提供、分享,一起进步


VFL语句实例:

(代码实现中包括:VFL实现的动态布局,通过点击按钮实现按钮以及其父视图的高度动态变化,以及下面的UIScrollView随之变化,还有UILable内容的高度动态适应)


#import <UIKit/UIKit.h>

@interface limit3ViewController :UIViewController

@end


#import "limit3ViewController.h"

@interface limit3ViewController ()

{

   BOOL isSelect;

    NSLayoutConstraint * constr1;

    NSLayoutConstraint * contr2;

   UIView * clickView;

    UIScrollView * scrollV;

}

@end

@implementation limit3ViewController

- (void)viewDidLoad {

    [superviewDidLoad];

    isSelect=NO;

    

   clickView=[UIViewnew];

    clickView.backgroundColor=[UIColorcyanColor];

    clickView.translatesAutoresizingMaskIntoConstraints=NO;//vfl布局时,此属性要设置为NO

    [self.viewaddSubview:clickView];

    

    UIButton * clickBtn=[UIButtonbuttonWithType:UIButtonTypeCustom];

    clickBtn.backgroundColor=[UIColororangeColor];

    [clickBtn setTitle:@"点击"forState:UIControlStateNormal];

    [clickBtn setTitleColor:[UIColorblackColor] forState:UIControlStateNormal];

    clickBtn.translatesAutoresizingMaskIntoConstraints=NO;//vfl布局时,此属性要设置为NO

    [clickBtn addTarget:selfaction:@selector(toExpandV:)forControlEvents:UIControlEventTouchUpInside];

    [clickViewaddSubview:clickBtn];

    

    //H:表示水平方向布局,v:表示垂直方向布局

    [self.viewaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-10-[clickView]-10-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(clickView)]];

    

    [clickViewaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-30-[clickBtn]-30-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(clickBtn)]];

    [clickViewaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|-10-[clickBtn]"options:0metrics:nilviews:NSDictionaryOfVariableBindings(clickBtn)]];

    

    //上面的语句与下面的这句结合,可以确定clickBtn的高度比例情况。当然如果你不需要按比例变化clickBtn的高度,也可以不用设置下面这句了,直接用上的VFL布局也OK

    constr1=[NSLayoutConstraintconstraintWithItem:clickBtn attribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:clickViewattribute:NSLayoutAttributeHeightmultiplier:0.5constant:0];

   constr1.active =YES;//激活

    

    scrollV=[UIScrollViewnew];

    scrollV.translatesAutoresizingMaskIntoConstraints=NO;//vfl布局时,此属性要设置为NO

    scrollV.showsHorizontalScrollIndicator=NO;

    [self.viewaddSubview:scrollV];

    

    [self.viewaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-10-[scrollV]-10-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(scrollV)]];

    [self.viewaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|-74-[clickView]-10-[scrollV]-10-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(scrollV,clickView)]];

    

    contr2=[NSLayoutConstraintconstraintWithItem:clickViewattribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:self.viewattribute:NSLayoutAttributeHeightmultiplier:0.2constant:0];

    contr2.active=YES;//激活,也可以这样写[NSLayoutConstraint activateConstraints:contr2];

    

   UILabel* desLabel = [UILabelnew];

    desLabel.translatesAutoresizingMaskIntoConstraints =NO;//vfl布局时,此属性要设置为NO

    desLabel.text =@"燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢? ——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了:现在又到了哪里呢?我不知道他们给了我多少日子;但我的手确乎是渐渐空虚了。在默默里算着,八千多日子已经从我手中溜去;象针尖上一滴水滴在大海里,我的日子滴在时间的流里,没有声音也没有影子。我不禁头涔涔而泪潸潸了。去的尽管去了,来的尽管来着,去来的中间,又怎样的匆匆呢?早上我起来的时候,小屋里射进两三方斜斜的太阳。太阳他有脚啊,轻轻悄悄地挪移了;我也茫茫然跟着旋转。于是——洗手的时候,日子从水盆里过去;吃饭的时候,日子从饭碗里过去;默默时,便从凝然的双眼前过去。我觉察他去的匆匆了,伸出手遮挽时,他又从遮挽着的手边过去,天黑时,我躺在床上,他便伶伶俐俐地从我身边垮过,从我脚边飞去了。等我睁开眼和太阳再见,这算又溜走了一日。我掩着面叹息。但是新来的日子的影儿又开始在叹息里闪过了。在逃去如飞的日子里,在千门万户的世界里的我能做些什么呢?只有徘徊罢了,只有匆匆罢了;在八千多日的匆匆里,除徘徊外,又剩些什么呢?过去的日子如轻烟却被微风吹散了,如薄雾,被初阳蒸融了;我留着些什么痕迹呢?我何曾留着象游丝样的痕迹呢?我赤裸裸来到这世界,转眼间也将赤裸裸地回去罢?但不能平的,为什么偏要白白走这一遭啊?你聪明的,告诉我,我们的日子为什么一去不复返呢?";//此时

   desLabel.numberOfLines =0;//此时设置为0,会自动适配UITable高度

    desLabel.lineBreakMode=NSLineBreakByCharWrapping;

   desLabel.backgroundColor = [UIColorlightGrayColor];

   

    [scrollVaddSubview:desLabel];

    [scrollVaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|-[desLabel]-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(desLabel)]];

    [scrollVaddConstraints:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-[desLabel(==scrollV)]-|"options:0metrics:nilviews:NSDictionaryOfVariableBindings(desLabel,scrollV)]];

}


-(void)toExpandV:(UIButton *)btn

{

    isSelect=!isSelect;

    if(isSelect){

       //更新约束

        //以防约束冲突,先删除clickView高度的约束,再添加新的约束,使其高度变小。此时,下面的scrollView自动随其变化

        [self.viewremoveConstraint:contr2];

        contr2=[NSLayoutConstraintconstraintWithItem:clickViewattribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:self.viewattribute:NSLayoutAttributeHeightmultiplier:0.15constant:0];

       contr2.active=YES;

        [self.viewlayoutIfNeeded];//更新self.view上的约束

        

        //以防约束冲突,先删除设置btn高度的约束,再添加新的约束

        [clickViewremoveConstraint:constr1];

        constr1=[NSLayoutConstraintconstraintWithItem:btn attribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:clickViewattribute:NSLayoutAttributeHeightmultiplier:0.2constant:0];

        constr1.active =YES;

        //[self updateViewConstraints];

        [clickViewlayoutIfNeeded];//更新clickView上的约束

    }else{

       //更新约束

        //以防约束冲突,先删除clickView高度的约束,再添加新的约束,恢复原来的高度。此时,下面的scrollView自动随其变化

        [self.viewremoveConstraint:contr2];

        contr2=[NSLayoutConstraintconstraintWithItem:clickViewattribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:self.viewattribute:NSLayoutAttributeHeightmultiplier:0.2constant:0];

       contr2.active=YES;

        [self.viewlayoutIfNeeded];

        

        //以防约束冲突,先删除设置btn高度的约束,再添加新的约束

        [clickViewremoveConstraint:constr1];

        constr1=[NSLayoutConstraintconstraintWithItem:btn attribute:NSLayoutAttributeHeightrelatedBy:NSLayoutRelationEqualtoItem:clickViewattribute:NSLayoutAttributeHeightmultiplier:0.5constant:0];

        constr1.active =YES;

        [clickViewlayoutIfNeeded];

    }

}

- (void)didReceiveMemoryWarning {

    [superdidReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end


未点击状态效果图与点击状态动态改变后效果图如下:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值