RQVisual 是一个工具,可以像 Auto Layout 的 Visual Format Language 一样,通过可视化格式在代码中轻松地布局视图。所有视图都使用 Auto Layout 约束进行布局,因此您可以在不编写冗长的 NSLayoutConstraint 语法的情况下获得 Auto Layout 的全部优点。
Auto Layout 的 Visual Format Language 确实可以减少为视图添加多个约束所需的代码行数,但 Visual 的动机是进一步简化这一点。使用 Visual,您可以使用一个方法调用来布局整个视图(当然,这取决于视图的复杂性)。视图之间的隐式填充也被添加,并且可以可选地覆盖或配置到特定的值。这使得可以在不指定视图格式的情况下自动应用视图之间的“标准”间距。
通过 CocoaPods
pod 'RQVisual'
有关基本语法文档,请参阅 wiki。
以下示例可以采用以下方法之一
+ (UIView *)viewFromVisualFormats:(NSArray *)visualFormats rowSpacingVisualFormat:(NSString *)rowSpacingVisualFormat variableBindings:(NSDictionary *)variableBindings;
+ (void)addSubviewsToView:(UIView *)containerView usingVisualFormats:(NSArray *)visualFormats rowSpacingVisualFormat:(NSString *)rowSpacingVisualFormat variableBindings:(NSDictionary *)variableBindings;
第一种方法将在新的容器视图中返回您的视图,第二种方法将在现有视图中添加您的视图。
还有一个方便的宏,RQVisualDictionaryOfVariableBindings
,它将视图名称映射到视图对象本身。这个宏与 NSDictionaryOfVariableBindings
非常相似,但当你传递属性时,它将省略关键名称中的 self.
部分。例如
UIButton *button = ...
self.textView = ...
/**
Produces @{ @"self.textView": self.textView,
@"button": button }
*/
NSDictionary *variables1 = NSDictionaryOfVariableBindings(self.textView, button);
/**
Produces @{ @"textView": self.textView,
@"button": button }
*/
NSDictionary *variables2 = RQVisualDictionaryOfVariableBindings(self.textView, button);
假设我想创建一个视图,包含一个固定宽度为 50.0 的 UIImageView
和一个动态宽度的 UILabel
。类似这样
|[imageView][ label ]|
使用 Visual 我们可以这样操作
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)]-[label]"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label }];
这看起来与直接使用 NSLayoutConstraint 的 + constraintsWithVisualFormat:options:metrics:views:
方法非常相似,但是这里已经添加了一些隐式水平和垂直约束
imageView
和 label
之间设置了 10.0
的水平填充(默认水平填充)。imageView
限制在创建视图的左边边缘。label
限制在创建视图的右边边缘。如果调整containerView
的大小,则label
将拉伸宽度,而imageView
和label
都将拉伸高度。
如果我们想固定这些视图的高度,我们只需在视觉格式末尾添加一个特定的高度。
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)]-[label](60)"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label }];
现在,imageView
和label
都将被限制为一个高度为60
。
需要注意的是,这里的containerView
将返回一个不破坏约束的最小可能大小的界面框。对于上述示例,这意味着50 x 60
,因为标签具有动态宽度,且允许宽度为0.0
。
可以通过与Auto Layout的视觉格式语言相同的方式应用行中项目之间的间距。
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"|-(30)-[imageView(50)]-(40)-[label](60)"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label }];
任何未指定的间距将使用默认值,这些值是在两个项目之间为10
(如果您没有设置自己的默认值)并且在与父类视图的对角线上为0
。
可以指定同一行内的视图应该具有相同的宽度。
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(==)]-[label(==)](60)"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label }];
在这里,imageView
和label
将具有相同的宽度约束,且两者的高度都为60
(高度约束是可有可无的)。
如果您想居中某些视图或将某些视图固定到某一侧,可以使用`<`指定向左固定,`>`指定向右固定,`<>`用于居中。要生成这样的视图
|[imageView] [label] [button]|
我们将这样做
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)<]-[label(50)<>]-[button(50)>](60)"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label,
@"button" button }];
可以一起居中多个视图,例如
| [imageview][label] |
只需为两个视图都使用`<>`语法即可
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)<>]-[label(50)<>](60)"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label }];
请注意,对于这些视图固定和居中的示例,您必须在视图中指定宽度约束。这是因为如果视图允许在其宽度上拉伸,则没有固定/居中的意义。
制作具有多行的视图也很简单。假设我们想要像示例 1 中一样相同的视图,但在其下方我们想要一个UITextView
。
|[imageView][ label ]|
|[ textView ]|
使用视觉格式,将是这样的
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)]-[label](60)",
@"[textView]"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView,
@"label": label,
@"textView": textView }];
在这里,我们已在水平和垂直方向上添加了与示例 1 中相同的隐含约束,但现在还有在textView
和imageView
或label
之间的垂直填充。默认垂直填充也是10.0
。
如果我们想自定义行之间的间距,我们可以这样做
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"r1:[imageView(50)]-[label](60)",
@"r2:[textView]"]
rowSpacingVisualFormat:@"|-5-[r1]-5-[r2]-15-|"
variableBindings:@{ @"imageView": imageView,
@"label": label,
@"textView": textView }];
在这里,垂直间距将构建如您所预期的那样
r1
)将与其父视图顶部距离为5.0
点。r2
)将相隔5.0
点。15.0
点。为了指定行之间的自定义填充,您必须在行中添加标签。通过在视觉格式字符串前加上该行的名称和冒号来实现。名称可以是任何内容,只要它匹配 rowSpacingVisualFormat
中的变量。rowSpacingVisualFormat
字符串的构成方式与 Auto Layout 的视觉格式语言相同,除了使用方括号放置视图,您应使用行标签。
有时,您可能想包含一个类似于视图但用户看不见的间隔视图。为此,您可以使用 _spacer
关键字
UIView *containerView = [RQVisualMaster viewFromVisualFormats:@[@"[imageView(50)]-[_spacer]"]
rowSpacingVisualFormat:nil
variableBindings:@{ @"imageView": imageView }];
这将在 imageView
旁边隐式地为您添加一个不可见的视图。请注意,在这里最好使用 @"[imageView(50)<]"
将 imageView
固定在左侧,或者省略定位语法,只使用 @"[imageView(50)]"
,因为它们会产生相同的视觉效果。