【问题标题】:Xcode/IB - Autolayout, multiple Containers View and Scroll ViewXcode/IB - 自动布局、多个容器视图和滚动视图
【发布时间】:2016-07-28 14:45:04
【问题描述】:

我正在尝试使用一些容器视图在 Xcode 下构建与 IB 的接口。

我会尽力解释问题:

我有一个包含两个控制器的主场景。第一个,在场景的顶部,包含一个“Last Post View”,它从 Wordpress 网站检索最后一篇文章并显示封面图片、文章的日期和标题。

第二个包含一个集合视图,它通向其他视图。

功能独立,一切似乎都运行良好。问题是我不知道如何使用自动布局使这个“堆栈”工作并适合纵向和横向模式以及不同的设备。

这是我的故事板

Home Controller 的约束

最后一个帖子视图的限制

集合视图的约束

..最后,我得到了什么

经过数小时的搜索和尝试,我发现包含在我的 Home Controller 中的 Scroll View 必须只有一个直接子级。但我不知道如何放置不同的约束。另外,我总是收到这样的信息:“滚动视图”的可滚动内容大小不明确。

我遇到的另一个问题是,当我处于横向模式时,我无法滚动“整个视图”。充其量,我只能滚动 Collection View(当我可以显示它时),但不能滚动整个屏幕。

(如果我说我使用的是 Swift 2 可能会有所帮助)

有人有建议吗?将不胜感激!

非常感谢!

编辑 1

我尝试应用新狗的解决方案,我认为我非常接近目标,但我显然错过了一些东西。

这是我的 HomeViewController

class HomeViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var containerViewHeightConstrait: NSLayoutConstraint!
    @IBOutlet weak var lastPostContainerView: UIView!
    @IBOutlet weak var scrollContainerView: UIView!
    @IBOutlet weak var mainCollectionContainerView: UIView!

   /*************************/
   /***** VIEW DID LOAD *****/
   /*************************/

   override func viewDidLoad() {

       super.viewDidLoad()

       self.automaticallyAdjustsScrollViewInsets = false

       self.lastPostContainerView.setNeedsDisplay()
       self.mainCollectionContainerView.setNeedsDisplay()

       self.containerViewHeightConstrait.constant = UIScreen.mainScreen().bounds.height - 64

    //END viewDidLoad
    }

    ...

    /********************************/
    /***** SET CONTAINER HEIGHT *****/
    /********************************/

    func needSetContainerHeight( height: CGFloat ) {

        self.containerViewHeightConstrait.constant = height + lastPostContainerView.bounds.height + 200
        self.scrollView.contentSize.height = height + lastPostContainerView.bounds.height + 200

        print( "View Height Constrait \( self.containerViewHeightConstrait.constant )" )
        print( "Scroll View Height \( self.scrollView.contentSize.height )" )

    //END needSetContainerHeight
    }

    ...

...和我的 MainCollectionController

class MainCollectionViewController: UICollectionViewController {

    /*************************/
    /***** VIEW DID LOAD *****/
    /*************************/

    override func viewDidLoad() {

        super.viewDidLoad()

        collectionView!.autoresizingMask = [ .FlexibleWidth ]

    //END viewDidLoad
    }

    /****************************************/
    /****************************************/

    /***************************/
    /***** VIEW DID APPEAR *****/
    /***************************/

    override func viewDidAppear( animated: Bool ) {

        super.viewDidAppear( animated )
        ( self.parentViewController as! HomeViewController ).needSetContainerHeight( self.collectionView!.contentSize.height )

    //END viewDidAppear
    }

