iOS开发框架--MyLayout

news/2024/10/20 11:34:58

MyLayout 框架不仅支持 Objective-C,也可以在 Swift 中使用。通过 MyLayout,可以使用面向对象的方式来创建和管理视图的布局,简化了 Auto Layout 中繁琐的约束设置流程。在 Objective-C 中,MyLayout 提供了相同的布局类型和属性,使用方式稍有不同,主要是语法和调用方式上的差异。

先介绍一下如何使用吧,线性布局和相对布局是用的比较多的布局方式。

1. 线性布局(MyLinearLayout)

线性布局是一种里面的子视图按添加的顺序从上到下或者从左到右依次排列的单列(单行)布局视图,因此里面的子视图是通过添加的顺序建立约束和依赖关系的。 子视图从上到下依次排列的线性布局视图称为垂直线性布局视图,而子视图从左到右依次排列的线性布局视图则称为水平线性布局

创建一个垂直线性布局的示例:

MyLinearLayout *rootLayout = [MyLinearLayout linearLayoutWithOrientation:MyOrientation_Vert];
rootLayout.frame = self.view.bounds;
rootLayout.topPos.equalTo(@0);
rootLayout.leftPos.equalTo(@0);
rootLayout.rightPos.equalTo(@0);
rootLayout.bottomPos.equalTo(@0);// 添加子视图
UIView *view1 = [UIView new];
view1.myHeight = 50;
view1.leftPos.equalTo(@10);
view1.rightPos.equalTo(@10);
[view1 setBackgroundColor:[UIColor redColor]];
[rootLayout addSubview:view1];UIView *view2 = [UIView new];
view2.myHeight = 100;
view2.leftPos.equalTo(@10);
view2.rightPos.equalTo(@10);
[view2 setBackgroundColor:[UIColor blueColor]];
[rootLayout addSubview:view2];[self.view addSubview:rootLayout];

在这个例子中,我们创建了一个垂直线性布局容器 rootLayout,并在其中添加了两个 UIView 子视图。每个子视图都有自己的高度和边距设置。view1view2 分别设置了不同的高度,且左右边距为 10。

2. 相对布局(MyRelativeLayout)

相对布局允许子视图通过相对父视图或者其他子视图的位置来布局。

相对布局示例:

MyRelativeLayout *rootLayout = [MyRelativeLayout new];
rootLayout.frame = self.view.bounds;
rootLayout.topPos.equalTo(@0);
rootLayout.leftPos.equalTo(@0);
rootLayout.rightPos.equalTo(@0);
rootLayout.bottomPos.equalTo(@0);UIView *view1 = [UIView new];
view1.mySize = CGSizeMake(100, 100);
view1.centerXPos.equalTo(rootLayout.centerXPos);  // 水平居中
view1.topPos.equalTo(@10);                        // 距离父视图顶部 10
[view1 setBackgroundColor:[UIColor redColor]];
[rootLayout addSubview:view1];UIView *view2 = [UIView new];
view2.mySize = CGSizeMake(100, 100);
view2.topPos.equalTo(view1.bottomPos).offset(10); // 位于 view1 底部,间隔 10
view2.centerXPos.equalTo(view1.centerXPos);       // 水平与 view1 对齐
[view2 setBackgroundColor:[UIColor blueColor]];
[rootLayout addSubview:view2];[self.view addSubview:rootLayout];

在这个示例中,view1 在父视图中水平居中,并且距离顶部有 10 的间隔。而 view2 则位于 view1 的下方,并保持水平对齐。通过设置 centerXPostopPos 等属性,MyLayout 可以轻松实现相对布局。

3. 布局框架的类架构

