UIKit框架(8)屏幕适配(二)

  • AutoLayout介绍

AutoLayout的功能要比AutoResizing强大的多。

当对一个UIView对象使用了AutoLayout布局后,意味着放弃了通过对象的frame进行修改视图的位置、尺寸。

AutoLayout使约束条件,通过自动布局引擎,计算view对象的frame。

可以认为在AutoLayout中view对象的frame是一个只读的属性。

约束的核心公式:

view1.attr1 = (view2.attr2 * multiplier) + constraint

其中obj2可以是nil

除了=关系外,还可以是>= <=的关系

  • 代码适配

添加约束的步骤:

1)禁止被适配view的AutoResizing功能

- (BOOL)translatesAutoresizingMaskIntoConstraints
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag

2)创建约束对象NSLayoutConstraint

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

参数即约束的核心公式

NSLayoutRelation枚举:

enum {
   NSLayoutRelationLessThanOrEqual = -1,
   NSLayoutRelationEqual = 0,
   NSLayoutRelationGreaterThanOrEqual = 1,
};
typedef NSInteger NSLayoutRelation;

NSLayoutAttribute枚举:

typedef enum: NSInteger {
   NSLayoutAttributeLeft = 1,
   NSLayoutAttributeRight,
   NSLayoutAttributeTop,
   NSLayoutAttributeBottom,
   NSLayoutAttributeLeading,
   NSLayoutAttributeTrailing,
   NSLayoutAttributeWidth,
   NSLayoutAttributeHeight,
   NSLayoutAttributeCenterX,
   NSLayoutAttributeCenterY,
   NSLayoutAttributeBaseline,
   NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
   NSLayoutAttributeFirstBaseline,
   NSLayoutAttributeLeftMargin,
   NSLayoutAttributeRightMargin,
   NSLayoutAttributeTopMargin,
   NSLayoutAttributeBottomMargin,
   NSLayoutAttributeLeadingMargin,
   NSLayoutAttributeTrailingMargin,
   NSLayoutAttributeCenterXWithinMargins,
   NSLayoutAttributeCenterYWithinMargins,
   
   NSLayoutAttributeNotAnAttribute = 0} NSLayoutAttribute;

3)在UIView对象上添加约束对象

- (void)addConstraint:(NSLayoutConstraint *)constraint
- (void)addConstraints:(NSArray *)constraints

将约束添加到哪个view对象上应按照以下规则:

对于同级view之间的约束关系,添加到它们的父控件上

对于不同级view之间的约束关系,添加到最近的共同父控件上

对于有层级关系的两个view之间约束关系,添加到层次较高的的空间上

注意:约束不能重复添加,不能缺少必要的约束

添加约束的过程中非常容易出现无法计算出frame的情况

UIView的其他操作约束的方法:

- (NSArray *)constraints
- (void)removeConstraint:(NSLayoutConstraint *)constraint
- (void)removeConstraints:(NSArray *)constraints
  • AutoLayout的补充

AutoLayout的动画:

代码中如果修改了约束的数值,则执行下面的代码,就能产生相应的动画效果。

[UIView animateWithDuration:1.0 animations:^{
    [view layoutIfNeeded];
}];

哪个view中的约束变化了,哪个view对象调用layoutIfNeed方法

约束的变化应在动画之前完成。

UILabel、UIButton这类显示文字的控件使用AutoLayout的好处:

使用了恰当的约束,能够使其尺寸自动匹配。

如设置了UILabel对象的上、左、右的规定边距,则UILabel的尺寸会根据文字自动适应。

  • 约束的VFL方式

Visual Format Language,可视化格式语言,是苹果公司为了简化AutoLayout的编码而推出的抽象语言。

其实不能称之为“语言”,可以认为这仅仅是一种“语法”,其目的是减少代码使用AutoLayout的编程量

但实际减少的程度有限,有些约束的功能使用VFL也无法完成,但在实现一些简单约束时非常有效。

NSLayoutConstraint的另一个创建方法:

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

format参数:VFL语句

views参数:VFL中出现的对象“键值对”

metrics:占位符

返回一组约束对象

VFL语句示意:

如:

