iOS开发之--屏幕适配相关小结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq136501564/article/details/51953456

屏幕适配小结

纯手动之Autolayout

1、VFL语言添加约束

  • VFL(Visual format language)语言是苹果为了简化手写Autolayout代码所创建的专门负责编写约束的代码。为我们简化了许多代码量。

2、使用步骤

使用步骤同手动添加约束保持一致

  • 创建控件
  • 添加到父控件
  • 禁用Aoturesizing
  • 添加约束

3、使用方法

  • 这里先展示一个实例:
	NSArray *blueHArr = [NSLayoutConstraint constraintsWithVisualFormat:
	@"H:|-20-[blueView]-20-|" 
	options:kNilOptions
 	metrics:nil views:
	NSDictionaryOfVariableBindings(blueView)];

	方法介绍:
	constraintsWithVisualFormat:这个方法返回了一个数组;
	   @"H:|-20-[blueView(100)]-20-|":这句话表明所添加的约束,H的意思是水平方向添加约束,blueView 视图名称,(100)代表着blueView 的宽 
        为100blueView距离父类的左边20,距离父类的右边是20;
	options:是对其方式;
           metrics:返回的是一个字典,它的意思是可以将约束中的值用某些字符串来代理,然后在这个字典中给多对应的字符串赋值
           方便修改,并且增加可读性;
           views:返回的也是一个字典,这个字典的意思是:你可以将前面的view用其他字符串来代替,在这里在给他赋给对应的vie 
           w的名字。
        我可以将上面的约束语句改成如下这样:

		NSArray *blueHArr = [NSLayoutConstraint 
		constraintsWithVisualFormat:@"H:|-aa-[cccc(100)]-20-|"
		options:kNilOptions
        	metrics:@{@"aa":@20}
		views:@{@"cccc":blueView}];
  • 
    
    这里我用aa替换了20,cccc替换了blueVuew
    这里有一个简单的方法,就是使用NSDictionaryOfVariableBindings(blueView)来替换views中的内容也是可以的。

4、VFL的缺点

  • VFL语句不支持乘除法
  • 比如我想表示redview是blueview高度的一半,
    我们是不能这样写的:
    NSArray *redVArr = [NSLayoutConstraint 
    constraintsWithVisualFormat:@"V:[blueView]-20-[redView(==blueView*0.5)]" 
    options:NSLayoutFormatAlignAllRight 
    metrics:nil 
    views:NSDictionaryOfVariableBindings(blueView, redView)];
    原因就是这里包含了乘法,而一旦VFL语句中包含了乘除法那么系统就会不识别而崩溃。
  • 所以,当一涉及到乘除法的时候,我们又不得不再次使用系统原来的方法中来:
    NSLayoutConstraint *redWidth = [NSLayoutConstraint 
    constraintWithItem:redView 
    attribute:NSLayoutAttributeWidth 
    relatedBy:NSLayoutRelationEqual
    toItem:blueView 
    attribute:NSLayoutAttributeWidth
    multiplier:0.5
    constant:0.0];

5、关于Autolayout还有一个叫Masonry的框架


Masonry 源码:https://github.com/Masonry/Masonry

Masonry是一个轻量级的布局框架 拥有自己的描述语法 采用更优雅的链式语法封装自动布局 简洁明了 并具有高可读性 而且同时支持 iOS 和Max OS X。

我们先来看一段官方的sample code来认识一下Masonry

	[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
   	 make.edges.equalTo(superview).with.insets(padding);}];

看到block里面的那句话: make edges equalTo superview with insets

通过链式的自然语言 就把view1给autolayout好了。

Masonry是目前最流行的AutoLayout框架.

  • 使用:将Masonry文件包拖入项目,删掉自带的info.plist文件.demo中对Masonry的引用在.pch文件中.

  • 使用Masonry不需要设置
    控件的translatesAutoresizingMaskIntoConstraints属性为NO;

Masonry简单实现

(左下角正方形):
	[targetView mas_makeConstraints:^(MASConstraintMaker *make) {
        	make.bottom.equalTo(self.view).offset(-20);
        	make.leading.equalTo(self.view).offset(20);
        	make.size.mas_equalTo(CGSizeMake(100, 100));
	}];
