的UIScrollView contentSize不工作

问题描述 投票:55回答:14

我把我的笔尖的UIScrollView一个view,它链接到一个IBOutlet属性。

现在,我做这在我的viewDidLoad方法时,它似乎对contentSize没有影响:

self.sv.backgroundColor = [UIColor yellowColor]; // this works
CGSize size =  CGSizeMake(1000.0, 1000.0); 
[self.sv setContentSize:size]; // this does not

它的行为就好像contentSize是一样的框架。这是怎么回事?这开始时,我关掉自动版式工作。为什么?

objective-c ios uiscrollview
14个回答
79
投票

我有同样的问题。自动布局UIScrollView被搞砸了。

解决方法:把一切都在UIScrollView到另一个UIView,并把该UIView作为UIScrollView唯一的孩子。然后你可以使用自动布局。

如果临近年底的事情被搞砸了(无论您的方向滚动UIScrollView的结束),在年底改变约束有可能的最低优先级。


1
投票

我以前做成立的UIScrollView编程,直到我看了下面的精彩教程,如何一步一步得到的UIScrollView和UIView的工作:https://www.youtube.com/watch?v=PgeNPRBrB18

观看视频后,你会开始喜欢Interface Builder的,我相信。

投票了


1
投票

如果您正在使用AutoLayout一个非常简单的方法来设置contentSizeUIScrollView只是增加是这样的:

CGFloat contentWidth = YOUR_CONTENT_WIDTH;

NSLayoutConstraint *constraintWidth = 
 [NSLayoutConstraint constraintWithItem:self.scrollView 
                              attribute:NSLayoutAttributeTrailing 
                              relatedBy:NSLayoutRelationEqual 
                                 toItem:self.scrollView 
                              attribute:NSLayoutAttributeLeading 
                             multiplier:1 
                               constant:contentWidth];

[self.scrollView addConstraint:constraintWidth];

1
投票

当标签的动态高度超过视图高度还没滚动。

我做了什么,上面是正确的说是做yuf的回答标记(我增加了一个内容视图,以我的滚动视图和设置的约束前置,顶部底部和相等的宽度从内容视图滚动视图)。但是我的观点是当内部控制高度超出滚动视图的高度不滚动。

enter image description here

在我的内容视图我有一个形象和它下面的3个标签。每个标签调整自己的高度依赖于有多少文字是他们(它们被设置为自动换行和numberoflines = 0来实现这一点)。

我的问题是我的内容视图的高度不符合标签的动态高度调节,当他们超过了滚动视图/主视图的高度。

为了解决这个问题我措辞了,我需要设置的底部空间,以我的底部标签和内容查看之间的集装箱约束并赋予它值40(任意选择给它在底部一个不错的保证金)。现在,这意味着我的内容查看调整其高度,使存在的最后一个标签的底部之间的空间,本身和它完美的滚动!

耶!


1
投票

尝试了这一点... 添加的所有约束像你这样做UIView(见我的故事板ViewControler的截图) enter image description here 现在招开始。选择您的最后一个对象,并选择其底部约束。 (见上面的截图,Instagram的按钮的底部约束(黄线))和波纹管截图更改尺寸检查恒等。

enter image description here

我需要不断= 8,但你可以按您的要求而改变。这个不变的是橙色按钮的底部和滚动视图之间的空间。

编辑

确保你的视图的层次结构。

0)ViewController.view(可选) 1)的UIScrollView 2)的UIView(重命名为 “内容查看”) 3)的UIView(这种看法是你的内容,这将使滚动视图滚动)


0
投票

我自动布局为分页滚动视图,其页面占据了屏幕的全宽工作。该页面根据滚动视图的大小自动调整。我没有测试过这对于较小的宽度滚动视图但评论的路程,如果它的工作原理 - 我beleieve它应该。针对iOS的9,在斯威夫特2编写代码,使用兴业银行的awakeFromNib混合和自定义代码。