    ...

如果我很好地理解了提议的内容,那么约束应该是这样的:

(主)视图

滚动视图

子视图容器

最后一个帖子容器

集合容器

所有约束的列表

...以及我得到的结果

肖像

风景

我用不同的额外约束进行了一些测试,我发现我必须告诉 Scroll View 填充其整个父级以在屏幕上显示某些内容(否则,我只会得到红色背景)。

另一件事是,如果我为 Last Post Container 和 Collection Container 之间的空间添加一个约束,事情就“很好”地定位,但我不能再点击集合的单元格了。但是,如果我不添加这个约束,事情会更加混乱(例如,集合视图与帖子视图重叠),但我可以点击单元格。

不幸的是,屏幕似乎被裁剪了,当我旋转屏幕时会有一些差异。但我认为我必须在设备旋转时重新计算高度(对吗?)。屏幕顶部的边距仍然存在,但并非总是如此:这取决于我启动应用程序的模式以及我旋转了多少次。

我忘了提到的另一件事是,最后一篇文章是异步检索的。因此,在显示主屏幕之后显示具有可变大小的封面图像。我将其移至 AppDelegate - didFinishLaunchingWithOptions 并将帖子存放在通知中心,但不幸的是,仍有一些延迟。

有什么建议吗? :)

解决方案

就像新狗说的,使用collection view的header section(Accessories/Section Header)要容易得多。

【问题讨论】:

    标签: ios swift xcode autolayout interface-builder


    【解决方案1】:

    你需要解决以下问题:

    1. 在你家的意义上,viewdidload,添加如下代码:

      self.automaticallyAdjustsScrollViewInsets = false 这可以使导航栏和您的图片之间的红色区域消失。

    2. 修复了“滚动视图”的可滚动内容大小不明确的问题: 这是因为滚动视图不知道它会显示的内容大小。您需要重置视图的约束(两个容器视图的超级视图),我将其称为滚动容器视图:

    scrollcontainerview.leading = scrollview.leading

    scrollcontainerview.trailing = scrollview.trailing

    scrollcontainerview.top = scrollview.top

    scrollcontainerview.bottom = scrollview.bottom

    scrollcontainerview.width = self.view.width

    scrollcontainerview.height = 603 //我们会通过代码改变这个值

    现在“滚动视图的可滚动内容大小不明确”错误应该消失了。

    1. 更改代码中的scrollcontainerview.height: 在您的家庭场景中,将 scrollcontainerview.height 约束拖到您的视图控制器中,并将其更改为适合屏幕:

      @IBOutlet 弱变量 contianerViewHeightConstrait: NSLayoutConstraint!

       override func viewDidLoad() {
          super.viewDidLoad()
      
          self.automaticallyAdjustsScrollViewInsets = false
          //because we set the height at const 603,but height is different on different device,so we need chang it to the correct value
      
          contianerViewHeightConstrait.constant =       UIScreen.mainScreen().bounds.height - 64
      
      }
      

    现在你可以看到两个容器视图填满了屏幕。

    1. 需要滚动整个内容,而不仅仅是集合视图: 要解决此问题,您需要为 scrollview.contentsize.height 分配正确的高度。 在你的集合视图控制器中:
     override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        (self.parentViewController as!    HomeScenceViewController).needSetContainerHeight(self.collectionView.contentSize.height)
    }
    

    然后在 HomeScenceViewController 中添加一个方法

     // set the containerview and scrollview height
        func needSetContainerHeight(height:CGFloat){
            //the 200 is your first container view's height
            contianerViewHeightConstrait.constant = height + 200
            scrollview.contentSize.height = height + 200
        }
    

    现在你应该可以滚动整个内容了

    【讨论】:

    • 非常感谢您的回答!我会尽快尝试!
    • 嗨!我试图应用你的解决方案,我认为我已经很接近目标了,但我显然错过了一些东西。你有什么建议吗?
    • @LancelotKiin 考虑使用supplementheader而不是你最后发布的容器视图,那么整个视图只是一个collectionview,那么你就不会为scrollview contentsize而烦恼
    • @LancelotKiin 在你的代码中需要setcontainerheight.,你不需要加 200,我的代码中的 200 代表你上次发布的容器高度。我建议你使用collectionview来构建整个场景。
    • 绝对!我没想到!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    相关资源
    最近更新 更多