使用Swift以编程方式布局视图的另一种方法
开始学习Swift时,我对自动布局系统感到困惑。 无论是使用情节提要还是程序限制,它都不适合我。 一些约束在运行时会干扰其他约束,而对所有不同的冲突约束进行分类变得令人沮丧。 我承认在Xcode中使用自动布局功能非常强大,但我相信,除了自动解决方案的替代方法会增加计算成本之外,还会增加其他复杂性。 请注意,在我的标题中,我并不是说这是一种布局视图的“更好”方法,只是一种可以促进进一步实验的不同方法
我觉得有一种更简洁,更省钱的布局视图方式,因此我开始着手开发一个名为View Layout的小型项目。 它只是UIView的扩展,您在其中实例化一个结构(ViewLayout),该结构为您计算视图的位置。 您可能会做的所有数学运算都可以使用CGRect和框架布局视图? 所有这些都封装在“视图布局”结构中。 它使用ViewPosition枚举来确定视图相对于“引导视图”的位置。 我不会尝试描述它,而是显示代码。 这是ViewLayout的初始化,包括分解和解释的步骤。
//您要放置的视图的不同位置选择
枚举ViewPosition {
案例底部中心
案例底部左
案例底部右
案例中心
案例顶部左
案例顶部右
案例中心
剩下的情况
案例权
}
//通常除非要以根视图为指导进行布局,否则通常要使用withFrame init
init(withFrame ofView:UIView,position:ViewPosition,size:CGSize,padding:(CGFloat,CGFloat)){
self.guide = ofView.frame // 1
self.position =位置// 2
self.size =大小// 3
self.padding =填充// 4
}
1:我设置ViewLayout对象在计算其原点时使用的框架
2:我将框架的位置与指南进行了比较
3:我设置要在ViewLayout中创建的框架的大小
4:我使用元组设置视图的水平和垂直填充。 第一项(padding.0)控制垂直填充,正数增加原点的Y坐标,负数减少原点的Y。第二个数与水平填充相同,正数增加X坐标,负数减少了它。
现在,调用此初始化程序后,您将获得一个ViewLayout对象! 不过您还不能使用它。 您只是获得一个自动配置的框架以供视图使用而已,而仅仅是一个函数调用! 您所要做的就是调用以下功能之一:
//不要忘记在实例化结束时调用它!
func makeInnerLayout()-> CGRect {
返回CGRect(来源:原点,大小:大小)
}
func makeOuterLayout()-> CGRect {
返回CGRect(来源:outerOrigin,大小:size)
}
那么这是怎么回事? 好吧,我们使用外部或内部原点,并将大小传递给初始化程序,以返回CGRect用作视图的框架。 原点是ViewLayout对象中的计算属性,这些属性通过使用初始化程序的padding,position和guide视图返回视图的原点。 这两个函数之间的区别在于,makeOuterLayout()函数仅将原点计算为位于引导视图之外,而makeInnerLayout()函数将原点计算为在视图内部。 如果您想使用8pt的间距将两个视图彼此相邻地布局,则只需执行以下操作:
覆盖func viewDidLoad(){
super.viewDidLoad()
让viewWidth = self.view.bounds.width / 2-12
//在根视图内布置第一个视图
让view1Layout = UIView.ViewLayout(withBounds:self.view,position:.topLeft,size:CGSize(width:viewWidth,height:200),padding:(50,0))。makeInnerLayout()
view1 = UIView(框架:view1Layout)
view1.backgroundColor = .black
self.view.addSubview(view1)
//以view1为参考,向左8点
让view2Layout = UIView.ViewLayout(withFrame:view1,position:.right,size:CGSize(width:viewWidth,height:200),padding:(0,8))。makeOuterLayout()
view2 = UIView(框架:view2Layout)
view2.backgroundColor = .red
self.view.addSubview(view2)
}
此代码产生的布局如下所示:
这种方法的最大缺点是,许多人更喜欢autoLayout而不是CGRect数学,原因是您必须在代码中设置要布局两次的View的框架,至少要设置动画的话。 您可以在ViewDidLoad和didRotate(或类似函数)中进行设置。 我曾经在didLayoutSubviews()中布局视图一次。 但是我后来发现,如果在didLayoutSubviews()中存在与正在动画化的视图相关的布局代码,则在动画过程中会调用此方法,这通常会破坏动画。
我仍在尝试找出如何处理动画以及使用此方法在更困难的环境(如分屏和多任务)中进行布局的方法。 如果您有任何意见或认为可以实现的方式,请随时通过https://github.com/afrench53198/ViewLayout派生或向主项目发送拉取请求。
这是我的第一篇有关开发和实际代码的中级文章,所以请告诉我我的工作方式! 如果不清楚或可以更好地解释,请发表评论。 感谢您的阅读,我希望介绍ViewLayout结构可以激发您创建比AutoLayout程序约束或Visual Formatting Language更好,更有用的功能。