canelButton宽72,acceptButton宽50,它们之间间距12

 H:[cancelButton(72)]-12-[acceptButton(50)]

wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)

H:[wideView(>[email protected])]

竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox

 V:[redBox]-[yellowBox(==redBox)]

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

 H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
  • ZXPAutoLayout

号称最轻巧的自动布局,简化了NSLayoutConstraint的繁琐,采用新颖的链式语法,可扩展性强,维护成为低。

使用 zxp_addAutoLayout添加布局, 如:

[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {

}];


单个view的布局关系:

在superview中的内边距:

@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^edgeInsets)(UIEdgeInsets insets);

如:

[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
        //layout.topSpace(20);
        //layout.bottomSpace(30);
        //layout.leftSpace(40);
        //layout.rightSpace(50);
        layout.edgeInsets(UIEdgeInsetsMake(20, 30, 40, 50));
}];

居中操作:

@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^xCenterByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^yCenterByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^centerByView)(UIView *view,CGFloat value);

参数view应为superview

宽高操作:

@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^widthValue)(CGFloat value);
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^heightValue)(CGFloat value);

如:

[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
    layout.xCenterByView(self.view, 0);
    layout.yCenterByView(self.view, -100);
    layout.widthValue(100);
    layout.heightValue(100);
}];

两个view的布局关系:

//与另一个view的内边距相等
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^edgeEqualTo)(UIView *view);       
//当前的top距离view为value点坐标距离
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpaceByView)(UIView *view,CGFloat value); 
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpaceByView)(UIView *view,CGFloat value);
//当前top内边距值与view的相等
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpaceByView)(UIView *view,CGFloat value); 
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpaceByView)(UIView *view,CGFloat value);
//与view等宽
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^widthEqualTo)(UIView *view,CGFloat value); 
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^heightEqualTo)(UIView *view, CGFloat value);

如:

[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
    layout.xCenterByView(self.view, 0);
    layout.yCenterByView(self.view, -100);
    layout.widthValue(100);
    layout.heightValue(100);
}];
[self.blueView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
    layout.topSpaceByView(self.redView, 100);
    layout.heightEqualTo(self.redView, 0);
    layout.widthEqualTo(self.redView, 0);
    layout.leftSpaceEqualTo(self.redView, 0);
}];

自适应操作:(对UILabel有效)

@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoHeight)();
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoHeightByMin)(CGFloat value);
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoWidth)();
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoWidthByMin)(CGFloat value);

其他操作:

@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^priority)(UILayoutPriority priority); //优先级
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^multiplier)(CGFloat multiplier); //约束的倍数

如:

[self.blueView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
    layout.topSpaceByView(self.redView, 100);
    layout.heightEqualTo(self.redView, 0).multiplier(0.5);
    layout.widthEqualTo(self.redView, 0);
    layout.leftSpaceEqualTo(self.redView, 0);
}];
时间: 2024-08-06 07:29:51

UIKit框架(8)屏幕适配(二)的相关文章

Android下屏幕适配&lt;二&gt;

