iOS】利用PureLayout实现:比例自动布局(AutoLayout)

2023-12-21 08:58

本文主要是介绍iOS】利用PureLayout实现:比例自动布局(AutoLayout),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

早在前两年还没有iPhone6(s)、iPhone6(s) plus出现的时候,在开发iOS的应用程序的时候感觉在布局上都完爆Android,因为虽然iPhone5与iPhone4的高度不一样,但是参照宽度(320px)都是一样的。
  但是在iPhone6(s)、iPhone6(s) plus出现后,iPhone的屏幕分辨率开始碎片化,但是使用iOS的AutoLayout好像也是屌屌的,完全能够针对屏幕大小进行相应的自动布局(相对布局)。
  但是眼尖的程序员可能会发现:在iPhone5上的控件如果设置了边距,字体大小等等,在iPhone6Plus上也是一样一样的,并没有像Android上会按照屏幕的分辨率比例缩放。这是因为在Android开发过程中并没有使用像素单位px,而是使用的pd为单位,而字体使用的sp为单位。

对比图.png
  这是iPhone6p与iPhone6的对比图,几乎肉眼可见(本人用测量工具侧量过),加入按钮高度是一样的。

  其实这样的布局也不会带来什么特别的困扰,只要设计师考虑了iOS布局的这个特性,设计得当,最后出来的效果无非是iPhone6p出来的效果空一些,而iPhone5出来的效果经凑一些。
  一直以来我也是按照这种设计模式开发自己的App。

  然而命运出现了转折……
  在新的一个项目中,设计师设计的图纸是在1242px的画布(参考的iPhone6p的尺寸)上设计的。按照iPhone6p的屏幕尺寸切图额和标注给我后,导致出来的结果是在iPhone6p上效果上佳,但是在iPhone5上就开始挤在一起,甚至出现了有些控件叠加在一起。
  这就是因为iOS开发布局后字体大小、间距、控件大小并不会按照屏幕的分辨率等比例缩放的结果。
  然后设计师又重新按照iPhone6的尺寸标注了一份新的设计图后,开发出来的结果也是并不理想,因为在iPhone6上表现上佳,但是iPhone5上紧了,在iPhone6p上又显得比较空了。

对比图2.png
问题所在:
最后我发现,大部分设计师在设计的时候,工作流程都是这样:
1.在自己的参照的屏幕尺寸下设计;
2.导出设计图,放在iPhone6p、iPhone6、iPhone5等设备上查看效果;
3.效果感觉满意后就可以开始标注、切图了;
  看着好像并没有什么问题,但是问题恰恰就出现在第2步,导出图片放在手机中查看,如果宽度和手机屏幕宽度一致,高度按比例缩放了,那么其实图片里面展示的字体大小、控件间距、控件大小都随着该比例缩放了。但是iOS开发中并没有进行缩放的操作,这也就成为了为什么设计师明明看着好好的,可是出来的效果怎么就出现偏差了呢?

  最后设计师问我,能不能按照屏幕分辨率直接等比例缩放,这样在所有的屏幕上就全部都完美了。

对比图3.png
  参照上图的意思是说,在iPhone6p上这个itemView能够展示2.5个,那么在iPhone6上面也是2.5个,而不会因为iPhone6的屏幕宽度小了就只展示2个。

  说了这么多,也应该开始正真的代码开发了。

  先放两张效果图看看:

对比图4.png

对比图5.png
  效果显示不管是字体大小、控件间距、控件大小都跟随屏幕大小自适应缩放大小,然后终于合了设计师的心意了~

  我给我的这个操作起了个名字:比例自动布局(AutoLayout)。使用的AutoLayout第三方库是PureLayout,这里就不再对PureLayout做过多的介绍了,不知道的同学可以在github上搜索下载学习。
  大部分操作也是在PureLayout的源文件里进行修改操作。

1.选取参考尺寸
  因为自己是从iPhone4、iPhone5开发过来的,原来的很多设计图,都是参考这个尺寸做的,所以我选择的参考尺寸是320px,当然你也可以选择其他的参考尺寸,比如iPhone6的375px。

  在UIView扩展类:ALView+PureLayout.m中添加:

//依据iPhone5的尺寸得到当前屏幕相对于iPhone5屏幕尺寸的大小
+(CGFloat)sizeFromIphone5:(CGFloat)size{
#if TARGET_OS_IPHONE
static float width = 0;
if (width == 0) {
width = [UIScreen mainScreen].bounds.size.width;
}
return width/320.0*size;
#endif
return size;
}

//依据真实的尺寸得到iPhone5屏幕尺寸的大小
+(CGFloat)sizeFromRealSize:(CGFloat)size{

if TARGET_OS_IPHONE

static float width = 0;
if (width == 0) {width = [UIScreen mainScreen].bounds.size.width;
}
return 320.0/width*size;

endif

return size;

}
2.字体大小修改
  对UIFont扩展方法:

import “UIFont+XM.h”

@implementation UIFont (CW)

+(UIFont *)cwFontWithSize:(CGFloat)fontSize{
return [UIFont systemFontOfSize:[UIView sizeFromIphone5:fontSize]];
}

+(UIFont *)cwBoldFontWithSize:(CGFloat)fontSize{
return [UIFont boldSystemFontOfSize:[UIView sizeFromIphone5:fontSize]];
}

@end
  在开发中全部字体设置都用这个方法来执行。

3.控件大小
  在传入size后,对size进行加工:

size = [UIView sizeFromIphone5:size];
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation
{
size = [UIView sizeFromIphone5:size];

self.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)dimension];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:size];
[constraint autoInstall];
return constraint;

}
4.控件间距
  在传入offset后,对offset进行加工:

offset = [UIView sizeFromIphone5:offset];
  因为不管是两个控件之间的相对间距,还是相对于父控件的间距,在PureLayout中最后执行都是这个方法:

  • (NSLayoutConstraint )autoConstrainAttribute:(ALAttribute)attribute toAttribute:(ALAttribute)toAttribute ofView:(ALView )otherView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation
    {
    offset = [UIView sizeFromIphone5:offset];

    self.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutAttribute layoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:attribute];
    NSLayoutAttribute toLayoutAttribute = [NSLayoutConstraint al_layoutAttributeForAttribute:toAttribute];
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:layoutAttribute relatedBy:relation toItem:otherView attribute:toLayoutAttribute multiplier:1.0 constant:offset];
    [constraint autoInstall];
    return constraint;
    }
    5.对抗系统自带大小
      iOS有很多自带的布局控件,而且大小(特别是高度)是固定的,我的操作是:

1.UINavigationBar:全部隐藏,就当没有这个控件,全部自定义;
2.UITabBar:因为并没有什么影响,所以不予置理;
6.心理
  为什么会把这个单独提出来,原因是开发中需要调整自己的心理影响,现在的做法是目前的屏幕宽度都是320px。

  比如在设置UILabel的preferredMaxLayoutWidth属性的时候:

-(void)layoutSubviews{
[super layoutSubviews];
contentLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.frame)-[UIView sizeFromIphone5:10]-[UIView sizeFromIphone5:26];
commentLabel.preferredMaxLayoutWidth = CGRectGetWidth(commentView.frame)-[UIView sizeFromIphone5:22];
}
  比如在得到屏幕5等分宽度的时候:

float width = 320/5;
7.总结
设计师工作流程就变成了这样:
1.在自己的参照的屏幕尺寸下设计;
2.导出设计图,放在iPhone6p、iPhone6、iPhone5等设备上查看效果;
3.效果感觉满意后就可以开始在【960px或者640px或者320px上进行标注】,因为可能直接在320px上标注像素会丢失,最好在960px上标注,开发人员自行除以3处理;
4.1242px上切图,因为要保证图片的分辨率在大屏手机上的清晰度;
  可能还有很多没有考虑到(涉世未深,工作经验并不多),这里提出的只是一个参考的思路,本人对PureLayout的使用也是刚刚接触,其中的方法,我常用的也就这么几个,如果用到了其他的方法,肯定是要注意的。

文/狍子君(简书作者)
原文链接:http://www.jianshu.com/p/8ecc594b6c5f

这篇关于iOS】利用PureLayout实现:比例自动布局(AutoLayout)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/519360

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、