iOS-UI

300 阅读7分钟

UIButton

iOS常用组件和布局, 个人学习记录, 仅做记录.

//- (IBAction)minus:(id)sender {
//    NSLog(@"minus");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.size.width -= 10;
//    originFrame.size.height -= 10;
//
//    originFrame.origin.x += 5;
//    originFrame.origin.y += 5;
//    self.btnIcon.frame = originFrame;
//}
//
//- (IBAction)add:(id)sender {
//    NSLog(@"add");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.size.width += 10;
//    originFrame.size.height += 10;
//
//    originFrame.origin.x -= 5;
//    originFrame.origin.y -= 5;
//    self.btnIcon.frame = originFrame;
//}
//
//- (IBAction)right:(id)sender {
//    NSLog(@"right");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.origin.x += 10;
//    self.btnIcon.frame = originFrame;
//}
//
//- (IBAction)left:(id)sender {
//    NSLog(@"left");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.origin.x -= 10;
//    self.btnIcon.frame = originFrame;
//}
//
//- (IBAction)down:(id)sender {
//    NSLog(@"down");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.origin.y += 10;
//    self.btnIcon.frame = originFrame;
//}
//
//- (IBAction)up {
//    NSLog(@"up");
//    CGRect originFrame = self.btnIcon.frame;
//    originFrame.origin.y -= 10;
//    self.btnIcon.frame = originFrame;
//}
- (IBAction)zoom:(UIButton *)sender {
    CGFloat gap = 100;
    
    CGRect bounds = self.btnIcon.bounds;
    
    switch (sender.tag) {
        case 1011: // 放大
            bounds.size.height += gap;
            bounds.size.width += gap;
            break;
        case 1012: // 缩小
            bounds.size.height -= gap;
            bounds.size.width -= gap;
            break;
    }
    
//    // 通过动画执行
//    // 1. 开启动画
//    [UIView beginAnimations:nil context:nil];
//    // 2. 设置动画时间
//    [UIView setAnimationDuration:1];
//
//    // 3. 动画执行操作
//    self.btnIcon.bounds = bounds;
//
//    // 4. 提交动画
//    [UIView commitAnimations];
    
    // 通过block实现动画
    [UIView animateWithDuration:1.0 animations:^{
        self.btnIcon.bounds = bounds;
    } completion:^(BOOL finished) {
        NSLog(@"动画结束");
    }];
    
}

- (IBAction)moveIcon:(UIButton *)sender {

    CGFloat gap = 100;
    
    CGPoint centerPoint = self.btnIcon.center;
    
    switch (sender.tag) {
        case 1001: // 左
            centerPoint.x -= gap;
            break;
        case 1002: // 上
            centerPoint.y -= gap;
            break;
        case 1003: // 右
            centerPoint.x += gap;
            break;
        case 1004: // 下
            centerPoint.y += gap;
            break;
    }
    
//    // 通过动画执行
//    // 1. 开启动画
//    [UIView beginAnimations:nil context:nil];
//    // 2. 设置动画时间
//    [UIView setAnimationDuration:1];
//
//    // 3. 动画执行操作
//    self.btnIcon.center = centerPoint;
//
//    // 4. 提交动画
//    [UIView commitAnimations];
    
    // 通过block实现动画
    [UIView animateWithDuration:1.0 animations:^{
        self.btnIcon.center = centerPoint;
    } completion:^(BOOL finished) {
        NSLog(@"动画结束");
    }];
}

UIButton 动态创建

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIButton *btnIcon;

@end

@implementation ViewController

// 当显示一个界面的时候,首先创建这个界面对应的控制器
// 只要 viewDidLoad 被执行了, 就表示控制器所管理的view创建好了
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSLog(@"viewDidLoad");
    
    // 动态创建按钮
    // 1. 创建按钮
    UIButton *btnIcon = [[UIButton alloc] init];
    self.btnIcon = btnIcon;
    
    // 2. 设置按钮属性
    [btnIcon setTitle:@"点我吧" forState:UIControlStateNormal];
    [btnIcon setTitle:@"你瞅啥" forState:UIControlStateHighlighted];
    // 2.2 设置背景
    [btnIcon setBackgroundImage:[UIImage imageNamed:@"icon1"] forState:UIControlStateNormal];
    [btnIcon setBackgroundImage:[UIImage imageNamed:@"icon2"] forState:UIControlStateHighlighted];
    // 2.3 设置字体颜色
    [btnIcon setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    [btnIcon setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted];
    // 2.4 设置大小
    btnIcon.frame = CGRectMake(100, 100, 100, 100);
    
    // 2.5 设置监听
    [btnIcon addTarget:self action:@selector(iconClick) forControlEvents:UIControlEventTouchUpInside];
    
    // 3. 添加按钮
    [self.view addSubview:btnIcon];
     
}

