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

6

我有一个嵌套在容器中的视图控制器内部的滚动视图。使用指定类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.
    }
}

基本上正在发生的是,使用该类SubProfileOneViewControllerSubProfileTwoViewController的两个视图控制器分别被实例化为subOnesubTwo。然后将它们作为子级添加到滚动视图中,以创建一个接口,用户可以向右滑动来访问另一个视图(几乎像 Snapchat)。 subOnesubTwo应该并排并且用户应该能够从一个滚动到另一个。

这就是我的故事板上的样子: enter image description here

SubProfileOneViewControllerSubProfileTwoViewController各自有一个视图(分别由绿色和红色表示),并且每个视图具有相同的约束条件,即:高度= 262,距离父视图的右边界= 0,距离父视图的左边界= 0,距离父视图的顶部= 0

理想情况下,运行时应该有两个视图,一个绿色,一个红色,用户应该能够在它们之间滑动。然而,实际上发生的是:绿色和红色视图没有占据整个屏幕宽度,而是被压缩成左侧的小条状,并且大部分视图控制器是白色而不是它们各自的颜色。我尝试了很多方法,但不确定我做错了什么。 (代码中的credit归功于github上lbrendanl的ScollingViewController,链接在此:https://github.com/lbrendanl/SwiftSwipeView)

你在scrollview中使用了哪些container views的约束条件?你能发布一个示例项目吗? - Mahesh Agrawal
我会在你的UIScrollView中添加一个单独的UIView(contentView)。然后在内容视图中添加子控制器视图。为子视图添加约束,将它们的顶部和底部固定到内容视图上。对于视图一,将其前导固定到内容视图,然后将其尾随固定到视图二的前导。最后将视图二的尾随固定到内容视图上。为了强制宽度正确,您需要为视图一和视图二的宽度添加约束:或者为contentView添加一个宽度约束为x2屏幕大小,并添加视图一和视图二的等宽约束。 - Rory McKinnel
2个回答

2

使用自动布局的ScrollView的行为与设置子视图数量有关, 你可以通过将translatesAutoresizingMaskIntoConstraints = true并显式设置contentSize,仅使用一个子视图;或者你可以将translatesAutoresizingMaskIntoConstraints = false并让它自己找出约束。详细信息请访问此链接

如果您希望两个视图占用整个屏幕,则需要添加自动布局约束,类似于以下内容:

  1. 将greenView左边固定到父视图
  2. 将greenView的宽度设置为scrollViewWidth相同,即bounds.size.width(而不是contetnSizeWidth)
  3. 将redView的左侧固定到greenView的右侧
  4. 将redView的宽度值设置为scrollViewWidth相同,即bounds.size.width(而不是contetnSize.width)

2
注意:我建议使用自动布局解决方案,它会自动处理方向更改、屏幕大小等问题,代码量更少,解决方案更健壮,比我下面开发的方法要好得多。
使用嵌入的 UIViewController 的当前方法需要等待这些控制器完成各自的初始化,这与您的布局直接竞争。请注意,您需要在方向更改时重新计算位置和大小。虽然这种方法可行,但不是一个合理的设计,因为它需要大量的代码、逻辑和一般功能,而使用 NSLayoutConstraint 可以免费获得这些功能。
(已测试、构建、链接和运行):
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)
}

这是滚动效果(演示)。请注意,我创建了ViewLayoutAssistant.swift类的视图,它可以方便地可视化位置和缩放。

enter image description here

您也不需要告诉视图其层次结构已更改。以下代码应该能帮助您继续:
@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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接