UI学习--布局子视图


布局子视图

当我们想让子视图随着父视图的变化跟着变化时,我们需要选择使用手动布局子视图或者自动布局子视图两个方法之一。

手动布局子视图

先来学习手动布局子视图。
首先,我们先创建一个父视图superView,

在这里插入图片描述
然后在ViewController中,实现两个内容:

  1. 创建一个父视图
  2. 创建两个按钮,控制视图放大缩小。

我们使用UIView的 animateWithDuration: animations:方法来制作控制视图放大缩小的效果,该方法传入两个参数

  1. duration(持续时间):这是动画的持续时间,以秒为单位。它指定了从动画开始到动画结束所经过的时间。在指定的持续时间内,UIKit 框架会根据动画块中的属性更改逐渐过渡到新的属性值。

  2. animations(动画块):使用代码块更视图属性。在这个代码块中,可以修改视图的位置、大小、透明度等属性,UIKit 框架会在指定的持续时间内,根据动画块中的属性更改逐渐过渡到新的属性值。


#import "ViewController.h"
#import "SuperView.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //创建父视图
    SuperView *sView = [[SuperView alloc] init];
    
    sView.frame = CGRectMake(20, 50, 180, 280);
    
    sView.backgroundColor = [UIColor orangeColor];
    
    //将父视图添加到主视图中
    [self.view addSubview:sView];
    
    //创建两个按钮控制放大缩小
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btn.frame = CGRectMake(240, 580, 80, 40);
    [btn setTitle:@"放大" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(pressLarge) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    UIButton *btn02 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btn02.frame = CGRectMake(240, 620, 80, 40);
    [btn02 setTitle:@"缩小" forState:UIControlStateNormal];
    [btn02 addTarget:self action:@selector(pressSmall) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn02];
    
    sView.tag = 101;
    
    [sView creatSubViews];
}

- (void) pressLarge {
    //放大父亲视图动画
    SuperView *sView = (SuperView*)[self.view viewWithTag: 101];
    [UIView animateWithDuration:1.0 animations:^{
        sView.frame = CGRectMake(20, 50, 300, 480);
    }];
}
 
//缩小父亲视图
- (void) pressSmall {
    SuperView *sView = (SuperView*)[self.view viewWithTag: 101];
    [UIView animateWithDuration: 1.0 animations: ^{
        sView.frame = CGRectMake(20, 50, 180, 280);
    }];
}
@end

然后在父视图中接口文件中定义四个子视图属性,和创建子视图的方法。

//superView.h文件
#import <UIKit/UIKit.h>

@interface SuperView : UIView
{
    UIView *_view01;
    UIView *_view02;
    UIView *_view03;
    UIView *_view04;
}
-(void) creatSubViews;
@end

然后我们在实现文件中创建这四个子视图,并且手动布局子视图随着父视图的变化而改变。
注意的是,从iOS13.0起,弃用了beginAnimations: context:的方法,而改用基于代码块的动画实现这一功能。但是两者依旧都能运行,此处给出了两种方法的代码。我们还运用了-(void) layoutSubviews方法:

  • layoutSubviews : UIView 类中的一个方法,它在视图需要重新布局其子视图时被调用。在视图层次结构发生变化或视图的大小发生改变时,系统会自动调用 layoutSubviews 方法,以便进行子视图的重新布局。

#import "SuperView.h"

@implementation SuperView
-(void) creatSubViews
{
    _view01 = [[UIView alloc] init];
    _view01.frame = CGRectMake(0, 0, 40, 40);
    
    _view02 = [[UIView alloc] init];
    _view02.frame = CGRectMake(self.bounds.size.width - 40, 0, 40, 40);
    
    _view03 = [[UIView alloc] init];
    _view03.frame = CGRectMake(self.bounds.size.width - 40, self.bounds.size.height-40, 40, 40);
    
    _view04 = [[UIView alloc] init];
    _view04.frame = CGRectMake(0, self.bounds.size.height - 40, 40, 40);
    
    _view01.backgroundColor = [UIColor blueColor];
    _view02.backgroundColor = [UIColor blueColor];
    _view03.backgroundColor = [UIColor blueColor];
    _view04.backgroundColor = [UIColor blueColor];
    
    [self addSubview:_view01];
    [self addSubview:_view02];
    [self addSubview:_view03];
    [self addSubview:_view04];
}
//当需要重新布局时调用此函数
//通过次函数重新设定子视图的位置
//手动调整子视图的位置
-(void) layoutSubviews
{
//    [UIView beginAnimations:nil context:nil];
//    [UIView setAnimationDuration:1];
//    _view01.frame = CGRectMake(0, 0, 40, 40);
//    _view02.frame = CGRectMake(self.bounds.size.width - 40, 0, 40, 40);
//    _view03.frame = CGRectMake(self.bounds.size.width - 40, self.bounds.size.height-40, 40, 40);
//    _view04.frame = CGRectMake(0, self.bounds.size.height - 40, 40, 40);
//    
    
    //新版
    [UIView animateWithDuration: 1.0 animations:^ {
        self->_view01.frame = CGRectMake(0, 0, 40, 40);
        self->_view02.frame = CGRectMake(self.bounds.size.width - 40, 0, 40, 40);
        self->_view03.frame = CGRectMake(self.bounds.size.width - 40, self.bounds.size.height - 40, 40, 40);
        self->_view04.frame = CGRectMake(0, self.bounds.size.height - 40, 40, 40);
        }];
}
@end

效果(放大前):
在这里插入图片描述
放大后:
在这里插入图片描述

自动布局子视图

手动布局子视图需要我们自己手动调整子视图的原点位置,我们还可以自动控制子视图对齐。
需要注意:我们在viewController视图控制器中创建四个UILabel控件子视图,便于区别。

首先,我们在接口部分定义属性

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
    //创建父亲视图对象
    UIView *superView;
    //创建四个标签
    UILabel *label1;
    
    UILabel *label2;
    
    UILabel *label3;
    
    UILabel *label4;
    
    UIView *viewCenter;
}

@end

在实现部分中,我们首先创建接口部分中的六个视图。
再通过- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法,使用一个局部布尔变量储存当前屏幕状态,实现点击改变父视图大小。
再通过修改View的autoresizingMask自动调整布局属性,实现自动布局子视图。


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    superView = [[UIView alloc] init];
    superView.frame = CGRectMake(20, 20, 180, 280);
    superView.backgroundColor = [UIColor blueColor];
    
    label1 = [[UILabel alloc] init];
    label1.text = @"1";
    label1.frame = CGRectMake(0, 0, 40, 40);    label1.backgroundColor = [UIColor greenColor];
    
    label2 = [[UILabel alloc] init];
    label2.frame = CGRectMake(180 - 40, 0, 40, 40);
    label2.text = @"2";
    label2.backgroundColor = [UIColor   greenColor];
    
    label3 = [[UILabel  alloc] init];
    label3.frame = CGRectMake(180-40, 280-40, 40, 40);
    label3.text = @"3";
    label3.backgroundColor = [UIColor greenColor];
    
    label4 = [[UILabel alloc] init];
    label4.frame = CGRectMake(0, 280-40, 40, 40);
    label4.text = @"4";
    label4.backgroundColor = [UIColor greenColor];
    
    [superView addSubview:label1];
    [superView addSubview:label2];
    [superView addSubview:label3];
    [superView addSubview:label4];
    
    [self.view addSubview:superView];
    
    viewCenter = [[UIView alloc] init];
    viewCenter.frame = CGRectMake(0, 0, superView.bounds.size.width, 40);
    viewCenter.center = CGPointMake(180/2, 280/2);
    viewCenter.backgroundColor = [UIColor orangeColor];
    
    [superView addSubview:viewCenter];
    
    //自动布局属性设置,通过此变量来调整视图再父亲视图中的位置和大小
    //视图距离父亲视图的左侧是可以变化的
    label2.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
    
    label4.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    //左上可变,则实现移动到右下角
    label3.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
	//上下都可变,即可实现居中效果
    viewCenter.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
    
    
    //语句会覆盖
    //viewCenter.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    
}

- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //用一个局部变量来区分视图的大小的状态
    static BOOL isLarge = NO;
    //设置动画效果
    [UIView animateWithDuration: 1.0 animations:^{
        if (isLarge == NO) {
            self->superView.frame = CGRectMake(10, 10, 350, 580);
        } else {
            self->superView.frame = CGRectMake(20, 20, 180, 280);
        }
        isLarge = !isLarge;
    }];
}


@end

效果(放大前):
在这里插入图片描述
放大后:
在这里插入图片描述

总结

我们以一个问题来总结:为什么手动布局子视图在父视图的文件中创建子视图,而自动布局子视图在视图控制器中创建子视图呢?
这两种不同的布局方式,在视图的管理和实现上也有不同。因此他们的位置是不同的。

  • 手动布局:通过直接设置视图的 frame 属性或使用类似的布局方法来手动计算和设置子视图的位置和大小。在这种情况下,布局的逻辑通常集中在父视图中,因为父视图更了解自己的布局需求和子视图的相对关系。因此,在手动布局中,在父视图中的 layoutSubviews 方法中进行子视图的布局计算和设置。
  • 自动布局:使用 Auto Layout 技术进行视图布局的一种方式,它通过使用约束来描述和管理视图之间的关系。在自动布局中,视图的布局逻辑通常由视图的父视图的视图控制器来管理。视图控制器负责设置视图之间的约束关系,以及处理视图的自动布局。因此,在自动布局中,视图控制器通常会在适当的方法中(如 viewDidLoad 或 viewWillAppear:)设置视图之间的约束关系,从而实现自动布局。
  • 38
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值