zoukankan      html  css  js  c++  java
  • Beginning Auto Layout Tutorial in iOS 7: Part 6

    Gallery example

    The Gallery app

    屏幕有四个分开的相同的矩形,每个矩形有一个label和一个image view。创建一个Gallery的项目。在Main.storyboard中,拖拉一个view大小为160 by 284 points。

    Green view in canvas

    Note: There are two main reasons why you would drop a plain UIView onto a storyboard:

    a) You’re going to use it as a container for other views, which helps with organizing the content of your scenes; or

    b) It is a placeholder for a custom view or control, and you will also set its Class attribute to the name of your own UIView or UIControl subclass.

    现在设置一些约束。你已经知道了两种约束,使用EditorPin和Align菜单。或者ctrl+dragging控件来实现。然后还有一种方式是使用下面的工具选项。

    Auto Layout buttons

    Align, Pin, Resolve Auto Layout Issues, and Resizing Behavior从左到右依次是对齐,固定,解决auto layout问题,重定义大小。

    前三个选项顶部的菜单栏目中都一样的,resizing behavior允许你当resize view的时候改变约束

    The pin popup

    选择pin弹出如上的筐体。然后点击四个T-bar颜色会变成solid red,最后选择add 4 constrains选项就会产生新的约束。

    Spacing to nearest neighbor

    View with the four new constraints

    选择Assistant editor中的priview也可以先预览模拟器竖屏和横屏的效果图

    Storyboard preview

    Note: Maybe you wondered why the constraint at the top of the view didn’t go all the way up to the top of the screen:

    Space at top

    Instead it stops at the status bar. But in iOS 7 the status bar is always drawn on top of the view controller — it is no longer a separate bar — so what gives? When you created the constraint it didn’t actually attach to the top of the screen but to an invisible line called the Top Layout Guide.

    On a regular view controller this guide sits at 20 points from the top of the screen, at least when the status bar is not hidden. In a navigation controller it sits below the navigation bar. Because the navigation bar has a different height in landscape, the Top Layout Guide moves with the bar when the device is rotated. That makes it easy to place views relative to the navigation bar. There is also a Bottom Layout Guide that is used for the tab bar and toolbars.

    为了不让模拟器旋转后宽度和高度发生变化,那么你可以设置宽度和高度

    Pin popup with width and height selected

    运行app,报错误

    2015-01-04 10:25:58.691 Gallery[888:279956] Unable to simultaneously satisfy constraints.
        Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
    (
        "<NSLayoutConstraint:0x7f8adae04f50 H:[UIView:0x7f8adac0b950(160)]>",
        "<NSLayoutConstraint:0x7f8adae08360 UIView:0x7f8adac0b950.leading == UIView:0x7f8adae05d80.leadingMargin + 204>",
        "<NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>",
        "<NSLayoutConstraint:0x7f8adeb6c870 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7f8adae05d80(375)]>"
    )

    Will attempt to recover by breaking constraint
    <NSLayoutConstraint:0x7f8adae04f50 H:[UIView:0x7f8adac0b950(160)]>

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
    2015-01-04 10:25:58.693 Gallery[888:279956] Unable to simultaneously satisfy constraints.
        Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
    (
        "<NSLayoutConstraint:0x7f8adae08360 UIView:0x7f8adac0b950.leading == UIView:0x7f8adae05d80.leadingMargin + 204>",
        "<NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>",
        "<NSLayoutConstraint:0x7f8adeb6c870 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7f8adae05d80(375)]>"
    )

    Will attempt to recover by breaking constraint
    <NSLayoutConstraint:0x7f8adae083b0 UIView:0x7f8adae05d80.trailingMargin == UIView:0x7f8adac0b950.trailing + 204>

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
    2015-01-04 10:25:58.693 Gallery[888:279956] Unable to simultaneously satisfy constraints.
        Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
    (
        "<NSLayoutConstraint:0x7f8adae05be0 V:[UIView:0x7f8adac0b950(284)]>",
        "<NSLayoutConstraint:0x7f8adae08400 V:[_UILayoutGuide:0x7f8adae06db0]-(81)-[UIView:0x7f8adac0b950]>",
        "<NSLayoutConstraint:0x7f8adae08450 V:[UIView:0x7f8adac0b950]-(215)-[_UILayoutGuide:0x7f8adae07ca0]>",
        "<_UILayoutSupportConstraint:0x7f8adae080f0 V:[_UILayoutGuide:0x7f8adae06db0(20)]>",
        "<_UILayoutSupportConstraint:0x7f8adae08290 V:|-(0)-[_UILayoutGuide:0x7f8adae06db0]   (Names: '|':UIView:0x7f8adae05d80 )>",
        "<_UILayoutSupportConstraint:0x7f8adae08ab0 V:[_UILayoutGuide:0x7f8adae07ca0(0)]>",
        "<_UILayoutSupportConstraint:0x7f8adae08150 _UILayoutGuide:0x7f8adae07ca0.bottom == UIView:0x7f8adae05d80.bottom>",
        "<NSLayoutConstraint:0x7f8adeb6c8c0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7f8adae05d80(667)]>"
    )

    Will attempt to recover by breaking constraint
    <NSLayoutConstraint:0x7f8adae05be0 V:[UIView:0x7f8adac0b950(284)]>

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

    还记得之前说的必须设置足够的约束来使得auto layout知道如何布局?而现在的情况是设置的约束太多了。有冲突的地方。一旦报错 “Unable to simultaneously satisfy constraints”, 就是说明你设置的约束太多了有冲突。让我们来看看怎么回事。

    Conflicting constraints

    Width and height constraints on green view

    可以看到屏幕中设置了6个约束,四个之前的约束1-4然后还有新的宽度和高度约束可以查看5和6.那么冲突在哪里呢?在竖直的模式下不应该有问题因为数学运算。superview的宽度是320 points。如果你添加水平距离长度和宽度约束,然后你应该最终得到320. 计算原则是98+160+62 = 320 (就是左边筐到view左边框的宽度+view的宽度+view右边筐到superview右边筐的距离)同样的垂直的约束应该是568 。但是当你旋转设备到横屏的状态时,窗口是568 points宽度。意思是98+160+62+?= 568.有248额外的points auto layout无法得知如何获得。
    冲突在于:要么view的宽度确定并且其中一个margins必须可变或者margins确定并且width可变。你不能同时将他们的值都设定死。所以其中一个约束需要删除。在上面的例子中,你想让view的宽度和高度在旋转时候都保持不变那么trailing 水平距离就必须要删除掉。删除右侧的horizontal space和底部的vertical space。

    Conflicting constraints fixed

    再次运行app正常了。

    Painting the portraits

    添加一个新的Label到view中去,你可以注意到guides出现了,因为它将是label的superview

    Dragging the label

    设置label的约束,水平居中布局

    Pin menu with bottom T-bar selected

    拖拉Image View进去

    Image view with constraints

    1. Drag the image view into the green view but don’t worry too much about its size or position:

    2. With the image view selected, press the Pin button and choose the following options:

    Pin menu for image view

    一定要选择Items of New Constraints给update frames选项,不要是默认的,否则auto layout会显示成如下的样子,因为你设定的frame和默认的imageview的frame有冲突所以不对。

    Misplaced image view

    当然你也可以用如下的方式来修改成这个效果Resolve Auto Layout Issues

    Resolve issues menu

    Download the resources for this tutorial 下载图片资源文件,设置Ray.png 把背景设置成白色然后把图片的适应方式设置成Aspect Fit

    Gallery with Ray

    可以发现在绿色view中的约束变成了橘色。当你设置image view的时候会出现这个问题。那么你的layout怎么会突然失效了呢?幸运的是xcode可以告诉你哪里错了。

    Content priority ambiguity error

    有一个content priority ambiguity的错误。意思是:image view和label没有固定的高度。auto layout不知道scale多少如果green view改变高度的话。(interface builder似乎忽略这点green view实际上有一个固定的高度约束)

    比如说你的green view高了100 points。那么auto layout如何在label和image view间分配这新的100 points呢?当label 还是之前的大小image view会增高100 points吗?或者当image view还是之前的大小label会增高100 points吗?他们都有额外的50 points还是他会分隔成25/75, 40/60或者其他可能的划分呢?

    如果你不解决这个问题那么auto layout就必须猜并且结果可能是出乎预料的。

    合适的解决方案是改变label的content compression resistance priority。选择label的size inspector设置vertical content compression resistance priority为751.这样label的priority就会高于image view的。设置content hugging priority为252.这两个数都是报错时候显示的建议数字。imageview的默认的夜市750,251,这样就高于imageview了

    Compression resistance priority

    警告没有了

    Adding the other heads

    把green view拖拉到左上角。使用Resolve Auto Layout IssuesUpdate Constraints.delete that “Vertical Space (-20)” constraint

    Misaligned green view

    选择⌘D来复制一个同样的并且移动到右上角,出现了橘色,设置top和trailing to right就可以了

    Duplicate view in top-right corner

    同样的复制两个再分别pin到左下和右下方

    Gallery with all 4 heads

    但是横屏的话却是有问题的

    Gallery landscape bad

    之所以这样是因为你设置了固定的宽度和高度,因此他们总是这样的高度和宽度而不会虽然superview的高度和宽度的变化而变化

    选择Width (160) and Height (284)并且删除,再次运行就会是如下的样子:

    Still bad in landscape

    Note: If you’re wondering why some of the views are larger than others, this is again related to the intrinsic content size. The size of the image determines how large the image view is; the size of the text determines how large the label is. Taken together with the constraints for the margins — 20 points on all sides — this determines the total size of each view.

    在document line中使用选择所有的有颜色的view,你可以一次添加所有的约束。在pin中选择equal widths and equal heights并且选择add 6 constraints。再次运行还是不对,但是你会发现所有的view宽度和高度都一样了。

    Add equal widths and heights constraints

    Gallery landscape equal sizes

    这是因为他们之间没有约束,auto layout不清楚如何布局他们。

    选择ray和matthijs并且选择PinHorizontal Spacing.因为他们是side by side,这样添加一个他们之间的horizontal space 0的约束并且足以让auto layout知道这两个view是有关联的。并且在ray和dennis之间添加一个EditorPinVertical Spacing

    Run the app again, and this time it looks all right:

    Gallery landscape OK

  • 相关阅读:
    java表达式, 语句, 块(翻译自Java Tutorials)
    java控制流语句(翻译自Java Tutorials)
    你可以将使用搬到ubuntu上
    python进阶学习笔记(三)
    译:selenium webdriver (python)
    异步调用轻量级封装AsynCaller
    企业开发基础设施--事件通知服务(Remoting双向通信)
    企业开发基础设施--序
    关于跨程序集的反射
    异常处理经验谈
  • 原文地址:https://www.cnblogs.com/lisa090818/p/4201347.html
Copyright © 2011-2022 走看看