QMUI / QMUI_iOS框架学习(五)

来源:互联网 发布:社交网络的好处知乎 编辑:程序博客网 时间:2024/06/05 01:08

看源码的时候,发现了一个flat的用法,来返回一个新的cgfloat数值,为了弄懂为什么要这么做,我们来看一下

/** *  基于指定的倍数,对传进来的 floatValue 进行像素取整。若指定倍数为0,则表示以当前设备的屏幕倍数为准。 * *  例如传进来 “2.1”,在 2x 倍数下会返回 2.5(0.5pt 对应 1px),在 3x 倍数下会返回 2.333(0.333pt 对应 1px)。 */CG_INLINE CGFloatflatSpecificScale(CGFloat floatValue, CGFloat scale) {    scale = scale == 0 ? ScreenScale : scale;    CGFloat flattedValue = ceil(floatValue * scale) / scale;    return flattedValue;}

如果说苹果设备是固定ppi ,那就好计算了。。截了一份官网的ppi
,除了这个之外还有watch 设备等。。。拿这个去做适配得算死

这里写图片描述

苹果系统会假设你编程都是72dpi 。然后再自动适应,。

如果是这样 72pt = 72px , 1pt = 1px

这样你还是只用关心px,反正和pt是相等的,他设备会自己算,

后来出现了高分辨率屏幕,如果还按照px来做,为在不同像素密度的屏幕里面,像素本身大小是不一样的,会导致尺寸乱了。。。

dpi高了以后就出现了 1pt = 2px ,
1pt = 3px 就是我们平常用的@2x @3x图

然后就苹果设备会自己做适配。
所以你在运行时打印的pt 对应的px数值是根据你所运行的设备决定

说了这么多,现在可以开始尝试理解代码了。

运行期间到底是几倍呢?苹果有个函数

[[UIScreen mainScreen] scale];
1 pt = scale *  px

如果这个px 数值越多。就是说一个点上有更多的光栅方形格子
光栅格子是啥意思 参考这篇文章
就是我之前纠结的1pt 到底等于多少px 的数值参考文章

比如说4s scale 就是2 ,会使用@2x的图片, 6+就是3,会使用@3x的图片,

 iPhone6+在实际时,downsampling/1.151242x2208->1080x1920) , 苹果为方便开发者用的是@3x的素材,然后再缩放到@2.46x上。

因为ip6+实际物理像素比屏幕像素压缩了1.15倍。但是为了开发者方便还是只要提供@3x图就好了,苹果是会自己缩放的。

回到这个公式

ceil(floatValue * scale)/ scale

这个意思是向下取整,比如一个floatValue数值为24.3,在ip6+的屏幕上
scale = 3

floatValue * scale=72.900000000000006
ceil(72.900000000000006) = 73 (这个是实际屏幕的显示的大小)
73 /scale = 24.333333333333332 (这个是代码中应该写的数值,来保证屏幕实际大小是73)

为什么要保证屏幕尺寸取最小值呢,ceil 代表向下取整,是为了最大限度处理像素吧,不要出现<1的方格, px 放在pt里面就是一个pt 对应多少个px数值,
像素说到底是一个方格,0.00001个方格怎么放,就不好说了,因为普通意义上这个方格就是最小的点了,苹果系统应该会忽略他,至于怎么忽略,我们就不知道了。所以可以自己把方格数量取整,就不会出现像素有预想的偏移量了。

最后补充一下image 要用imageNamed初始化的原因

以下基于UIImage的两类初始化API简介高倍图的适配:同时该API根据UIScreen的scale,自动查找包含对应高倍图后缀名(@2x)的文件,如果找到二倍图,则image.scale=2.0,对应逻辑size大小以point度量(pixel度量的一半);如果没找到设置默认image.scale=1.0,对应逻辑size大小同像素尺寸。因此,使用该方法,无需特意指定高倍图后缀。在实际运行时,系统如果发现当前设备是Retina屏(scale=2),会自动寻找"*@2x.png"命名格式的图片,加载针对Retina屏的图片素材,否则会失真。