脚步:

  • 定义一个全屏幕滚动视图。
  • 里面的滚动视图中添加UIView(我叫雷contentView),其顶部,后,底部和前缘滚动视图都为零;高度等于滚动视图;但宽度是滚动视图的宽度乘以页数。如果你这样做视觉上,你会看到你的内容视图超出在Inteface生成器滚动视图。
  • 对于每一个“页”的contentView内,加自动布局规则,把它们并排侧对方,但最重要的是,给他们每人一个约束,使它们的宽度等于滚动视图,而不是内容视图的。

下面的示例代码。 embedChildViewController是增加孩子的风险投资只是我的简便方法 - 不要看setupLayoutRulesForPages。我有整整两页所以功能过于简单,但可以将其扩大到您的需求。

在我的视图控制器:

override func loadView() {
    self.view = self.customView
}

override func viewDidLoad() {
super.viewDidLoad()

self.embedChildViewController(self.addExpenseVC, toView: self.customView.contentView, fillSuperview: false)
self.embedChildViewController(self.addCategoryVC, toView: self.customView.contentView, fillSuperview: false)
self.customView.setupLayoutRulesForPages(self.addExpenseVC.view, secondPage: self.addCategoryVC.view)
}

我的自定义视图:

class __AMVCView: UIView {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!

    override func awakeFromNib() {
        super.awakeFromNib()

        self.scrollView.pagingEnabled = true
        self.scrollView.bounces = true
        self.scrollView.showsHorizontalScrollIndicator = false
        self.scrollView.showsVerticalScrollIndicator = false

        self.pageControl.numberOfPages = 2

        self.contentView.backgroundColor = UIColor.blueColor()
        self.scrollView.backgroundColor = UIColor.clearColor()
        self.backgroundColor = UIColor.blackColor()
    }

    func setupLayoutRulesForPages(firstPage: UIView, secondPage: UIView) {
        guard self.contentView.subviews.contains(firstPage) && self.contentView.subviews.contains(secondPage)
            else {
                return
        }

        let rules = [
            "H:|-0-[firstPage]-0-[secondPage]-0-|",
            "V:|-0-[firstPage]-0-|",
            "V:|-0-[secondPage]-0-|"
        ]
        let views = [
            "firstPage" : firstPage,
            "secondPage" : secondPage
        ]
        let constraints = NSLayoutConstraint.constraintsWithVisualFormatArray(rules, metrics: nil, views: views)

        UIView.disableAutoresizingMasksInViews(firstPage, secondPage)
        self.addConstraints(constraints)

        // Add the width Autolayout rules to the pages.
        let widthConstraint = NSLayoutConstraint(item: firstPage, attribute: .Width, relatedBy: .Equal, toItem: self.scrollView, attribute: .Width, multiplier: 1, constant: 0)
        self.addConstraint(widthConstraint)
    }

}

67
投票

我试图viewWillLayoutSubviews更新滚动视图的contentSize,它为我工作。