Android下屏幕适配: 适配:即当前应用在不同的手机上面显示相同的效果.适配前需要首先确定当前手机所属像素密度类型(如:xhdpi.hdpi.mdpi等),以下已华为G700.模拟器为例,计算其像素密度. 案例一: 手机型号:G700 手机分辨率:1280*720 (注:手机两个直角边上分别放置了1280及720个像素点) 手机尺寸大小:5英寸(手机对角线长度) 假设a,b分别为两个直角边,c为斜边,由勾股定理可得出计算方式:sqrt(a*a+b*b)/c 计算结果:sqrt(1280*12

[iOS开发]屏幕适配二:Xcode7使用Autolayout拖拽布局基础(1)

参照自动布局教程一我们在Xcode7中来实现一下这个界面(由于教程是较早的Xcode版本所以来重做一遍)Xcode7中已经没有了pin这个选项了. 设计图如下: 实现步骤一:在Stroyboard上拖拽三个view并用不同的颜色表示,将他们修改到与设计图相似的大小效果图如下 实现步骤二:通过观察设计图可以发现三个view等高,上半部分两个view等宽,按住command单击选中三个view,使用autolayout约束为等高,同样选中上部两个view约束为等宽,实现过程如下: 同样的方式来处理上

iOS屏幕适配的几种方式

屏幕适配问题共有四种解决方案:(1)根据屏幕宽高写控件frame(下策);(2)Autoresizing的使用(中策);(3)AutoLayout的使用(上策);(4)sizeClasses+AutoLayout的使用(上上策).下面将会分别来进行叙述. (1)根据屏幕宽高写控件frame 利用宽高比,在不同的屏幕中来进行对控件的位置与控件的宽高进行等比例缩放.选定一个型号的屏幕的宽高为基准,进行等比例缩放.例如以iPhone6或者iPhone6s为基准. 其宽高分别是375与667.Iphon

UIKit框架(8)屏幕适配(一)

本篇本章介绍iOS开发中经常使用的几种屏幕适配方式,包括: 通过frame进行适配 通过AutoResizing进行适配 使用AutoLayout进行适配 使用ZXPAutoLayout进行适配 ... 这里面最重要的是:通过frame适配以及AutoLayout 屏幕适配的目的 目的一: 不同型号的iPhone和iPad可能拥有不同大小的屏幕(点坐标系不同) 发布一款App时,不能只针对一种规格的屏幕,应当在不同大小屏幕的设备都能够运行 目的二: iPhone支持三个方向的旋转,iPad支持四

Autolayout屏幕适配——代码实现(苹果公司 / VFL语言 / 第三方框架Masonry)

在讲解如何通过代码来实现屏幕适配前,先来了解一下,屏幕适配中用到的约束添加的规则. 在创建约束之后,需要将其添加到作用的view上 在添加时要注意目标view需要遵循以下规则: 1. 约束规则    1> 添加约束的规则(一) 对于两个同层级view之间的约束关系,添加到它们的父view上 2> 添加约束的规则(二) 对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上 3> 添加约束的规则(三) 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view

UIKit&#160;框架之UIView二

下面这些都是UIView一些基本的东西,具体的可以参考UIKit 框架之UIView一博客 一.自定义一个View // // MyView.m // UIView // // Created by cyw on 15-5-17. // Copyright (c) 2015年 cyw. All rights reserved. // #import "MyView.h" @implementation MyView - (id)initWithFrame:(CGRect)frame {

Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一),今天就来真正实践一下,让这两个方法大显神威来帮我们搞定图片的屏幕适配问题. 请尊重原创劳动成果,转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329,非允许请勿用于商业或盈利用途,违者必究. 使用ImageView会遇到

Android屏幕适配框架-(今日头条终极适配方案)

在Android开发中,屏幕适配是一个非常头痛的问题,因而为了去进行屏幕适配,作为程序员,是呕心沥血,历经磨难,哈哈 我们之前做屏幕适配一般都会用到一下两种方式: 第一种就是宽高限定符适配,什么是宽高限定符适配呢 ├── src/main│   ├── res│   ├── ├──values│   ├── ├──values-800x480│   ├── ├──values-860x540│   ├── ├──values-1024x600│   ├── ├──values-1024x768│

(二十四)屏幕适配的基本概念

1.屏幕大小 :物理屏幕的大小,看屏幕的对角线.分辨率 :实际上是像素的总和.1280*720dpi :密度.(每英寸所展示的像素)2.hdpi :放480*800分辨率的图片 ~240dpildpi :320*240 ~120dpimdpi : 320*480 ~160dpi (参照物)xhdpi: 1280*720 ~320dpi ldpi.mdpi.hdpi.xhdpi缩放比例l :m :h :x 3:4:6:8 3. 480*800 :小分辨率往大分辨率兼容,填充屏幕的时候,会拉伸,出现

034-iOS屏幕适配-iOS笔记

学习目标 1.[了解]屏幕适配的发展史 2.[了解]autoResizing基本用法 3.[掌握]autoLayout 的基本用法 4.[掌握]autoLayout代码实现 5.[理解]sizeClass的基本用法 一.屏幕适配的发展史 随着iOS屏幕尺寸越来越多样化,屏幕适配也就越来越重要了. iphone1 - iphone3gs时代,window的size固定为(320,480).我们只需要简单计算一下相对位置就好了,不需要做屏幕适配. iphone4 - iphone4s时代,苹果推出了