美文网首页
iOS-屏幕适配

iOS-屏幕适配

作者: Imkata | 来源:发表于2020-08-10 11:26 被阅读0次

一. 屏幕适配历史

  1. iphone3gs-4s
    frame直接写死。
  2. ipad:autoresizing
    根据父控件的frame发生改变,子控件跟着一起改变。
  3. iphone5-iPhone5s:autolayout
    自动布局(是针对xib进行使用的)。
  4. iPhone6和iphone6p:sizeClass
    发现屏幕变得太多样,界面大统一了(是针对storyboard进行使用的)。

更多关于屏幕适配可参考:
一篇文章详解iOS之AutoResizing、AutoLayout、sizeClass来龙去脉
iOS8中SizeClass的使用

二. AutoLayout

1. AutoLayout简介

在以前的iOS程序中,是如何设置布局UI界面的?

  • 经常编写大量的坐标计算代码
  • 为了保证在3.5 inch和4.0 inch屏幕上都能有完美的UI界面效果,有时还需要分别为两种屏幕编写不同的坐标计算代码(即传说中的“屏幕适配”)。

什么是Autolayout?

  • Autolayout是一种“自动布局”技术,专门用来布局UI界面的
  • Autolayout自iOS 6开始引入,由于Xcode 4的不给力,当时并没有得到很大推广
  • 自iOS 7(Xcode 5)开始,Autolayout的开发效率得到很大的提升
  • 苹果官方也推荐开发者尽量使用Autolayout来布局UI界面
  • Autolayout能很轻松地解决屏幕适配的问题

关于Autoresizing:

  • 在Autolayout之前,有Autoresizing可以作屏幕适配,但局限性较大,有些任务根本无法完成
  • 相比之下,Autolayout的功能比Autoresizing强大很多

Autolayout的2个核心概念:

  • 参照
  • 约束

2. Autolayout的警告和错误

  1. 警告:黄色向右的箭头
    控件的frame不匹配所添加的约束,比如约束控件的宽度为100,而控件现在的宽度是110。
  2. 错误:红色向右的箭头
    缺乏必要的约束,比如只约束了宽度和高度,没有约束具体的位置。
  3. 两个约束冲突黄色警告
    比如,1个约束控件的宽度为100,1个约束控件的宽度为110。

3. 约束添加的原则

在创建约束之后,需要将其添加到作用的view上,在添加时要注意目标view需要遵循以下规则:

  1. 对于两个同层级view之间的约束关系,添加到它们的父view上
原则1.png
  1. 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
原则2.png
  1. 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
原则3.png

三. VFL语言

什么是VFL语言?

  • VFL全称是Visual Format Language,翻译过来是“可视化格式语言”
  • VFL是苹果公司为了简化Autolayout的编码而推出的抽象语言

1. 代码实现Autolayout的步骤

  1. 利用NSLayoutConstraint类创建具体的约束对象
  2. 添加约束对象到相应的view上
- (void)addConstraint:(NSLayoutConstraint*)constraint;
- (void)addConstraints:(NSArray*)constraints;
  1. 代码实现Autolayout的注意点
    ① 要先禁止autoresizing功能,设置view的下面属性为NO。
    view.translatesAutoresizingMaskIntoConstraints=NO;
    ② 添加约束之前,一定要保证相关控件都已经在各自的父控件上。
  2. 不用再给view设置frame

2. NSLayoutConstraint类

一个NSLayoutConstraint对象就代表一个约束。

创建约束对象的常用方法:

// view1:要约束的控件
// attr1:约束的类型(做怎样的约束)
// relation:与参照控件之间的关系
// view2:参照的控件
// attr2:约束的类型(做怎样的约束)
// multiplier:乘数
// c:常量 
+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

3. VFL的使用

使用VFL来创建约束数组

// format:VFL语句
// opts:约束类型
// metrics:VFL语句中用到的具体数值
// views:VFL语句中用到的控件
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;

创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义NSDictionaryOfVariableBindings(...)

VFL示例:

// canelButton宽72,acceptButton宽50,它们之间间距12
H:[cancelButton(72)]-12-[acceptButton(50)]

// wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
H:[wideView(>=60@700)]

// 竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox
V:[redBox]-[yellowBox(==redBox)]

// 水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|”表示superview的边缘) 
H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|

4. VFL练习

练习①

//添加两个view蓝色在上.红色在下,红色的宽度是蓝色的一半
- (void)test1
{
    // 1.添加控件
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];
    
    // 2.VFL生成约束
    NSArray *conts = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:0 metrics:nil views:@{@"blueView" : blueView}];
    [self.view addConstraints:conts];
    
    //右对齐
    NSArray *conts2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[blueView(40)]-20-[redView(==blueView)]" options:NSLayoutFormatAlignAllRight metrics:nil views:@{@"blueView" : blueView, @"redView" : redView}];
    [self.view addConstraints:conts2];
    //设置红色的宽度是蓝色的一半,(设置一个view是另外一个view的多少倍的时候必须要用下面的方法)
    NSLayoutConstraint *redWidth = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];
    [self.view addConstraint:redWidth];
}

效果图如下:

练习1.png

练习②

//添加两个按钮,左边,右边,下边距离相等都是20
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 1.添加控件
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];
    
    // 2.VFL生成约束
    NSDictionary *mertrics = @{@"margin" : @20}; // 参数\数值
    NSDictionary *views = NSDictionaryOfVariableBindings(blueView, redView);//view
    NSArray *conts = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-margin-[blueView]-margin-[redView(==blueView)]-margin-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:mertrics views:views];
    //NSLayoutFormatAlignAllTop上对齐
    NSArray *conts2 = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[blueView(==blueHeight)]-margin-|" options:0 metrics:@{@"blueHeight" : @40, @"margin" : @20} views:views];
    //竖直方向高度相等
    [self.view addConstraints:conts];
    [self.view addConstraints:conts2];
}

效果图如下:

练习2.png

四. 补充

1. 自动包住文字内容

给label添加Autolayout之后,label的尺寸会根据里面的内容自动包裹文字,不会有空白,以前要算,现在不用算了

在没有Autolayout之前,UILabel的文字内容总是居中显示,导致顶部和底部会有一大片空白区域

没有Autolayout.png

有了Autolayout之后,UILabel的bounds默认会自动包住所有的文字内容,顶部和底部不再有空缺区域

有了Autolayout.png

2. 通过约束添加动画

storyboard里面的控件如下:

添加动画.png

代码如下:

//  MJViewController.m
 
#import "MJViewController.h"
 
@interface MJViewController ()
@property (weak, nonatomic) IBOutlet UILabel *textLabel;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftMargin;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *width;
@property (weak, nonatomic) IBOutlet UIView *redView;
 
@end
 
@implementation MJViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
}
 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    self.leftMargin.constant = 100;
    self.width.constant = 200;
    
    [UIView animateWithDuration:2.0 animations:^{
        [self.view layoutIfNeeded];
        [self.redView layoutIfNeeded];
    }];
    
    self.textLabel.text = @"sdhjkfhkjlsdhkjflhjdsflhjsdlhkjflhjdshjlfsdhjkfhkjlsdhkjflhjdsflhjsdlhkjflhjdshjlfsdhjkfhkjlsdhkjflhjdsflhjsdlhkjflhjdshjlfsdhjkfhkjlsdhkjflhjdsflhjsdlhkjflhjdshjlfsdhjkfhkjlsdhkjflhjdsflhjsdlhkjflhjdshjlf";
}
@end

相关文章

网友评论

      本文标题:iOS-屏幕适配

      本文链接:https://www.haomeiwen.com/subject/awmddktx.html