如果是label 记得添加了文字后 要用sizetoFit

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 110, 150)];label.backgroundColor = [UIColor orangeColor];[self.view addSubview:label];/* CGRectGetHeight返回label本身的高度 CGRectGetMinY返回label顶部的坐标 CGRectGetMaxY 返回label底部的坐标 CGRectGetMinX 返回label左边缘的坐标 CGRectGetMaxX 返回label右边缘的坐标 CGRectGetMidX表示得到一个frame中心点的X坐标 CGRectGetMidY表示得到一个frame中心点的Y坐标 */

这个是框架做的横屏适配,之后我也 会按照这种写法。

        //左边视图宽度 = 滚动视图宽度 / 2, 右边视图宽度 = 滚动视图宽度- 左边视图宽度;        CGFloat leftWidth = flat(CGRectGetWidth(self.scrollView.bounds) / 2);        CGFloat rightWidth = CGRectGetWidth(self.scrollView.bounds) - leftWidth;        //左边视图高度 = logo图高度 + label顶部距离 + label高度        CGFloat leftHeight = CGRectGetHeight(self.logoImageView.frame) + versionLabelMarginTop + CGRectGetHeight(self.versionLabel.frame);        //左边视图最小Y数值 = (滚动视图高度 - 导航栏的底部高度)- 左边视图高度 /2;来保证 左边视图全部居中        CGFloat leftMinY = CGFloatGetCenter(CGRectGetHeight(self.scrollView.bounds) - CGRectGetMaxY(self.navigationController.navigationBar.frame), leftHeight);        //logo图的frame =  logo图的rect  x =(左边视图宽度 -logo图宽度)/2  y = 最小y数值        self.logoImageView.frame = CGRectSetXY(self.logoImageView.frame, CGFloatGetCenter(leftWidth, CGRectGetWidth(self.logoImageView.frame)), leftMinY);        //版本label frame = 版本label的rect  x = 和logo图的水平居中的位置  y = logo图加上高度        self.versionLabel.frame = CGRectSetXY(self.versionLabel.frame, CGRectGetMinXHorizontallyCenter(self.logoImageView.frame, self.versionLabel.frame), CGRectGetMaxY(self.logoImageView.frame) + versionLabelMarginTop);        //右边内容宽度 = 右边视图宽度 - 左右两边的边距        CGFloat contentWidthInRight = rightWidth - UIEdgeInsetsGetHorizontalValue(padding);        //访问官网的frame  x = 左边宽度 + pading距离  y = logo图片的顶部 + 10 宽度 = 右边内容宽度 高度        self.websiteButton.frame = CGRectMake(leftWidth + padding.left, CGRectGetMinY(self.logoImageView.frame) + 10, contentWidthInRight, buttonHeight);        //功能列表的frame  rect 和访问官网一致   y 和访问官网底部一致        self.documentButton.frame = CGRectSetY(self.websiteButton.frame, CGRectGetMaxY(self.websiteButton.frame));        //同上        self.gitHubButton.frame = CGRectSetY(self.documentButton.frame, CGRectGetMaxY(self.documentButton.frame));        //copyRightLabel 的高度 = 自适应一下,传入宽度 右边内容宽度        CGFloat copyrightLabelHeight = [self.copyrightLabel sizeThatFits:CGSizeMake(contentWidthInRight, CGFLOAT_MAX)].height;        //copyRightLabel frame   x = 左边宽度 + pading距离   y = 滚动视图高度 - 导航条底部 - 底部底部边距 - 高度,        self.copyrightLabel.frame = CGRectFlatMake(leftWidth + padding.left, CGRectGetHeight(self.scrollView.bounds) - CGRectGetMaxY(self.navigationController.navigationBar.frame) - padding.bottom - copyrightLabelHeight, contentWidthInRight, copyrightLabelHeight);        //滚动视图内容区域 =  宽度 为 屏幕宽度     高度=屏幕高度 - 导航栏的高度        self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - CGRectGetMaxY(self.navigationController.navigationBar.frame));

这里写图片描述

0 0
原创粉丝点击