-(void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    NSLog(@"didReceiveMemoryWarning");
}

- (void) iconClick {
    NSLog(@"iconClick");
}

@end

UIView 动画

// 基于原始值缩放
self.btnIcon.transform = CGAffineTransformMakeScale(1.5, 1.5);

// 基于当前值缩放
self.btnIcon.transform = CGAffineTransformScale(self.btnIcon.transform, 1.5, 1.5);

// 基于原始值旋转
self.btnIcon.transform = CGAffineTransformMakeRotation(90);

// 基于当前值旋转 M_PI_4 = 45°
self.btnIcon.transform = CGAffineTransformRotate(self.btnIcon.transform, M_PI_4);


// 组合动画
[UIView animateWithDuration:2.5 animations:^{
    self.btnIcon.transform = CGAffineTransformTranslate(self.btnIcon.transform, 50, 50);
    self.btnIcon.transform = CGAffineTransformRotate(self.btnIcon.transform, M_PI_4);
    self.btnIcon.transform = CGAffineTransformScale(self.btnIcon.transform, 1.5, 1.5);
}];
    
// 父控件
sender.superview;
    
// 所有子控件
sender.superview.subviews;
    
// 获取或有子控件,修改背景颜色
for (UIView *subView in sender.superview.subviews) {
    [subView setBackgroundColor:[UIColor redColor]];
}
    
// 移除所有子控件
while (self.view.subviews.firstObject) {
    [self.view.subviews.firstObject removeFromSuperview];
}


// 基于原始值平移
self.btnIcon.transform = CGAffineTransformMakeTranslation(0, 50);
    
// 基于当前值平移
self.btnIcon.transform = CGAffineTransformTranslate(self.btnIcon.transform, 0, -50);


// 恢复原状
self.btnIcon.transform = CGAffineTransformIdentity;

图片浏览

image.png

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic, strong) NSArray * pics;

@property(nonatomic, assign) int index;

@property (weak, nonatomic) IBOutlet UIImageView *ivLoading;

@property (weak, nonatomic) IBOutlet UIImageView *ivPic;
@property (weak, nonatomic) IBOutlet UILabel *labelIndex;
@property (weak, nonatomic) IBOutlet UILabel *labelTitle;
- (IBAction)next:(UIButton *)sender;
- (IBAction)pre:(UIButton *)sender;

- (void) setImage:(int) index;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSLog(@"pics = %@", self.pics);
    
    [self setImage:0];
    
    // bdp_anim_loading_small_blue_001
    NSMutableArray *arrayM = [NSMutableArray array];
    for (int i = 0; i < 12; i++) {
        [arrayM addObject:[UIImage imageNamed:[NSString stringWithFormat:@"bdp_anim_loading_small_blue_%03d", i+1]]];
//        NSString *imageName = [NSString stringWithFormat:@"bdp_anim_loading_small_blue_%03d.png", i+1];
//        NSString *path = [[NSBundle mainBundle] pathForResource:imageName ofType:nil];
//        NSLog(@"path = %@", path);
//        [arrayM addObject:[UIImage imageWithContentsOfFile:path]];
    }
    NSLog(@"arrayM = %@", arrayM);
    
    // 通过 [UIImage imageNamed] 加载图片会一直存在内存中缓存,不会自动释放
    // 解决 : 使用 [UIImage imageWithContentsOfFile:path] 加载
    
    // 1. 设置UIImageView animationImages 数据源
    self.ivLoading.animationImages = arrayM;
    // 2. 设置持续时间
    self.ivLoading.animationDuration = arrayM.count * 0.1;
    // 3. 是否重复播放
    self.ivLoading.animationRepeatCount = NSIntegerMax;
    // 4. 开启动画
    [self.ivLoading startAnimating];
    
//    self.ivLoading animation
    // 要考虑 self.ivLoading.animationImages 指针释放
}

- (NSArray *)pics {
    // 懒加载
    if (_pics == nil) {
        // [NSBundle mainBundle] 表示app安装到手机上的根目录
        // 然后在安装根目录 搜索文件
        NSString *path = [[NSBundle mainBundle] pathForResource:@"picInfo.plist" ofType:nil];
        
        _pics = [NSArray arrayWithContentsOfFile:path];
    }
    return _pics;
}