这张图展示了 MyLayout 布局框架的类架构,帮助开发者理解其内部设计和结构。

  1. MyBaseLayout

    • 这是 MyLayout 框架的基础类,所有具体的布局类(如 MyLinearLayoutMyFrameLayout 等)都继承自它。它负责处理布局容器的基础功能,如视图的排列、布局更新等。
  2. 布局子类

    • MyBaseLayout 派生的不同布局类型用于支持多种布局方式:
      • MyLinearLayout:线性布局,视图依次排列,可以是垂直或水平。
      • MyFrameLayout:帧布局,子视图重叠在一起,根据设置的大小、位置显示。
      • MyRelativeLayout:相对布局,子视图可以相对于其他视图或容器进行布局。
      • MyFlowLayout:流式布局,子视图按行或列排列,类似于文本换行的效果。
      • MyFloatLayout:浮动布局,视图可以根据容器空间自动排列。
      • MyPathLayout:路径布局,子视图可以沿着路径排列。
      • MyGridLayout:网格布局,子视图按网格排列。
      • MyTableLayout:表格布局,子视图按表格形式排列。
  3. MyViewSizeClass 和子类:

    • MyViewSizeClass 是用于定义视图在不同尺寸类别下的表现,类似于 iOS 的 Size Class 概念。
    • MyLayoutViewSizeClass 是它的子类,用于处理 MyLayout 视图的大小、边距、位置等属性。
    • 不同的布局有各自的 ViewSizeClass,如 MyLinearLayoutViewSizeClassMyTableLayoutViewSizeClass 等,来定义在这些布局中的尺寸规则。
  4. UIView 的扩展 (Category)

    • 通过对 UIView 进行扩展,MyLayout 框架为视图添加了自定义布局属性,如 leftPostopPoswidthSizeheightSize 等。这些属性与 MyLayoutPosMyLayoutSize 类相关联,帮助开发者通过简单的设置实现复杂的布局需求。
  5. MyLayoutPos 和 MyLayoutSize

    • MyLayoutPos:MyLayoutPos类是用来描述一个视图所在的位置的类。UIView中扩展出了leftPos,topPos,bottomPos,rightPos,centerXPos,centerYPos这六个变量来实现视图的定位操作。您可以用这些变量的equalTo方法来设置视图之间的边距和间距。 equalTo 方法可以设置NSNumber, MyLayoutPos, NSArray<MyLayoutPos*>这几种值,分别用于不同的场景。同时系统提供了6个简单的变量myLeft, myTop, myBottom, myRight, myCenterX, mYCenterY来设置NSNumber类型的值,比如 A.leftPos.equalTo(@10); 等价于 A.myLeft = 10;.

    • MyLayoutSize:MyLayoutSize类是用来描述一个视图的尺寸的类。UIView中扩展出了widthSize,heightSize这两个变量来实现视图的宽度和高度尺寸的设置。您可以用其中的equalTo方法来设置视图的宽度和高度。equalTo方法可以设置NSNumber, MyLayoutSize, NSArray<MyLayoutSize*>这几种值,分别用于不同的场景。同时系统提供了2个简单的变量myWidth,myHeight来设置NSNumber类型的值,比如A.widthSize.equalTo(@10); 等价于A.myWidth = 10;.

  6. MyWeight

    • MyWeight 是一个与布局权重相关的概念,用于控制视图在容器中占据的相对空间。

通过这个类架构图,可以看到 MyLayout 框架是如何通过继承和扩展的方式,将多种布局模式整合到一个框架中,从而简化复杂布局的实现。

4. 底层原理

MyLayout 的底层原理主要是通过对每个视图的布局属性(如 myLeftMarginmyWidthmyHeight 等)进行计算,并在布局容器中根据这些属性重新调整每个子视图的位置和大小。这个过程与 Auto Layout 系统相似,但 MyLayout 不依赖 iOS 自带的 Auto Layout 约束机制,而是通过手动布局来优化性能和简化实现。

1. 视图树遍历与布局计算

MyLayout 的核心机制是遍历视图树,逐个计算每个视图的位置和大小。这个过程在布局视图的 layoutSubviews 方法中触发。当父布局容器需要重新布局时,会调用 layoutSubviews,在这个方法中,MyLayout 遍历所有子视图,并根据子视图的布局属性(如边距、宽高、自适应等)进行计算和定位。

每个视图的布局属性都会影响到其最终的 frame,MyLayout 会根据这些属性和布局容器的尺寸来动态调整子视图的位置和大小。例如:

  • myLeftMarginmyRightMargin 决定视图在父视图中的左右间距。
  • myWidth 决定视图的宽度,可以是固定值、百分比或根据内容自适应。
  • weight 属性用于动态分配剩余空间,类似于 flexboxflex 属性。
2. 布局属性的自定义与扩展

MyLayout 基于 UIView 的扩展,将自定义的布局属性直接挂载在每个子视图上。通过为 UIView 扩展自定义属性(例如 myLeftMarginmyHeight),MyLayout 实现了布局属性的可访问性。然后,框架通过在布局视图的 layoutSubviews 方法中访问这些自定义属性,完成布局的计算和调整。

这些自定义属性的设定值可以是固定数值,也可以是相对父视图或兄弟视图的动态值,这使得 MyLayout 在布局时非常灵活。例如:

  • 当视图的宽度是相对父视图的宽度时,可以设置 myWidth.equalTo(self.view.myWidth),表示视图的宽度等于父视图宽度。
3. 自适应与动态调整

MyLayout 支持子视图的自适应布局,通过计算视图的固有内容大小和父视图的剩余空间,动态调整子视图的尺寸和位置。与 Auto Layout 类似,当某个视图的内容发生变化时(例如文本视图内容变长),MyLayout 可以自动调整该视图的大小,使其适应新的内容。

此外,MyLayout 还支持动态调整布局。当父视图的尺寸改变时(例如旋转屏幕或窗口大小调整),MyLayout 会重新计算所有子视图的布局,确保它们始终适应当前的父视图大小。

