为啥水平滚动视图内容之间存在差距?

Posted

技术标签:

【中文标题】为啥水平滚动视图内容之间存在差距?【英文标题】:Why is there a gap between horizontal scrollview content?为什么水平滚动视图内容之间存在差距? 【发布时间】:2015-07-27 15:54:49 【问题描述】:

我设置了一个UIScrollView,其中包含两个ViewController's。这就是我的viewDidLoad 的样子:

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    scrollView.delegate = self

    self.automaticallyAdjustsScrollViewInsets = false

    let allViewController = self.storyboard!.instantiateViewControllerWithIdentifier("All") as! AllViewController;
    let favoritesViewController = self.storyboard!.instantiateViewControllerWithIdentifier("Favorites") as! FavoritesViewController;

    scrollView!.contentSize = CGSizeMake(2*CGRectGetWidth(allViewController.view.frame), CGRectGetHeight(scrollView!.frame));

    let viewControllers = [allViewController, favoritesViewController]

    var idx:Int = 0;

    for viewController in viewControllers 
        addChildViewController(viewController);
        let originX:CGFloat = CGFloat(idx) * CGRectGetWidth(scrollView!.frame);
        viewController.view.frame = CGRectMake(originX, 0, viewController.view.frame.size.width, viewController.view.frame.size.height);
        scrollView!.addSubview(viewController.view)
        viewController.didMoveToParentViewController(self)
        idx++;
     

在 iPhone 6 模拟器上一切正常,但是当我在 iPhone 5 模拟器上运行它时,滚动时控制器之间存在间隙:

[] scrollView 的前导、尾随、顶部和底部的自动布局设置为 0。

【问题讨论】:

【参考方案1】:

如果您想在viewDidLoad: 中设置原点,并且您肯定知道滚动视图将具有屏幕宽度,请在计算逻辑中而不是CGRectGetWidth(scrollView!.frame) 使用

var bounds = UIScreen.mainScreen().bounds
var width = bounds.size.width

为了在您的子视图进行布局之前获得适当的宽度。

代码: Working Github Project

统一更新: 正如这里有人提到的,我取消选中滚动视图的Autoresize Subviews 属性,子类化UITableViewCell 并将我的提交推送到github。通过我上面提供的链接检查它。这是按钮向右对齐的结果:

结果:

参考: 主要概念在我的 SO 回答 here

中进行了描述

【讨论】:

还是不行,现在间隙是一半大小,另一半出现在第二个视图控制器之后……所以绿色->白色(间隙)->紫色->白色跨度> 谢谢,它现在可以工作了。我会在 12 小时内将赏金奖励给你。我只有一个最后的问题。我的测试项目可以正常工作,但是在我的真实项目(实现 UITableViewDelegate、UITableViewDataSource 的 UIViewControllers)中有两个 tableview 而不是 viewcontroller,并且我在 UITableViewCell 的右侧有一个按钮,我也在那里进行了更改,但是我仍然看不到牢房的右侧,它在碎石的外面。有什么建议为什么会发生这种情况? @Adrian,可以在 3-4 小时内试用您的案例,并将发布更新的项目 @Adrian 请查看我的更新答案,请不要忘记奖励赏金 :) 顺便说一句,我看到您使用的是 4 英寸故事板....如果我在您的项目中使用 4.7 英寸故事板,那么我仍然有我的问题,没有看到右侧按钮。如果您有时间,您可以更新以使用 4.7 故事板吗?我会很感激的。【参考方案2】:

您在视图中设置视图控制器位置确实加载。此时,视图的尺寸将与您的故事板中的视图大小相匹配。我假设您在情节提要中使用 4.7" 视图。这意味着在 viewDidLoad 中,您将第二个视图控制器的 x 位置设置为 375。在 viewWillAppear 或 didLayoutSubviews 中设置视图控制器位置以获得正确的宽度视图(iPhone 5 上为 320)。请注意,这两个方法都可以多次调用,因此请相应计划。

【讨论】:

我已经在 viewWillAppear 中设置了滚动视图的内容大小,但它的行为是一样的。是的,我正在使用 4.7 故事板 viewWillAppear: 也太早了。您应该在viewDidLayoutSubviews 中设置框架,或者创建约束来布置它们。您可以在viewDidLoad 中创建约束。 即使在viewDidLayoutSubviews中,还是有差距的。我在情节提要中设置了约束 您在情节提要中设置了哪些约束?这些约束是否限制了在滚动视图中设置视图控制器的位置? 对于滚动视图 0 到顶部/底部/前导/尾随【参考方案3】:

如果您的子视图应始终为滚动视图的大小,最简单的解决方案可能是添加 UIScrollView 的自定义子类,该子类仅按添加顺序排列所有子视图,如下所示:

import UIKit

class MyScrollView: UIScrollView 

    override func layoutSubviews() 
        super.layoutSubviews()
        var idx:Int = 0;
        contentSize = CGSizeMake(2*CGRectGetWidth(bounds), CGRectGetHeight(bounds));
        for sview in self.subviews as! [UIView] 
            let originX:CGFloat = CGFloat(idx) * CGRectGetWidth(bounds);
            sview.frame = CGRectMake(originX, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds));
            idx++
        
    


然后您可以将 viewDidLoad 简化为

override func viewDidLoad() 
    super.viewDidLoad()

    self.automaticallyAdjustsScrollViewInsets = false

    let allViewController = self.storyboard!.instantiateViewControllerWithIdentifier("All") as! AllViewController;
    let favoritesViewController = self.storyboard!.instantiateViewControllerWithIdentifier("Favorites") as! FavoritesViewController;

    for viewController in [allViewController, favoritesViewController] 
        addChildViewController(viewController);
        scrollView!.addSubview(viewController.view)
        viewController.didMoveToParentViewController(self)
    

【讨论】:

是的,这也一定需要。 更改了禁用子视图布局的建议,以在 UIScrollView 的自定义子类中手动布局子视图。将处理呼叫状态栏中的旋转和大小更改,ios 9 多任务处理中的大小更改等【参考方案4】:

在你的滚动视图中添加两个子视图作为占位符,并在它们和滚动视图之间添加约束,并将两个@IBOutlet 设置为占位符。 在 viewDidLoad 中只需设置 scrollView 大小,添加 childViewControlers 并将其视图添加到占位符

【讨论】:

以上是关于为啥水平滚动视图内容之间存在差距?的主要内容,如果未能解决你的问题,请参考以下文章

在导航控制器中使用 Auto Layout 的主视图和滚动视图之间的差距

如何根据文本视图内容大小设置滚动视图中的启用或禁用滚动?

为啥视图和文本输入之间存在差距?

当我开始水平滚动时,为啥我的收藏视图中的单元格被取消选择?

有没有更好的方法在不同的表格视图之间进行水平滚动?

视图之间的水平“制表符”滚动