- (IBAction)pre:(UIButton *)sender {
    [self setImage: self.index - 1];
}

- (IBAction)next:(UIButton *)sender {
    [self setImage: self.index + 1];
}
 
- (void) setImage:(int) index {
    if (index < 0 || index >= self.pics.count) {
        return;
    }
    
    self.index = index;
    
    NSDictionary *data = self.pics[index];
    
    self.ivPic.image = [UIImage imageNamed:data[@"icon"]];
    self.labelTitle.text = data[@"title"];
    
    self.labelIndex.text = [NSString stringWithFormat:@"%d / %lu", self.index + 1, self.pics.count];
}

@end

picInfo.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>icon</key>
		<string>pic1</string>
		<key>title</key>
		<string>天泉套装</string>
	</dict>
	<dict>
		<key>icon</key>
		<string>pic2</string>
		<key>title</key>
		<string>失落套装</string>
	</dict>
	<dict>
		<key>icon</key>
		<string>pic3</string>
		<key>title</key>
		<string>碧玉套装</string>
	</dict>
</array>
</plist>

xib 和 UIView

  1. 创建xib image.png

  2. 创建 自定义View, 继承 UIView (类名建议跟xib一致) image.png

  3. xib关联 自定义View

image.png

xib 关联 UIView 注意 :

  1. 在File's Owner中设置class,设置了要删掉
  2. 如果File's Owner 有设置关联的要删除关掉属性,只能在View中设置关联.这点和在ViewController创建Xib的时候有点区别,viewController 关联的属性都是通过File's Owner 关联的

将xib上的控件拖线关联到自定义View上.

// AppView.h
#import <UIKit/UIKit.h>
#import "ModelAppView.h"
@interface AppView : UIView
    @property(nonatomic, strong) ModelAppView *model;
@end

// AppView.m
#import "AppView.h"
@interface AppView ()
@property (weak, nonatomic) IBOutlet UIImageView *ivIcon;
@property (weak, nonatomic) IBOutlet UILabel *tvDect;
@property (weak, nonatomic) IBOutlet UIButton *btnDownload;
@end
@implementation AppView
- (void)setModel:(ModelAppView *)model {
    _model = model;
    self.ivIcon.image = [UIImage imageNamed:@"ic_launcher"];
    self.tvDect.text = model.name;
}
+ (instancetype) appView {
    NSBundle *rootBundle = [NSBundle mainBundle];
    return [[rootBundle loadNibNamed:@"AppView" owner:nil options:nil] firstObject];
}
@end

// 在 ViewController 使用 
// 创建自定义view
AppView *view = [AppView appView];
// 设置坐标
CGFloat viewX = (gap + subViewWidth) * c + gap;
CGFloat viewY = (gap + subViewHeight) * r + gap;
view.frame = CGRectMake(viewX, viewY, subViewWidth, subViewHeight);
// 设置view model
[self.view addSubview:view];
// 添加view
view.model = self.appInfos[i];

显示提示


- (UILabel *) showMsg:(NSString *) msg {
    UILabel *msgView = [[UILabel alloc] init];
    msgView.text = msg;
    
    
    CGFloat sw = self.superview.frame.size.width;
    CGFloat sh = self.superview.frame.size.height;
    
    CGFloat msgW = sw * 0.7;
    CGFloat msgH = 30;
    CGFloat msgX = (sw - msgW) / 2;
    CGFloat msgY = (sh - msgH) / 2;
    
    msgView.frame = CGRectMake(msgX, msgY, msgW, msgH);
    
    [msgView setTextColor:[UIColor whiteColor]];
    [msgView setBackgroundColor:[UIColor blackColor]];
    [msgView setTextAlignment:NSTextAlignmentCenter];
    
    
    msgView.alpha = 0.0;
    
    msgView.layer.cornerRadius = 10;
    msgView.layer.masksToBounds = YES;
    
    [UIView animateWithDuration:1.0 animations:^{
        msgView.alpha = 0.6;
    } completion:^(BOOL finished) {
        if (finished) {
            [UIView animateWithDuration:0.5 delay:1.0 options:nil animations:^{
                msgView.alpha = 0;
            } completion:^(BOOL finished) {
                [msgView removeFromSuperview];
            }];
        }
    }];
    
    [self.superview addSubview:msgView];
    
    return msgView;
}

代码段-快速编辑

image.png

image.png

UIScrollView

image.png

image.png

设置到指定位置,滚动动画 image.png

