简体   繁体   English

iOS自动布局约束和框架无法正常工作

[英]iOS Auto-layout constraints and frames not working

I have a Scroll View nested inside a View Controller which is rested in a Container. 我有一个嵌套在View Controller中的Scroll View,它停放在Container中。 The View Controller, which uses a specified class called ScrollingViewController looks like this: View Controller使用一个名为ScrollingViewController的指定类,如下所示:

class ScrollingViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView! //outlet for the Scroll View

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1) Create the two views used in the swipe container view
        var storyboard = UIStoryboard(name: "App", bundle: nil)
        var subOne: SubProfileOneViewController = storyboard.instantiateViewControllerWithIdentifier("subone") as! SubProfileOneViewController
        var subTwo: SubProfileTwoViewController = storyboard.instantiateViewControllerWithIdentifier("subtwo") as! SubProfileTwoViewController

        // 2) Add in each view to the container view hierarchy
        //    Add them in opposite order since the view hierarchy is a stack
        self.addChildViewController(subTwo);
        self.scrollView!.addSubview(subTwo.view);
        subTwo.didMoveToParentViewController(self);

        self.addChildViewController(subOne);
        self.scrollView!.addSubview(subOne.view);
        subOne.didMoveToParentViewController(self);

        // 3) Set up the frames of the view controllers to align
        //    with each other inside the container view
        var adminFrame :CGRect = subOne.view.frame;
        adminFrame.origin.x = adminFrame.width;
        subTwo.view.frame = adminFrame;

        // 4) Finally set the size of the scroll view that contains the frames
        var scrollWidth: CGFloat  = 2 * self.view.frame.width
        var scrollHeight: CGFloat  = 262
        self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight);
        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Basically what's happening is that two View Controllers that use that class SubProfileOneViewController and SubProfileTwoViewController , respectively, are being instantiated as subOne and subTwo . 基本上发生的事情是,分别使用该类SubProfileOneViewControllerSubProfileTwoViewController两个View控制器被实例化为subOnesubTwo These are then added into the Scroll View as children in order to create an interface where the user can swipe right to access another view (almost like Snapchat). 然后将这些作为子项添加到Scroll View中,以创建一个界面,用户可以向右滑动以访问另一个视图(几乎像Snapchat)。 subOne and subTwo should be side by side and the user should be able to scroll from one to the next and vice versa. subOnesubTwo应该是并排的,用户应该能够从一个滚动到下一个,反之亦然。

Here's what this all looks like on my storyboard: 以下是我的故事板上的所有内容: 在此输入图像描述

SubProfileOneViewController and SubProfileTwoViewController each have a view (represented by green and red respectively) and each have the same exact constraints which are: Height = 262, Trailing space to superview = 0, Leading space to superview = 0, Top space to superview = 0 SubProfileOneViewControllerSubProfileTwoViewController每个都有一个视图(分别用绿色和红色表示),每个都有相同的精确约束:Height = 262,superview的尾随空间= 0,superview的前导空间= 0,superview的顶部空间= 0

Ideally, when run, there should be two views, one green and one red and the user should be able to swipe between each one. 理想情况下,在运行时,应该有两个视图,一个绿色和一个红色,用户应该能够在每个视图之间滑动。 However, here's what actually happens: 但是,这是实际发生的事情: 在此输入图像描述

The green and red views don't take up the entire screen width and instead are condensed into a small sliver on the left, and the majority of the View Controllers are white instead of their respective color. 绿色和红色视图不会占据整个屏幕宽度,而是会在左侧压缩成一个小条子,而大多数视图控制器都是白色而不是各自的颜色。 I've tried many things and I'm not sure what I'm doing wrong. 我尝试了很多东西,但我不确定我做错了什么。

(credit for code in ScollingViewController goes to lbrendanl on github, linked here: https://github.com/lbrendanl/SwiftSwipeView ) ScollingViewController中代码的ScollingViewController归到github上的lbrendanl,链接到这里: https//github.com/lbrendanl/SwiftSwipeView

Note: I would recommend using an Autolayout solution, which will automatically handle orientation changes, screen sizes, all with much less code and more robust solution than what I develop below . 注意: 我建议使用Autolayout解决方案,该解决方案将自动处理方向更改,屏幕尺寸,所有代码和更强大的解决方案都比我在下面开发的解决方案更好

With the current approach, using embedded UIViewControllers , you must wait for these controllers to complete their respective initializations, which are in direct competition with your layout. 使用当前的方法,使用嵌入式 UIViewControllers ,您必须等待这些控制器完成各自的初始化,这与您的布局直接竞争。 Note that you will need to recalculate positions + sizes upon orientation changes . 请注意,您需要在方向更改时重新计算位置+大小 Again, while this works, it is not a sound design since it calls for a lot of code, logic, and general functionalities you would get for free using NSLayoutConstraint . 同样,虽然这有效,但它不是一个合理的设计,因为它需要使用NSLayoutConstraint免费获得的大量代码,逻辑和一般功能。

( tested, built, linked and ran ): 测试,构建,链接和运行 ):

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    // 3) Set up the frames of the view controllers to align
    //    with each other inside the container view
    var adminFrame = self.view.frame
    subOne.view.frame = adminFrame
    adminFrame.offset(dx: self.view.frame.width, dy: 0)
    subTwo.view.frame = adminFrame;

    // 4) Finally set the size of the scroll view that contains the frames
    let scrollWidth = 2 * self.view.frame.width
    self.scrollView!.contentSize = CGSizeMake(scrollWidth, self.view.frame.height)
}

Here is the scrolling ( in action ). 这是滚动( 在行动中 )。 Notice that I created views of class ViewLayoutAssistant.swift which allows you to visualize position + scale very conveniently. 请注意,我创建了ViewLayoutAssistant.swift类的视图,它允许您非常方便地可视化位置+比例。

在此输入图像描述

You also do not need to tell the view its hierarchy has changed. 您也不需要告诉视图其层次结构已更改。 This last bit of code should get you going: 最后一点代码应该让你去:

@IBOutlet weak var scrollView: UIScrollView!
weak var subOne: SubProfileOneViewController!
weak var subTwo: SubProfileTwoViewController!

    self.addChildViewController(subTwo);
    self.scrollView!.addSubview(subTwo.view);
    self.addChildViewController(subOne);
    self.scrollView!.addSubview(subOne.view);

ScrollView with auto layout works differently either you can use only one subview by setting translatesAutoresizingMaskIntoConstraints = true and setting contentSize explicitly. 具有自动布局的ScrollView的工作方式不同,您可以通过设置translatesAutoresizingMaskIntoConstraints = true并显式设置contentSize来仅使用一个子视图。 Or you set translatesAutoresizingMaskIntoConstraints = false and let it find out constraint it self. 或者你设置translatesAutoresizingMaskIntoConstraints = false并让它找出它自己的约束。 Visit this link for more details 请访问此链接了解更多详情

As you want both should take full screen then you need to add AutoLayoutConstraints, something like this 如你所愿,两者都应该全屏,然后你需要添加AutoLayoutConstraints,就像这样

  1. Pin greenView left to super view 将绿色视图固定为超级视图
  2. Set greenView width to same as scrollViewWidth ie bounds.size.width (not contetnSizeWidth) 将greenView宽度设置为与scrollViewWidth相同,即bounds.size.width(不是contetnSizeWidth)
  3. Pin redView left to greenView right 将redView固定为绿色视图右侧
  4. set redView width value same as scrollViewWidth ie bounds.size.width (not contetnSize.width) 设置与scrollViewWidth相同的redView宽度值,即bounds.size.width(不是contetnSize.width)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM