首页 > 其他分享 >UI学习--布局子视图

UI学习--布局子视图

时间:2024-06-06 18:00:39浏览次数:8  
标签:-- self CGRectMake 40 UI 视图 frame UIView

布局子视图


布局子视图

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

手动布局子视图

先来学习手动布局子视图。
首先,我们先创建一个父视图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:)设置视图之间的约束关系,从而实现自动布局。

标签:--,self,CGRectMake,40,UI,视图,frame,UIView
From: https://blog.csdn.net/2301_80253909/article/details/139499119

相关文章

  • 开源低代码平台技术为数字化转型赋能!
    实现数字化转型升级是很多企业未来的发展趋势,也是企业获得更多发展商机的途径。如何进行数字化转型?如何实现流程化办公?这些都是摆在客户面前的实际问题,借助于开源低代码平台技术的优势特点,可以轻松助力企业降低开发成本、提高开发效率,获得高效快速发展。了解低代码技术平台的客户......
  • 新质生产力赋能公司治理,以数字化引领董事会管理效率
    什么是新质生产力?新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级而催生的当代先进生产力,它以劳动者、劳动资料、劳动对象及其优化组合的质变为基本内涵,以全要素生产率提升为核心标志。新质生产力、数字化与公司治理近日,深圳证券交易所、上海证券交易......
  • C# 使用Newtonsoft.Json的JsonProperty设置返回的Json数据列名/C# 通过实体类序列化生
    原文链接:https://blog.csdn.net/weixin_44917045/article/details/103236167         https://blog.csdn.net/bazinga_y/article/details/134416680在写分页的时候,返回Json数据给前台的时候,数据不能出来,原因就是Json数据的列名是大写的,而页面需要的是小写的。......
  • Web攻防:SQL注入 - 前置知识
    SQL注入-前置知识1.注入原理1.1.什么是SQL注入1.2.SQL注入产生的条件2.系统函数2.1.version()-MySQL版本2.2.user()-数据库用户名2.3.database()-数据库名2.4.@@datadir-数据库路径2.5.@@version_compile_os-操作系统版本3.字符串连接函数3.1.C......
  • AI绘画中的色彩空间转换技术
    在数字艺术的广阔天地中,AI绘画作为一种新兴的创作方式,正以其独特的魅力吸引着越来越多的关注。它不仅仅是一种技术,更是一种全新的艺术表现形式。而在AI绘画的背后,色彩空间转换技术起着至关重要的作用。今天,我们就来深入探讨一下这个神奇的技术。首先,我们需要了解什么是色彩......
  • vue+java实现大文件上传解决方案
    分片上传大文件Demo为了实现分片上传,包括断点续传和重试机制,我们可以使用Vue.js作为前端,SpringBoot作为后端。这个方案包括以下步骤:前端:使用Vue.js进行文件分片上传。管理分片上传的进度和状态,处理断点续传和重试。后端:使用SpringBoot处理分片上传的请求。存储上......
  • C语言杂谈:函数栈帧,函数调用时到底发生了什么
            我们都知道在调用函数时,要为函数在栈上开辟空间,函数后续内容都会在栈帧空间中保存,如非静态局部变量,返回值等。这段空间就叫栈帧。    当函数调用,就会开辟栈帧空间,函数返回时,栈帧空间就会被释放。这里的释放并非清空,而是让其无效化,可以后续的使用。1,......
  • 镜头效果技术在AI绘画中的革新作用
    随着人工智能技术的飞速发展,AI绘画已经成为艺术与科技交汇的前沿领域。在这一领域中,镜头效果技术的应用不仅为艺术家和设计师们提供了全新的创作工具,更在艺术创作中扮演了革命性的角色。本文将深入探讨镜头效果技术在AI绘画中的应用,以及它如何改变我们对艺术创作的认识和实......
  • 算法课程笔记——并查集基础
    算法课程笔记——并查集基础......
  • json.dumps 用法
    在Python中,json.dumps()函数是将Python对象转换为JSON格式的字符串的方法。下面是json.dumps()函数的基本用法:importjson#定义一个Python字典对象data={"name":"John","age":30,"city":"NewYork"}#将Python字典转换为JSO......