在 Xcode 6 中使用 AutoLayout 约束模拟切面匹配行为 [英] Emulating aspect-fit behaviour using AutoLayout constraints in Xcode 6

查看:17
本文介绍了在 Xcode 6 中使用 AutoLayout 约束模拟切面匹配行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 AutoLayout 以类似于 UIImageView 的 aspect-fit 内容模式的方式调整视图的大小和布局.

I want to use AutoLayout to size and layout a view in a manner that is reminiscent of UIImageView's aspect-fit content mode.

我在 Interface Builder 的容器视图中有一个子视图.子视图有一些我希望尊重的固有纵横比.容器视图的大小在运行之前是未知的.

I have a subview inside a container view in Interface Builder. The subview has some inherent aspect ratio which I wish to respect. The container view's size is unknown until runtime.

如果容器视图的纵横比比子视图宽,那么我希望子视图的高度等于父视图的高度.

If the container view's aspect ratio is wider than the subview, then I want the subview's height to equal the parent view's height.

如果容器视图的纵横比高于子视图,那么我希望子视图的宽度等于父视图的宽度.

If the container view's aspect ratio is taller than the subview, then I want the subview's width to equal the parent view's width.

无论哪种情况,我都希望子视图在容器视图中水平和垂直居中.

In either case I wish the subview to be centered horizontally and vertically within the container view.

有没有办法在 Xcode 6 或以前的版本中使用 AutoLayout 约束来实现这一点?理想情况下使用 Interface Builder,但如果不是,也许可以通过编程方式定义此类约束.

Is there a way to achieve this using AutoLayout constraints in Xcode 6 or in previous version? Ideally using Interface Builder, but if not perhaps it is possible to define such constraints programmatically.

推荐答案

你不是在描述 scale-to-fit;您正在描述方面适合.(我已经在这方面编辑了您的问题.)子视图变得尽可能大,同时保持其纵横比并完全适合其父视图.

You're not describing scale-to-fit; you're describing aspect-fit. (I have edited your question in this regard.) The subview becomes as large as possible while maintaining its aspect ratio and fitting entirely inside its parent.

无论如何,您可以使用自动布局来做到这一点.从 Xcode 5.1 开始,您可以完全在 IB 中完成.让我们从一些观点开始:

Anyway, you can do this with auto layout. You can do it entirely in IB as of Xcode 5.1. Let's start with some views:

浅绿色视图的纵横比为 4:1.深绿色视图的纵横比为 1:4.我将设置约束,以便蓝色视图填充屏幕的上半部分,粉红色视图填充屏幕的下半部分,并且每个绿色视图都尽可能扩展,同时保持其纵横比并适合其容器.

The light green view has an aspect ratio of 4:1. The dark green view has an aspect ratio of 1:4. I'm going to set up constraints so that the blue view fills the top half of the screen, the pink view fills the bottom half of the screen, and each green view expands as much as possible while maintaining its aspect ratio and fitting in its container.

首先,我将在蓝色视图的所有四个边上创建约束.我会将它固定到每个边缘上最近的邻居,距离为 0.我确保关闭边距:

First, I'll create constraints on all four sides of the blue view. I'll pin it to its nearest neighbor on each edge, with a distance of 0. I make sure to turn off margins:

请注意,我更新框架.我发现在设置约束时在视图之间留出空间更容易,只需手动将常量设置为 0(或其他值).

Note that I don't update the frame yet. I find it easier to leave room between the views when setting up constraints, and just set the constants to 0 (or whatever) by hand.

接下来,我将粉色视图的左、下和右边缘固定到最近的邻居.我不需要设置顶部边缘约束,因为它的顶部边缘已经被限制在蓝色视图的底部边缘.

Next, I pin the left, bottom, and right edges of the pink view to its nearest neighbor. I don't need to set up a top edge constraint because its top edge is already constrained to the bottom edge of the blue view.

我还需要粉色和蓝色视图之间的等高约束.这将使它们各自占据屏幕的一半:

I also need an equal-heights constraint between the pink and blue views. This will make them each fill half the screen:

如果我告诉 Xcode 现在更新所有帧,我会得到:

If I tell Xcode to update all the frames now, I get this:

所以到目前为止我设置的约束是正确的.我撤消该操作并开始处理浅绿色视图.

So the constraints I've set up so far are correct. I undo that and start work on the light green view.

Aspect-fiting 浅绿色视图需要五个约束:

Aspect-fitting the light green view requires five constraints:

  • 浅绿色视图上的必需优先级纵横比约束.您可以使用 Xcode 5.1 或更高版本在 xib 或情节提要中创建此约束.
  • 将浅绿色视图的宽度限制为小于或等于其容器宽度的必需优先级约束.
  • 将浅绿色视图的宽度设置为等于其容器宽度的高优先级约束.
  • 将浅绿色视图的高度限制为小于或等于其容器高度的必需优先级约束.
  • 将浅绿色视图的高度设置为等于其容器高度的高优先级约束.

让我们考虑两个宽度限制.小于或等于约束本身不足以确定浅绿色视图的宽度;许多宽度将适合约束.由于存在歧义,自动布局将尝试选择一个解决方案,以最小化另一个(高优先级但不是必需的)约束中的错误.最小化误差意味着使宽度尽可能接近容器的宽度,同时不违反所需的小于或等于约束.

Let's consider the two width constraints. The less-than-or-equal constraint, by itself, is not sufficient to determine the width of the light green view; many widths will fit the constraint. Since there's ambiguity, autolayout will try to choose a solution that minimizes the error in the other (high-priority but not required) constraint. Minimizing the error means making the width as close as possible to the container's width, while not violating the required less-than-or-equal constraint.

高度限制也会发生同样的事情.并且由于还需要aspect-ratio约束,所以只能最大化subview沿一个轴的大小(除非容器恰好和子view有相同的宽高比).

The same thing happens with the height constraint. And since the aspect-ratio constraint is also required, it can only maximize the size of the subview along one axis (unless the container happens to have the same aspect ratio as the subview).

首先我创建纵横比约束:

So first I create the aspect ratio constraint:

然后我用容器创建相等的宽度和高度约束:

Then I create equal width and height constraints with the container:

我需要将这些约束编辑为小于或等于约束:

I need to edit these constraints to be less-than-or-equal constraints:

接下来我需要用容器创建另一组相等的宽度和高度约束:

Next I need to create another set of equal width and height constraints with the container:

而且我需要使这些新约束低于所需的优先级:

And I need to make these new constraints less than required priority:

最后,您要求子视图在其容器中居中,所以我将设置这些约束:

Finally, you asked for the subview to be centered in its container, so I'll set up those constraints:

现在,为了测试,我将选择视图控制器并要求 Xcode 更新所有帧.这是我得到的:

Now, to test, I'll select the view controller and ask Xcode to update all the frames. This is what I get:

哎呀!子视图已扩展以完全填满其容器.如果我选择它,我可以看到它实际上保持了它的纵横比,但它正在做一个 aspect-fill 而不是 aspect-fit.

Oops! The subview has expanded to completely fill its container. If I select it, I can see that in fact it's maintained its aspect ratio, but it's doing an aspect-fill instead of an aspect-fit.

问题在于,在小于或等于约束中,约束两端的视图很重要,而 Xcode 设置的约束与我的预期相反.我可以选择这两个约束中的每一个并反转它的第一项和第二项.相反,我将只选择子视图并将约束更改为大于或等于:

The problem is that on a less-than-or-equal constraint, it matters which view is at each end of the constraint, and Xcode has set up the constraint opposite from my expectation. I could select each of the two constraints and reverse its first and second items. Instead, I'll just select the subview and change the constraints to be greater-than-or-equal:

Xcode 更新布局:

Xcode updates the layout:

现在我对底部的深绿色视图做同样的事情.我需要确保它的纵横比是 1:4(Xcode 以一种奇怪的方式调整了它的大小,因为它没有约束).我不会再展示这些步骤,因为它们是相同的.结果如下:

Now I do all the same things to the dark green view on the bottom. I need to make sure its aspect ratio is 1:4 (Xcode resized it in a weird way since it didn't have constraints). I won't show the steps again since they're the same. Here's the result:

现在我可以在 iPhone 4S 模拟器中运行它,它的屏幕尺寸与 IB 使用的不同,并测试旋转:

Now I can run it in the iPhone 4S simulator, which has a different screen size than IB used, and test rotation:

我可以在 iPhone 6 模拟器中进行测试:

And I can test in in the iPhone 6 simulator:

为了您的方便,我已将我的最终故事板上传到this gist.

I've uploaded my final storyboard to this gist for your convenience.

这篇关于在 Xcode 6 中使用 AutoLayout 约束模拟切面匹配行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