大家好,我是 K 哥。一名独立开发者,同时也是 Swift 开发框架【Aquarius】的作者,悦记和爱寻车 app 的开发者。
Aquarius 开发框架旨在帮助独立开发者和中小型团队,完成 iOS App 的快速实现与迭代。使用框架开发将给你带来简单、高效、易维护的编程体验。
Aquarius 布局系统简介
Aquarius 开发框架提供了一套完整的、极简的布局系统。通过该布局系统,你可以轻松的完成基于代码控制的视图布局。
核心价值:
🎯 一行顶多行 - 极简 API,大幅减少代码量
⚡ 动效零成本 - 所有布局变化天然支持动画
🔗 关系式布局 - 直观表达视图间相对关系
📦 批量好帮手 - 一次性操作多个视图
🔄 无缝兼容 - 基于原生 frame,即插即用
系统特点:
直观的定位和大小调整方法
内置动画支持
多视图批量操作
参见源码:
UIView+aLayout.swift
Array+aLayout.swift
复杂度:
基础布局:提供了对控件的基础设置
高级布局:提供了控件间关系型的动态设置
基础布局:重塑单个视图的操控体验
处理单个视图
位置
使用框架提供的方法,你可以轻松的完成视图位置的获取和设置。
不使用框架的获取方式
let x: CGFloat = myView.frame.origin.x
复制代码
使用框架的获取方式
let x: CGFloat = myView.x()//或let x: CGFloat = myView.left()
复制代码
不使用框架的获取方式
myView.frame.origin.x = 10.0
复制代码
使用框架的获取方式
myView.x(x: 10.0)//或myView.left(left: 10.0)
复制代码
不使用框架的获取方式
let y: CGFloat = myView.frame.origin.y
复制代码
使用框架的获取方式
let y: CGFloat = myView.y()//或let y: CGFloat = myView.top()
复制代码
不使用框架的获取方式
myView.frame.origin.y = 10.0
复制代码
使用框架的获取方式
myView.y(y: 10.0)//或myView.top(top: 10.0)
复制代码
不使用框架的获取方式
let right: CGFloat = myView.frame.origin.x + myView.frame.size.width
复制代码
使用框架的获取方式
let right: CGFloat = myView.right()
复制代码
不使用框架的获取方式
myView.frame.origin.x = 200.0 - myView.frame.size.width
复制代码
使用框架的获取方式
不使用框架的获取方式
let bottom: CGFloat = myView.frame.origin.y + myView.frame.size.height
复制代码
使用框架的获取方式
let bottom: CGFloat = myView.bottom()
复制代码
不使用框架的获取方式
myView.frame.origin.y = 200.0 - myView.frame.size.height
复制代码
使用框架的获取方式
myView.bottom(bottom: 200.0)
复制代码
大小
使用框架提供的方法,你可以轻松的完成视图大小的获取和设置。
不使用框架的获取方式
let width: CGFloat = myView.frame.size.width
复制代码
使用框架的获取方式
let width: CGFloat = myView.width()
复制代码
不使用框架的获取方式
myView.frame.size.width = 100.0
复制代码
使用框架的获取方式
myView.width(width: 100.0)
复制代码
不使用框架的获取方式
let height: CGFloat = myView.frame.size.height
复制代码
使用框架的获取方式
let height: CGFloat = myView.height()
复制代码
不使用框架的获取方式
myView.frame.size.height = 100.0
复制代码
使用框架的获取方式
myView.height(height: 100.0)
复制代码
point
不使用框架的获取方式
let point: CGPoint = myView.frame.origin
复制代码
使用框架的获取方式
let point: CGPoint = myView.point()
复制代码
不使用框架的获取方式
myView.frame.origin = CGPoint(x: 10.0, y: 10.0)
复制代码
使用框架的获取方式
myView.point(x: 10.0, y: 10.0)//或myView.point(point: CGPoint(x: 10.0, y: 10.0)//或myView.point(points: [10.0, 10.0])//当x, y值相同时myView.point(xy: 10.0)
复制代码
Size
不使用框架的获取方式
let size: CGSize = myView.frame.size
复制代码
使用框架的获取方式
let size: CGSize = myView.size()
复制代码
不使用框架的获取方式
myView.frame.size = CGSize(width: 100.0, height: 100.0)
复制代码
使用框架的获取方式
myView.size(width: 100.0, height: 100.0)//或myView.size(w: 100.0, h: 100.0)//或myView.size(size: CGSize(width: 100.0, height: 100.0))//或myView.size(sizes: [100.0, 100.0])//当宽和高相同时myView.size(widthHeight: 100.0)
复制代码
frame
不使用框架的获取方式
let frame: CGRect = myView.frame
复制代码
使用框架的获取方式
let frame: CGRect = myView.frame()
复制代码
不使用框架的获取方式
myView.frame = CGRect(x: 10.0, y: 10.0, width: 100.0, height: 100.0)//或myView.frame = CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: CGSize(width: 100.0, height: 100.0))
复制代码
使用框架的获取方式
myView.frame(frame: CGRect(x: 10.0, y: 10.0, width: 100.0, height: 100.0))//或myView.frame(x: 10.0, y: 10.0, w: 100.0, h: 100.0)//或myView.frame(frames: [10.0, 10.0, 100.0, 100.0])//当x, y和宽、高相同时myView.frame(xy: 10.0, widthHeight: 100.0)
复制代码
处理多个视图
基础操作
不使用框架的获取方式
view1.frame.origin.x = 10.0view2.frame.origin.x = 10.0
复制代码
使用框架的获取方式
UIView.x(x: 10.0, views: [view1, view2])//或UIView.left(left: 10.0, views: [view1, view2])
复制代码
使用框架的获取方式
UIView.right(right: 10.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame.origin.y = 10.0view2.frame.origin.y = 10.0
复制代码
使用框架的获取方式
UIView.y(y: 10.0, views: [view1, view2])//或UIView.top(top: 10.0, views: [view1, view2])
复制代码
使用框架的获取方式
UIView.bottom(bottom: 10.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame.size.width = 100.0view2.frame.size.width = 100.0
复制代码
使用框架的获取方式
UIView.width(width: 100.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame.size.height = 100.0view2.frame.size.height = 100.0
复制代码
使用框架的获取方式
UIView.height(height: 100.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame.origin = CGPoint(x: 10, y: 10)view2.frame.origin = CGPoint(x: 10, y: 10)
复制代码
使用框架的获取方式
UIView.point(x: 10.0, y: 10.0, views: [view1, view2])//或UIView.point(point: CGPoint(x: 10.0, y: 10.0), views: [view1, view2])//或UIView.point(points: [10.0, 10.0], views: [view1, view2])//当x, y值相同时UIView.point(xy: 10.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame.size = CGSize(width: 100.0, height: 100.0)view2.frame.size = CGSize(width: 100.0, height: 100.0)
复制代码
使用框架的获取方式
UIView.size(width: 100.0, height: 100.0, views: [view1, view2])//或UIView.size(w: 100.0, h: 100.0, views: [view1, view2])//或UIView.size(size: CGSize(width: 100.0, height: 100.0), views: [view1, view2])//或UIView.size(sizes: [100.0, 100.0], views: [view1, view2])//当宽和高相同时UIView.size(widthHeight: 100.0, views: [view1, view2])
复制代码
不使用框架的获取方式
view1.frame = CGRect(x: 10.0, y: 10.0, width: 100.0, height: 100.0)view2.frame = CGRect(x: 10.0, y: 10.0, width: 100.0, height: 100.0)//或view1.frame = CGRect(origin: CGPoint(x: 10.0, y: 10.0), size:CGSize(width: 100.0, height: 100.0))view2.frame = CGRect(origin: CGPoint(x: 10.0, y: 10.0), size:CGSize(width: 100.0, height: 100.0))
复制代码
使用框架的获取方式
UIView.frame(x: 10.0, y: 10.0, w: 100.0, h: 100.0, views: [view1, view2])//或UIView.frame(frame: CGRect(x: 10.0, y: 10.0, width: 100.0, height: 100.0), views: [view1, view2])//或UIView.frame(frame: CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: CGSize(width: 100.0, height: 100.0)), views: [view1, view2])//或UIView.frame(frames: [10.0, 10.0, 100.0, 100.0], views: [view1, view2])//当x, y和宽, 高相等时UIView.frame(xy: 10.0, widthHeight: 100.0, views: [view1, view2])
复制代码
对齐操作
框架支持多个视图的对齐
//顶端对齐UIView.top(views: [view1, view2, view3])//底部对齐UIView.bottom(views: [view1, view2, view3])//左侧对齐UIView.left(views: [view1, view2, view3])//右侧对齐UIView.right(views: [view1, view2, view3])
复制代码
支持对齐到某个目标位置
//顶端对齐UIView.top(views: [view1, view2, view3], position: 50)//底部对齐UIView.bottom(views: [view1, view2, view3], position: 50)//左侧对齐UIView.left(views: [view1, view2, view3], position: 50)//右侧对齐UIView.right(views: [view1, view2, view3], position: 50)
复制代码
分布操作
均匀分布视图:
// 在第一个和最后一个视图之间水平分布视图UIView.horizontal(views: [view1, view2, view3, view4])
// 在第一个和最后一个视图之间垂直分布视图UIView.vertical(views: [view1, view2, view3, view4])
复制代码
组合对齐和分布操作
在一次操作中对齐和分布视图:
// 顶端对齐并且水平分布视图UIView.topAndHorizontal(views: [view1, view2, view3, view4]) // 顶端对齐到某个目标位置并且水平分布视图UIView.topAndHorizontal(views: [view1, view2, view3, view4], position: 50) // 底部对齐并且水平分布视图UIView.bottomAndHorizontal(views: [view1, view2, view3, view4]) // 底部对齐到某个目标位置并且水平分布视图UIView.bottomAndHorizontal(views: [view1, view2, view3, view4], position: 50)
// 左侧对齐并且垂直分布视图UIView.leftVertical(views: [view1, view2, view3, view4])// 左侧对齐到某个目标位置并且垂直分布视图UIView.leftVertical(views: [view1, view2, view3, view4], position: 50)// 右侧对齐并且垂直分布视图UIView.rightVertical(views: [view1, view2, view3, view4])// 右侧对齐到某个目标位置并且垂直分布视图UIView.rightVertical(views: [view1, view2, view3, view4], position: 50)
复制代码
批量操作
框架支持数组的方式批量操作视图
let views: [UIView] = [view1, view2, view3]
views.width(width: 100.0)views.width(width: 100.0, 1)//设置数组中第2个UIView的宽度
views.height(height: 100.0)views.height(height: 100.0, 1)//设置数组中第2个UIView的高度
复制代码
高级布局:构建智能的、响应式的界面
Aquarius 开发框架提供了一个强大且灵活的布局系统,超越了基本的定位功能。通过高级布局技术,帮助你用最少的代码和最大的灵活性创建复杂的 UI 布局。
Aquarius 开发框架通过全面的布局方法扩展了 UIView,这些方法建立在原生基于框架的布局系统之上,使其更加直观和强大。与 Auto Layout 的基于约束的方法不同,Aquarius 开发框架提供了直接、命令式的 API,易于理解且可以无缝动画。
相对定位
基础操作
Aquarius 开发框架最强大的功能之一是它能够将视图相对于彼此定位。这消除了在排列视图时进行复杂计算的需要。
// 将viewB定位在viewA下方,间距为10ptviewB.alignTop(view: viewA, offset: 10)
// 将viewB定位在viewA右侧,间距为15ptviewB.alignLeft(view: viewA, offset: 15)
// 将viewB定位在viewA左侧,间距为8ptviewB.alignRight(view: viewA, offset: 8)
// 将viewB定位在viewA上方,间距为12ptviewB.alignBottom(view: viewA, offset: 12)
复制代码
批量操作
let views: [UIView] = [view1, view2, view3]
// 将views数组定位在viewA下方,间距为8ptviews.alignTop(view: viewA, offset: 8)
// 将views数组中第2个视图定位在viewA下方,间距为8ptviews.alignTop(view: viewA, offset: 8, 1)
// 将views数组定位在viewA上方,间距为8ptviews.alignBottom(view: viewA, offset: 8)
// 将views数组中第2个UI视图在viewA上方,间距为8ptviews.alignBottom(view: viewA, offset: 8, 1)
// 将views数组定位在viewA右侧,间距为8ptviews.alignLeft(view: viewA, offset: 8)
// 将views数组中第2个视图视图iewA右侧,间距为8ptviews.alignLeft(view: viewA, offset: 8, 1)
// 将views数组定位在viewA左侧,间距为8ptviews.alignRight(view: viewA, offset: 8)
// 将views数组中第2个UI视图视图wA左侧,间距为8ptviews.alignRight(view: viewA, offset: 8, 1)
复制代码
这些方法简化了流布局的创建,并能够在处理动态内容时无需手动计算位置。
等同定位
基础操作
当希望视图共享相同的边缘位置时,equal方法提供了一个简洁的语法
// 使viewB的左边缘与viewA相同(可选偏移)viewB.equalLeft(target: viewA, offset: 5)
// 使viewB的右边缘与viewA相同viewB.equalRight(target: viewA)
// 使viewB的顶部边缘与viewA相同viewB.equalTop(target: viewA)
// 使viewB的底部边缘与viewA相同viewB.equalBottom(target: viewA)
// 使viewB的大小与viewA相同viewB.equalSize(target: viewA)
// 使viewB的框架与viewA相同viewB.equalRect(target: viewA)
// 使viewB的左侧边缘设置为0viewB.equalZeroLeft()
// 使viewB的顶端边缘设置为0viewB.equalZeroTop()
// 使viewB的左侧边缘和顶端边缘设置为0viewB.equalZeroTopAndLeft()
复制代码
批量操作
let views: [UIView] = [view1, view2, view3]
// 使views数组的左边缘与viewA相同,间距为5ptviews.equalLeft(target: viewA, offset: 5)
// 使views数组中第2个视图的左边缘与viewA相同,间距为5ptviews.equalLeft(target: viewA, offset: 5, 1)
// 使views数组的右边缘与viewA相同,间距为5ptviews.equalRight(target: viewA, offset: 5)
// 使views数组中第2个UI视图边缘与viewA相同,间距为5ptviews.equalRight(target: viewA, offset: 5, 1)
// 使views数组的宽度与viewA相同,间距为5ptviews.equalWidth(target: viewA, offset: 5)
// 使views数组中第2个视图视图viewA相同,间距为5ptviews.equalWidth(target: viewA, offset: 5, 1)
// 使views数组的高度与viewA相同,间距为5ptviews.equalHeight(target: viewA, offset: 5)
// 使views数组中第2个UI视图视图ewA相同,间距为5ptviews.equalHeight(target: viewA, offset: 5, 1)
复制代码
这种方法非常适合创建对齐的 UI 元素,并在界面中保持视觉和谐。
屏幕感知定位
Aquarius 开发框架提供了方便的方法来处理屏幕尺寸和系统 UI 元素:
// 设置视图宽度与屏幕宽度相同view.equalScreenWidth()
// 设置视图高度与屏幕高度相同view.equalScreenHeight()
// 设置视图宽度和高度与屏幕高度相同view.equalScrenSize()
// 设置视图高度与屏幕高度相同,减去状态栏高度view.equalScreenHeightNoStatus()
// 设置视图高度与屏幕高度相同,减去导航栏高度view.screenHeightNoNavigation()
// 设置视图高度与屏幕高度相同,减去状态栏和导航栏高度view.screenHeightNoStatusNoNavigation()
// 设置视图高度与屏幕高度相同,减去底部安全区高度view.screenHeightNoSafeAreaFooter()
// 设置视图高度与屏幕高度相同,减去tabBar高度view.screenHeightNoTabBar()
// 设置视图高度与屏幕高度相同,减去状态栏和底部安全区高度view.screenHeightNoStatusNoSafeAreaFooter()
// 设置视图高度与屏幕高度相同,减去状态栏和tabBar高度view.screenHeightNoStatusNoTabBar()
// 设置视图高度与屏幕高度相同,减去状态栏、底部安全区和tabBar高度view.screenHeightNoStatusNoSafeAreaFooterNoTabBar()
// 设置视图高度与屏幕高度相同,减去导航栏和底部安全区高度view.screenHeightNoNavigationNoSafeAreaFooter()
// 设置视图高度与屏幕高度相同,减去导航栏和tabBar高度view.screenHeightNoNavigationNoTabBar()
// 设置视图高度与屏幕高度相同,减去导航栏、底部安全区和tabBar高度view.screenHeightNoNavigationNoSafeAreaFooterNoTabBar()
// 设置视图高度与屏幕高度相同,减去状态栏、导航栏和底部安全区高度view.screenHeightNoStatusNoNavigationNoSafeAreaFooter()
// 设置视图高度与屏幕高度相同,减去状态栏、导航栏和tabBar高度view.screenHeightNoStatusNoNavigationNoTabBar()
// 设置视图高度与屏幕高度相同,减去状态栏、导航栏、底部安全区和tabBar高度view.screenHeightNoStatusNoNavigationNoSafeAreaFooterNoTabBar()
复制代码
动画集成:让界面“活”起来
Aquarius 开发框架针对布局系统提供简单的动画,所有布局系统相关的方法均提供动画功能
// 在0.3秒内动画改变宽度view.width(width: 200, animate: true, duration: 0.3)
// 使用默认动画时长改变位置view.left(left: 50, animate: true)
// 使用自定义时序动画多个视图到相同位置UIView.bottom(bottom: 500, animate: true, duration: 0.5, views: [view1, view2, view3])...
复制代码
这种内置的动画支持使创建布局状态之间的平滑过渡变得简单,而无需额外代码。
实战案例:悦记 NoteView 布局剖析
下面以悦记 APP 中 NoteView 中 a_Layout 方法为例,展示 Aquarius 开发框架中布局系统的具体使用案例:
import UIKitimport Foundation
import Aquariusimport CommonFramework
class NoteView: BaseView { ... override func a_Layout() { super.a_Layout()
searchBar.frame(frames: [ 8, 8, screenWidth()-8*2, 52 ])
noteTableView.size(sizes: [ screenWidth(), screenHeight()-navigationBarHeight()-safeAreaFooterHeight()-tabBarHeight()-8 ]) noteTableView.equalTop(target: searchBar) noteTableView.equalLeft(target: self)
footerView.equalWidth(target: noteTableView) footerView.height(height: 48.0)
activityIndicatorView.equalSize(target: footerView) activityIndicatorView.equalZeroTopAndLeft()
leftSpaceView.width(width: NoteCell.distance) leftSpaceView.equalHeight(target: noteTableView) leftSpaceView.equalZeroLeft() leftSpaceView.equalTop(target: noteTableView) leftSpaceView.target(rightSpaceView) leftSpaceView.equals([.size, .top])
rightSpaceView.left(left: screenWidth()-NoteCell.distance)
createNoteButton.size(widthHeight: 60) createNoteButton.point(points: [ screenWidth()-60-16, screenHeight()-statusBarHeight()-navigationBarHeight()-tabBarHeight()-safeAreaFooterHeight()-createNoteButton.height() ]) } ...}
复制代码
代码解读:
关系清晰:视图间的依赖关系(如 equalTop, equalWidth)让布局逻辑一目了然。
易于维护:当某个视图的尺寸或位置需要调整时,只需修改一处,相关视图会自动更新。
动态适应:使用 screenHeight(), navigationBarHeight() 等方法,布局能自动适应不同的设备尺寸和系统状态。
为什么选择 Aquarius 布局系统
适用场景
🎯 独立开发者:追求开发效率,希望快速迭代。
🎯 动态 UI:界面元素需要频繁变化、动画丰富的应用。
🎯 代码控:喜欢用代码精确控制每一个像素,厌恶 Storyboard 的臃肿。
🎯 迁移项目:老项目基于 Frame,希望用最小成本引入现代布局方式。
总结
Aquarius 开发框架的布局系统提供了 Auto Layout 的强大替代方案,强调可读性、简洁性和动画集成。通过本篇文章介绍的相关技术,你可以用更少的代码创建复杂的布局,同时保持对 UI 元素定位和动画的完全控制。
直观的相对定位、灵活的分布方法和内置的动画支持相结合,使 Aquarius 开发框架成为需要创建动态、响应式界面的开发者的绝佳选择,而无需约束布局的复杂性。
立即体验 Aquarius:
第一步:探索资源
第二步:体验效果
第三步:沟通交流
评论