- (void)viewDidLayoutSubviews
{
  [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
}

Apple Doc

-(void)viewDidLayoutSubviews

调用,以通知其观点,刚刚公布其子视图的视图控制器。

讨论

当界视图控制器的看法改变,视图调整其子视图的位置,然后系统会调用这个方法。然而,被称为这个方法并不表明视图的子视图的各个布局进行了调整。每个子视图负责调整自己的布局。

您的视图控制器可以重写此方法来更改视图勾画出它的子视图后。此方法的默认实现不执行任何操作。


21
投票

最简单的/清洁的方法是在viewDidAppear所以你否定的自动版式的效果设置contentSize。这不涉及添加随机的意见。然而依靠负载为了工作的实施可能不是最好的主意。


14
投票

这里有两个问题。 (1)viewDidLoad中太早;你必须等待,直到布局发生之后。 (2)如果你想与来自笔尖滚动型使用自动布局,那么无论你必须使用约束完整地描述contentSize的大小(然后你不要在代码中设置contentSize的话),或者,如果你想将其设置在代码中,必须防止滚动视图的子视图的约束从口授contentSize。这听起来像你想这样做后者。要做到这一点,你需要充当滚动视图的唯一顶级子视图的UIView,并在代码中,你必须将其设置为不使用自动布局,使得其autoresizingMask和消除它的其他外部约束。我展示了如何做到这一点,下面的例子:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m

但也注意到下面的例子,它展示了如何完全使用约束,而不是contentSize


14
投票

A SUPER easy way to use AutoLayout with UIScrollViews inside Interface Builder:

第1步:创建一个UIScrollView

第2步:创建一个UIView就是喜欢让你的滚动视图的孩子:

-UIScrollView
---UIView
-----Your other content

(我们将其命名为contentView)。

步骤3:在尺寸检查器中,得到这一观点的高度和宽度(比如说,320x700)。

第4步(使用自动版式):创建一个从你的contentView到它的父(在UIScrollView)明确的限制:连接4个边缘(顶部,前置,底部),然后给它一个定义的宽度和高度,你希望它太滚动。

例如:如果你的滚动视图跨越整个屏幕,可以给你的内容查看[设备宽度]和600的高度的宽度;然后它会设置UIScrollView相匹配的内容大小。

要么:

步骤4(不使用自动版式):使用IB(CTRL +拖动从每个控制到您的视图控制器的.H @implementation)这两种新的控制的连接到视图控制器。假设每个被称为scrollViewcontentView,分别。它应该是这样的:

@interface YourViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, nonatomic) IBOutlet UIView *contentView;

@end

步骤5(不使用自动版式):在视图控制器的.h文件中加载(实际上,覆盖)下面的方法:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

12
投票

使用此代码。滚动型setContentSize应该被称为在主线程异步。

迅速:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    DispatchQueue.main.async {
        var contentRect = CGRect.zero

        for view in self.scrollView.subviews {
           contentRect = contentRect.union(view.frame)
        }

        self.scrollView.contentSize = contentRect.size
    }
}

目标C:

 - (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];

     dispatch_async(dispatch_get_main_queue(), ^ {
                        CGRect contentRect = CGRectZero;

                        for(UIView *view in scrollView.subviews)
                           contentRect = CGRectUnion(contentRect,view.frame);

                           scrollView.contentSize = contentRect.size;
                       });
}

5
投票

您可以使用此代码行到你的* .m文件的

- (void)viewDidLoad{
   [scroll setContentSize:CGSizeMake(320, 800)]   ;
   [scroll setScrollEnabled:TRUE];
   [scroll setShowsVerticalScrollIndicator:NO];
   [scroll setShowsHorizontalScrollIndicator:YES];
}    

为此,你需要采取的UIScrollView的一个IBOutlet属性到您的* .h文件中这样说:

IBOutlet UIScrollView *scroll;

而从故事板连接这一点。

要么,

您可以使用此方法到您的* .m文件:

-(void)viewDidLayoutSubviews 
{
  [scroll setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
   // this will pick height automatically from device's height and multiply it with 1.5  
}

这两种解决方案适用于我在Xcode-5,Xcode的-6,Xcode的-6.1,Xcode的-6.2


3
投票

viewDidAppear设置contentSize是至关重要的。

但我也有什么在3.5英寸的屏幕工作的变化,以及4英寸的屏幕。 4英寸大屏的工作,旧的一个没有。不论是iOS 7,离奇的是一种轻描淡写!


1
投票

基于约束的工作,我永远无法得到自动布局。而忽略了汽车的布局零高度setContentSize:消息自从我看来已经是一个子类的UIScrollView我通过重写的setContentView解决它。

@interface MyView : UIScrollView {}
@end

@implementation MyView
- (void)setContentSize:(CGSize)aSize {
    if (aSize.height > 0)
        [super setContentSize:aSize];
}
@end
© www.soinside.com 2019 - 2024. All rights reserved.