隐藏滚动指示器 image.png

// 设置UIScrollView的内容的内边距
self.scrollView.contentInset = UIEdgeInsetMake(10,10,10,10);

image.png

image.png image.png

UIScrollView 使用代理监听滚动
// 实现 UIScrollViewDelegate 协议
@interface ViewController () <UIScrollViewDelegate>

@property(nonatomic, weak) IBOutlet UIScrllView *scrollView;
@property(nonatomic, weak) IBOutlet UIImageView *imageView;

@end

@implementation ViewController
    - (void) viewDidLoad {
        [super viewDidLoad];
        self.scrollView.contentSize = self.imageView.image.size;
        self.scrollView.delegate = self;
        
        // 设置UIScrollView 缩放比例, 配置和 viewForZoomInScrollView 回调使用
        self.scrollView.maximunZoomScale = 3.5;
        self.scrollView.minimunZoomScale = 0.5;
    }
    
    // UIScrollViewDelegate协议方法
    - (void) scrollViewWillBeginDragging:(UIScrollView *) scrollView {
        NSLog(@"即将开始拖拽");
    }
    - (void) scrollViewDidScroll:(UIScrollView *) scrollView {
        NSLog(@"正在滚动");
    }
    - (void) scrollViewDidEndDragging:(UIScrollView *) scrollView {
        NSLog(@"拖拽结束");
    }
    
    // UIScrollView 缩放view
    - (void) viewForZoomInScrollView:(UIScrollView *) scrollView {
        return self.imageView;
    }
    - (void) scrollViewWillBeginZooming:(UIScrollView *) scrollView {
        NSLog(@"准备缩放");
    }
    - (void) scrollViewDidZoom:(UIScrollView *) scrollView {
        NSLog(@"正在缩放");
    }
    - (void) scrollViewDidEndZooming:(UIScrollView *) scrollView {
        NSLog(@"缩放结束");
    }
@end
图片轮播图
@interface ViewController() <UIScrollViewDelegate>

    @property(weak, nonatomic) IBOutlet UIScrollView *scrollView;
    @property(weak, nonatomic) IBOutlet UIPageControl *pageControl;

    @property(strong, nonatomic) NSTimer *timer;

@end

@implementation ViewController 

-(void) viewDidLoad {
    [super viewDidLoad];
    [self loadIamgeViews];
    
}
-(void) initIamgeViewsInScrollView {
    CGFloat y = 0;
    CGFloat w = scrollView.frame.size.width;
    CGFloat h = scrollView.frame.size.height;
    // 在 scrollView 中横向添加图片
    for(int i = 0; i < 5; i++) {
        UIImageView *imageView = [[UIImageView alloc] init];
        
        // 设置图片
        imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"img_%02d", i]];
        CGFloat x = i * w;
        imageView.frame = CGRectMake(x, y, w, h);
        
        // 添加进scrollView
        [self.scrollView addSubview:imageView];
    }
    
    // 设置scrollView内容大小
    CGFloat maxW = CGRectGetMaxX(self.scrollView.subViews.lastObject.frame);
    self.scrollView.contentSize = CGSizeMake(maxW, 0);
    
    // 开启分页功能, 以scrollView宽度位一页进行划分
    self.scrollView.pagingEnabled = YES;
    
    // 隐藏水平滚动条
    self.scrollView.showHorizontalScrollIndicator = NO:
    
    // 设置指示器页数
    self.pageControl.numberOfPages = ceil(maxW / self.scrollView.frame.szie.width);
    // 设置指示器当前页数, 在 UIScrollViewDetegate.scrollViewDidScroll 动态计算当前页数
    self.pageControl.currentPage = 0;

    // 开启定时器 NSTimer(时间间隔大,1 2秒)、CADisplayLink(时间间隔小,0.0x秒)
    [self startTime];
}

- (void) startTime {
    self.time = [NSTimer scheduledTimeWithInterval:1.0 target:self selector:@selector(scrollImage) userInfo:nil repeats:YES];
    
    // 修改self.timer优先级与控件一样
    // 创建一个消息循环对象
    NSRunLoop * runLoop = [NSRunLoop currentRunLoop];
    // 改变 self.timer对象的优先级
    [runLoop addTimer:self.timer forMode:NSRunLoopCommonModes];
    
    // 设置 pageControl 在 scrollView 中为最顶层View
    // [self.scrollView bringSubviewToFront:self.pageControl];
}