4. 避免 Auto Layout 的性能开销

MyLayout 的一个主要优势是避免了 Auto Layout 系统带来的性能开销。Auto Layout 通过约束系统来管理布局,内部需要解决一系列的线性方程,这可能在复杂布局场景下导致性能瓶颈。而 MyLayout 直接操作视图的 frame 属性,跳过了约束的解析过程,从而提高了布局效率,特别是在需要频繁动态调整布局的场景中表现更佳。

5. 布局类型的实现

MyLayout 提供了多种布局类型(线性布局、相对布局、表格布局等),这些布局类型的实现原理是根据布局容器的不同类型,采用不同的算法来计算子视图的排列方式。例如:

  • 线性布局:通过遍历子视图,按照垂直或水平方向依次排列,并根据 myLeftMarginmyTopMargin 等属性调整每个视图的位置。
  • 相对布局:根据子视图的相对定位属性(例如 centerXPos.equalTo()),在布局时计算相对关系,调整视图的位置。
  • 表格布局:按照行列方式排列子视图,类似于表格的布局逻辑。
6. 性能优化

MyLayout 的性能优化体现在以下几个方面:

  • 避免不必要的重绘:在子视图的布局属性发生变化时,MyLayout 会触发布局刷新,但它会避免无关子视图的重绘和布局调整,减少性能开销。
  • 轻量级的布局计算:由于不依赖 Auto Layout 的约束解析,MyLayout 的布局计算只涉及简单的几何运算,避免了复杂的约束求解过程,从而提升布局效率。
  • 支持缓存机制:在某些复杂场景下,MyLayout 还可以通过缓存布局结果,进一步减少重复计算的开销。

4. 使用

podfile中加入,然后运行,命令:pod install

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'pod 'MyLayout'

框架作者还给出了一个y演示demo:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73762.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

HCBOLL指标

HCBOLL也称弘缠布林,是在传统布林线的基础上,加上了开口与收口的计算,用来表示可能的单边与震荡走势状态 操作上比较适合于日线以下周期如 1分钟 5分钟 30分钟--一般是推荐30分钟使用此指标时要注意主图上的K线数要多于480根,否则显示不了指标数据布林上下线间的灰色底色代…

信友队2024CSP-S第二轮(复赛)模拟赛

2024CSP-S第二轮(复赛)模拟赛\(T1\) A. 坦白 \(30pts\)部分分\(30pts\) :爆搜。点击查看代码 ll ans[300010]; char s[300010]; int main() {freopen("confess.in","r",stdin);freopen("confess.out","w",stdout);ll t,n,cnt,i,j,…

最近网站频繁跳转到黑产网站,怀疑是51.la统计代码的问题

​ 最近我的几个网站,都出现了一个问题,就是访问的时候会莫名其妙的跳转到黑产网站。(由于都是黄du,我就不贴图了)通过排查了网页代码,发现网页都有一个共同点,就是使用了51.la统计。为什么会怀疑是51la统计代码问题?因为我的网页只有统计代码外没有任何js的情…

桌面软件/exe程序软件自动化大宝剑--lackey之二次封装以及selenium模仿

1 # lackey 二次封装2 3 class lackeyAtion(object):4 5 #初始化,有需要再加6 def __init__(self):7 self.lackey = lackey.Screen(0)8 self.lackey.setAutoWaitTimeout(30)9 10 #截屏需要保存路径,截图的名字11 def screen_shot(self,path,…

linux和windows的区别

Linux和Windows是两种广泛使用的操作系统,它们在多个方面存在显著的区别。本文将探讨Linux和Windows之间的不同之处,包括开放源代码与闭源的本质、用户界面和命令行的使用、软件兼容性、性能和稳定性等方面。1.开放源代码与闭源本质Linux是一种开放源代码操作系统,这意味着其…

TLS

参考:https://www.cnblogs.com/snowater/p/7804889.html https://xiaozhuanlan.com/topic/5367421089 https://xiaozhuanlan.com/topic/5367421089 https://www.rfc-editor.org/rfc/rfc52461.背景 HTTP的数据传输本身是不可靠/不安全的,原因在于数据在数据包中以明文的形式传…

R.I.P.

?.?.?——2024.10.06 永远怀念。我的第一个 CF 号,就以这样荒唐的方式被 ban 了。已经说不出话来了,就这样吧。

高等数学 7.1 微分方程的基本概念

一般地,凡表示未知函数、未知函数的导数与自变量之间的关系的方程,叫做微分方程,有时也简称方程。 微分方程中所出现的未知函数的最高阶导数的阶数,叫做微分方程的阶。 一般地,\(n\) 阶微分方程的形式是 \[F(x, y, y, \cdots, y^{(n)}) = 0 \tag{1} \]这里必须指出,在方程…