内边距为50:
  • 第一种实现方式
    make.leading.top.mas_equalTo(@50);
    make.trailing.bottom.mas_equalTo(@-50);
  • 第二种实现方式
    make.edges.insets(UIEdgeInsetsMake(50, 50, 50, 50));

Masonry使用技巧:

定义以下两个宏,在使用Masonry框架时就不需要加mas_前缀了
(定义宏一定要在引入Masonry.h文件之前).

	//define this constant if you want to use Masonry without the 'mas_' prefix
	#define MAS_SHORTHAND
	//define this constant if you want to enable auto-boxing for default syntax
	#define MAS_SHORTHAND_GLOBALS

使用Masonry添加兄弟控件约束不需要考虑父控件.

具体实现代码如下:

	[leftView mas_makeConstraints:^(MASConstraintMaker *make) {
        	make.leading.offset(20);
        	make.bottom.offset(-20);
        	make.trailing.equalTo(rightiew.leading).offset(-20);
        	make.height.equalTo(100);
        	make.height.equalTo(rightiew.height);
    	}];    
	[rightiew makeConstraints:^(MASConstraintMaker *make) {
        	make.trailing.equalTo(self.view.trailing).offset(-20);
        	make.top.equalTo(leftView.top);
        	make.width.equalTo(leftView.width);
	}];



xib(storyboard)进行约束

如题,利用xib文件为控件添加约束,storyboard方法一样,大家都懂得,之前的Xcode只有xib没有storyboard,storyboard当然会和xib方法一样了,使用xib的时候(记住不要勾选Use Autolayout  )下面切入正题,如何用xib为控件添加约束。


1.添加约束主要用到下面的三个部分:

屏幕快照 2015-06-05 下午10.18.33

从左到右:align、pin、resolve auto layout issues。单词的意思可能有同学不是很理解,不担心,不懂就点开试一下,是什么,一试便知。

    (1)、align

屏幕快照 2015-06-05 下午10.22.58

第一个模块主要是对齐的,那么对齐就要多个控件对齐,譬如:两个字空间左对齐、下对齐、X轴对齐、字控价和父控件中心对齐等,使用align主要是考虑多个控价对齐问题。

   (2)、pin

屏幕快照 2015-06-05 下午10.23.25

第二个模块主要是单个控件的属性,控件在父控件中的位置,控件的宽高等,主要是针对一个控件而言的。

   (3)、resolve auto layout issues

屏幕快照 2015-06-05 下午10.23.38

第三个模块主要是对约束进行编辑的,包括删除,添加,重置约束等。

2.添加约束的几个规则:

情况1:约束控件距离父控件的四周的距离。

屏幕快照 2015-06-05 下午11.17.12

第一种比较简单,也比较好理解,一个控件的上下左右的距离都控制好了,控件也就控制好了,如果你切换不同的屏幕时,控件距离屏幕边框的距离不变,会改变控件的大小。

屏幕快照 2015-06-05 下午11.24.42

xib中还是正方形的,但是当iPhone的屏幕上,变形了。

此处大家注意一个点,如果你是一个普通控件,像button,image view(已添加图片),label等,这些控件,当我们只给他添加三个约束时,软件不会报错,这是因为控件中有内容,软件会自适应大小,会根据内容的大小来改变控件的大小,这样虽然没有报错,但是控件的大小已经不是我们想要的大小了。。。但是对于一个view来说,你只给他控制三个边,软件会报错的,软件不知道最后一条边距离父控件多远,所以他会报错。所以,要想准确控制一个控件,就要确保确定的大小或者XY值。

情况2:控制控件相邻的两条边距离父控件的距离和控件的宽高。

屏幕快照 2015-06-05 下午11.17.20

控制控件相邻的两条边距离,也就控制了控件的左上角的(x,y),控制控件的宽高,也就控制了控件的右下角的(x,y),这样就能控制控件了。

 

情况3:控件XY轴居中,固定控件宽高。

屏幕快照 2015-06-05 下午11.39.43