- (void) nextPageOfScrollView {
    NSInteger page = self.pageControl.currentPage;
    if (page == self.pageControl.numberOfPages - 1) {
         // 跳转到第一页
         page = 0;
    } else {
        // 下一页
        page++;
    }
    // 跳转
    CGFloat offsetX = page * self.scrollView.frame.size.width;
    [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}

// 开始拖拽
- (void) scrollViewWillBeginDragging:(UIScrollView *) scrollView {
    // 停止计时器,调用invalidate停止后计时器不可重用
    [self.timer invalidate];
    self.timer = nil;
}
// 正在滚动
- (void) scrollViewDidScroll:(UIScrollView *) scrollView {
    //  动态计算 pageControl 当前页数
    // 1. 获取当前偏移量
    CGFloat offsetX = scrollView.currentOffset.x;
    // 1.1 使用偏移量加上半页宽度,拖拽到一半时已经可以确认切换页数
    offsetX += scrollView.frame.size.width;
    
    // 2. 用偏移除以 scrollView 宽度,获取当前页数
    int page = offsetX / scrollView.frame.size.width;
    
    // 3. 设置指示器页数
    self.pageControl.currentPage = page;
}
// 拖拽结束
- (void) scrollViewDidEndDragging:(UIScrollView *) scrollView {
    [self startTime];
}

@end


UICollectionView 流式列表

#import "ViewController.h"

// UICollectionViewDelegateFlowLayout 继承 UICollectionViewDelegate 协议
@interface ViewController () <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //创建一个layout布局类
    UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc]init];
    //设置布局方向为垂直流布局
//    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    //设置每个item的大小为100*100
    layout.itemSize = CGSizeMake(150, 40);
    //创建collectionView 通过一个布局策略layout来创建
    UICollectionView * collect = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:layout];
    //代理设置
    collect.delegate=self;
    collect.dataSource=self;
    //注册item类型 这里使用系统的类型
    [collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];
   
    [self.view addSubview:collect];
}

# pragma UICollectionViewDataSource

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 300;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell * cell  = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];
//    indexPath.item;
    cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
    return cell;
}

# pragma UICollectionViewDelegateFlowLayout

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return CGSizeMake(40, arc4random()%50 + 50);
}
@end

image.png

屏幕适配

1. autoresizing

需要关闭 autolayout

// 纯代码方式使用 autoresizing
@interface ViewControler ()
@end
@implementation ViewControler
- (void) viewDidLoad {
    // 父View
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.frame = CGRectMake(0,0,200,200);
    [self.view addSubview:blueView];
    
    // 子Viewq
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    int redW = blueView.frame.size.width;
    int redH = 50;
    int redX = 0;
    int redY = blueView.frame.size.height - redH;
    redView.frame = CGRectMake(redX,redY,redW,redH);
    [blueView addSubview:redView];
    
    // 设置autoresizing 锚定右边
    redView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
    
    // UIViewAutoresizingFlexibleLeftMargin 左边可变,右边固定
    // UIViewAutoresizingFlexibleTopMargin 顶部可变,底部固定
    // UIViewAutoresizingFlexibleWidth 宽度随父控件变化而变化
}
@end

2. autolayout

  • 参照
  • 约束

约束添加的位置

  1. 约束与其他view没关系,约束会添加在自身上
  2. 约束参照父类,约束会添加在父类上
  3. 约束参照兄弟view,约束添加到共同父类上 image.png

代码创建约束

@interface ViewControler ()
@end

