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.15(1242x2208->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));
- QMUI / QMUI_iOS框架学习(五)
- QMUI / QMUI_iOS框架学习(一)
- QMUI / QMUI_iOS框架学习(二)
- QMUI / QMUI_iOS框架学习(三)
- QMUI / QMUI_iOS框架学习(四)
- QMUI / QMUI_iOS框架学习(六)
- QMUI Android UI 框架正式发布
- Mina框架学习笔记(五)
- Mina框架学习笔记(五)
- SSH框架学习(五、加入log4j)
- spring框架学习(五)注解
- spring框架学习(五)注解
- Mina框架学习笔记(五)
- spring框架学习(五)注解
- Mybatis基础框架学习(五)
- spring框架学习(五)注解
- spring框架学习(五)注解
- spring框架学习(五)注解
- 解决mariadb数据库服务无法开启
- BeautifulSoup安装以及一些错误
- jvm运行机制
- Andriod Service与Thread的区别
- 使用 Mockito 修改私有属性
- QMUI / QMUI_iOS框架学习(五)
- 菜鸟之路
- 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)
- SEO学习笔记
- Android Service 前台
- ListView的简单使用
- java开发面试题
- 让CoreData更简单些
- 第三方很好的Toast