如果只控件XY轴居中,还是那句话,一般控件像button,image view(已添加图片),label等,软件不会报错,并会自适应大小,但是大小会改变,对于view就会报错,软件给不出控件的大小。

情况4:控件X或Y居中,另一个方向的边距离父控件的距离,宽高。

屏幕快照 2015-06-05 下午11.49.24

 

 

建议:建议大家在写demo的时候用view,如果用其他的控件,可能会有些问题不报错,但是用view就会暴露出来。

关于xib(storyboard)的适配详细的可以参考下篇博客:

http://justsee.iteye.com/blog/2148987


像素适配

以上说的两点都是屏幕大小适配,也就是我们常说的屏幕自适应仅仅只是坐标和大小的适配,避免出现严重的bug和控件溢出等现象,现在要谈的便是像素适配,也就是根据用户所用的机型信息判断出是什么设备,从而提供相应的@xx图片。

目前在iPhone的阵营中,iphone4~6s图片均采用@2x,只有6 plus&6s plus采用@3x。所以可以进行机型的判断从而使用正确的图片。

三种常用的办法获取iOS设备的型号:

1. [UIDevice currentDevice].model (推荐)

2. uname(struct utsname *name) ,使用此函数需要#include 

3.sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,

         size_t newlen) ,使用此函数需要#include ,#include;


推荐使用第一种方法,为最上层的API,在项目开发中推荐使用高级的API ,因为其识别度高,更简洁易用。2、3两种都是BSD级别的API ,为底层的API,不推荐。


示例:

1. NSString * strModel  = [UIDevice currentDevice].model 


2. struct utsname systemInfo 

     uname(&systemInfo) 

    NSString * strModel = [NSString stringWithCString:systemInfo.machine

                                                                             encoding:NSUTF8StringEncoding];

3. size_t size 

     sysctlbyname ("hw.machine" , NULL , &size ,NULL ,0)

     char *model = (char *)malloc(size)

     sysctlbyname ("hw.machine" , model , &size ,NULL ,0)

     NSString * strModel = [NSString stringWithCString: model

                                                                             encoding:NSUTF8StringEncoding];


获取了设备型号之后,还不能准确的了解其设备类型,还需要找到与其型号对应的设备说明。

 该链接为各机型设备信息对应表 :   https://www.theiphonewiki.com/wiki/Models


此外,因为苹果现在的手机的长宽比并未改变依旧是16:9,所以我们可以在准备素材的时候,以点为单位,而不是像素。非矢量素材,就可以做尺寸最大的,之后再进行缩小。比如你需要兼容3x的屏幕,就直接做最高那种图片。因为之后几种机型长宽比都是9:16,可以直接拉伸。已有非矢量素材,直接拉伸放大到@3x。矢量图就直接做点那个尺寸。比如44 x 66个点的按钮。就建立一个44 x 66的场景。之后再导出成2倍图,3倍图,因为矢量放大不失真。不要建立一个3x的场景,导出成大图片,再进行缩小,这样就容易失真。

以下为这方面的资料可以参考一下


《iPhone屏幕适配,历史及现状》http://hjcapple.github.io/2014/10/10/iphone-screen.html
《APP设计师必读-快速适配iPhone6及plus的诀窍》http://www.ui.cn/project.php?id=25685
《iPhone6分辨率与适配》http://www.cocoachina.com/ios/20140912/9601.html


总结:

以后我们再开发的时候,要使用autolayout,减少frame的使用,这样更方便屏幕的适配,要尽量使用点这个单位进行思考,而不要使用像素。比如,你需要做44 x 66个点的按钮,2x模式,就乘以2, 3x模式就乘以3。这样的思考方式可以大致估计到真实的物理长度。44个点,就是手机上导航栏,工具栏的高度。假如用像素思考,容易使得做出的图片过大或者过小。假如是那种导航栏,工具栏之类的背景图,需要横跨整个屏幕。可以只切一小块,让程序拉伸,拉伸方式是保持两边的像素不动,只拉伸最中间的一列像素。需要拉伸的话,横方向就不要出现一些渐变色。





猜你喜欢

转载自blog.csdn.net/qq136501564/article/details/51953456