@implementation ViewContraler 

    - (void) viewDidLoad {
        [super viewDidLoad];
        // 1. 创建蓝色View
        UIView *blueView = [[UIView alloc] init];
        blueView.backgroundColor = [UIColor blueColor];
        //blueView.frame = CGRectMake(0,0,100,100);
        [self.view addSubview:blueView];
        
        // 2. 创建红色View
        UIView *redView = [[UIView alloc] init];
        redView.backgroundColor = [UIColor redColor];
        //redView.frame = CGRectMake(100,100,100,100);
        [self.view addSubview:redView];
        
        // 3. 禁止autoresizing
        blueView.translatesAutoresizingMaskIntoConstraints = NO;
        redView.translatesAutoresizingMaskIntoConstraints = NO;
        
        // 4. 添加约束
        // 4.1 创建 blueView 的约束
        // 4.1.1 blueView 高度约束为50:A对象 某属性 怎样 B对象 魔属性 乘以 multipler 加上 constant
        NSLayoutConstraint *blueViewH = [NSLayoutConstrain 
            constraintWithItem:blueView attribute:NSLayoutAttributeHeight // blueView 高度
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:nil attribute:NSLayoutAttributeNOtAnAttribute // 没有参照对象和属性
            multiplier:1.0 // 乘以 multiplier
            constant:50 // 加上 constant
        ];
        [blueView addConstraint:blueViewH]; // 添加约束到 blueView
        
        // 4.1.2 blueView 距离父控件左边30
        NSLayoutConstraint *blueViewLeft = [NSLayoutConstrain 
            constraintWithItem:blueView attribute:NSLayoutAttributeLeft // blueView 左边
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView.superview attribute:NSLayoutAttributeLeft // 父类 左边
            multiplier:1.0 // 乘以 multiplier
            constant:30 // 加上 constant
        ];
        [blueView.superview addConstraint:blueViewH]; // 添加约束到 blueView 父类
        
        // 4.1.2 blueView 距离父控件上边30
        NSLayoutConstraint *blueViewTop = [NSLayoutConstrain 
            constraintWithItem:blueView attribute:NSLayoutAttributeTop // blueView 上边
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView.superview attribute:NSLayoutAttributeTop // 父类 上边
            multiplier:1.0 // 乘以 multiplier
            constant:30 // 加上 constant
        ];
        [blueView.superview addConstraint:blueViewTop]; // 添加约束到 blueView 父类
        
        // 4.1.2 blueView 距离父控件右边30
        NSLayoutConstraint *blueViewLeft = [NSLayoutConstrain 
            constraintWithItem:blueView attribute:NSLayoutAttributeRight // blueView 右边
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView.superview attribute:NSLayoutAttributeRight // 父类 右边
            multiplier:1.0 // 乘以 multiplier
            constant:-30 // 加上 constant
        ];
        [blueView.superview addConstraint:blueViewLeft]; // 添加约束到 blueView 父类
        
        // 4.2 创建 redView 的约束
        // 4.2.1 redView 高度约束为50:A对象 某属性 怎样 B对象 魔属性 乘以 multipler 加上 constant
        NSLayoutConstraint *redViewH = [NSLayoutConstrain 
            constraintWithItem:redView attribute:NSLayoutAttributeHeight // redView 高度
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView attribute:NSLayoutAttributeHeight // blueView 高度
            multiplier:1.0 // 乘以 multiplier
            constant:0 // 加上 constant
        ];
        [redView.superview addConstraint:redViewH]; // 添加约束到 redView 父类
        
        // 4.1.2 redView 距离 blueView 底部30
        NSLayoutConstraint *redViewTop = [NSLayoutConstrain 
            constraintWithItem:blueView attribute:NSLayoutAttributeTop // redView 上边
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView.superview attribute:NSLayoutAttributeBottom // blueView 底部
            multiplier:1.0 // 乘以 multiplier
            constant:30 // 加上 constant
        ];
        [blueView.superview addConstraint:redViewTop]; // 添加约束到 redView 父类
        
        // 4.2.3 redView 相对于 blueView 右边对齐
        NSLayoutConstraint *redViewRight = [NSLayoutConstrain 
            constraintWithItem:redView attribute:NSLayoutAttributeRight // redView 右边
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView attribute:NSLayoutAttributeRight // blueView 右边
            multiplier:1.0 // 乘以 multiplier
            constant:0 // 加上 constant
        ];
        [redView.superview addConstraint:redViewRight]; // 添加约束到 redView 父类
        
        // 4.2.3 redView 宽度相当于 blueView 宽度 一半
        NSLayoutConstraint *redViewW = [NSLayoutConstrain 
            constraintWithItem:redView attribute:NSLayoutAttributeWidth // redView 宽度
            relatedBy:NSLayoutRelationEqual // 等于
            toItem:blueView attribute:NSLayoutAttributeRight // blueView 宽度
            multiplier:0.5 // 乘以 multiplier
            constant:0 // 加上 constant
        ];
        [redView.superview addConstraint:redViewW]; // 添加约束到 redView 父类
        
        // self.topLayoutGuide // 状态栏
    }

@end

image.png

通过autolayout实现动画

@interface ViewController ()
    @property(weak, nonatomic) IBOutlet UIButton *button;
    // button 距离父控件顶部约束
    @property(weak, nonatomic) IBOutlet NSLayoutConstraint *buttonTopConstraint;
@end

@implementation ViewController

    -(void) move {
        buttonTopConstraint.constant += 100;
        [UIView animateWithDuration:1.5 animations:^{
            [self.button layoutIfNeeded]; // 要调用这句动画才生效
        }];
    }

@end