UIScrollView contentSize不起作用
我把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
与框架一样。 这是怎么回事? 当我closuresAutoLayout时,这开始工作。 为什么?
我有同样的问题。 UIScrollView
自动布局是搞砸了。
解决办法:将UIScrollView
所有内容放入另一个UIView
,并将该UIView
作为UIScrollView
的唯一子对象。 然后你可以使用自动布局。
如果接近尾声的东西被搞乱了( UIScrollView
滚动的方向的结束),那么改变最后的约束以获得尽可能低的优先级。
我试图viewWillLayoutSubviews更新scrollView的contentSize,它为我工作。
- (void)viewDidLayoutSubviews { [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)]; }
苹果文件
-(void)viewDidLayoutSubviews
打电话通知视图控制器,它的视图刚刚布置了它的子视图。
讨论
当视图控制器视图的边界发生变化时,视图会调整其子视图的位置,然后系统会调用此方法。 但是,调用此方法并不表示视图子视图的各个布局已被调整。 每个子视图负责调整自己的布局。
你的视图控制器可以重写这个方法来在视图布局子视图之后进行更改。 这个方法的默认实现什么也不做。
最简单/最干净的方法是将contentSize设置为viewDidAppear,这样可以抵消自动布局的效果。 这不涉及添加随机视图。 然而,依靠加载顺序来执行实施可能不是最好的主意。
这里有两个问题。 (1)viewDidLoad太快; 你必须等到布局完成之后。 (2)如果你想使用来自nib的滚动视图的自动布局,那么你必须使用约束来完整地描述contentSize
的大小(然后你根本不需要在代码中设置contentSize
),或者,如果你想在代码中设置它,你必须防止 scrollview子视图上的约束来指定contentSize
。 这听起来像你想要做后者。 为此,您需要一个UIView作为scrollview的唯一顶层子视图,在代码中,您必须将其设置为不使用自动布局,启用其autoresizingMask
并删除其他外部约束。 我展示了一个如何做到的例子,在这里:
但是请注意下一个示例,它显示了如何完全使用约束, 而不是 contentSize
。
在Interface Builder中使用UIScrollViews使用AutoLayout的超级简单方法:
第1步:创build一个UIScrollView
第2步:创build一个UIView
,这是你的滚动视图的孩子,如下所示:
-UIScrollView ---UIView -----Your other content
(我们将称这一个contentView
)。
步骤3:在尺寸检查器中,给这个视图的高度和宽度(比如320×700)。
第4步(使用AutoLayout):从你的contentView
到它的超级视图( UIScrollView
)创build明确的约束:连接4个边(顶部,前导,尾部,底部),然后给它定义的宽度和高度,也希望它滚动。
例如:如果您的滚动视图跨越整个屏幕,您可以给您的内容视图宽度[设备宽度]和高度600; 它会设置UIScrollView
的内容大小以匹配。
要么:
第4步(不使用AutoLayout):使用IB(Ctrl +从每个控件拖动到视图控制器的.h @实现)将这两个新的控件连接到你的视图控制器。 我们假设每个分别被称为scrollView
和contentView
。 它应该是这样的:
@interface YourViewController : UIViewController @property (strong, nonatomic) IBOutlet UIScrollView *scrollView; @property (strong, nonatomic) IBOutlet UIView *contentView; @end
第5步(不使用AutoLayout):在视图控制器的.h文件中添加(实际上覆盖)以下方法:
-(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.scrollView.contentSize = self.contentView.frame.size; }
使用这个代码。 ScrollView的setContentSize应该在主线程中调用async。
- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; dispatch_async(dispatch_get_main_queue(), ^ { CGRect contentRect = CGRectZero; for (UIView *view in scrollView.subviews) contentRect = CGRectUnion(contentRect, view.frame); contentRect.size.height=contentRect.size.height; scrollView.contentSize = contentRect.size; }); }
你可以在你的* .m文件中使用这行代码
- (void)viewDidLoad{ [scroll setContentSize:CGSizeMake(320, 800)] ; [scroll setScrollEnabled:TRUE]; [scroll setShowsVerticalScrollIndicator:NO]; [scroll setShowsHorizontalScrollIndicator:YES]; }
为此,您需要将UIScrollView的IBOutlet属性以这种方式放入您的* .h文件中:
IBOutlet UIScrollView *scroll;
并从Storyboard连接这个。
要么,
你可以在你的* .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 }
这两个解决scheme适用于我在xcode-5,xcode-6,xcode-6.1,xcode-6.2
在viewDidAppear
设置contentSize至关重要。
但我也有一个在3.5英寸的屏幕和4英寸的屏幕工作的变化。 4英寸的屏幕工作,年纪较大的没有。 这两个iOS 7.奇怪是轻描淡写!
我永远不能得到基于约束的自动布局工作。 由于我的观点已经是一个子类UIScrollView我解决了它通过覆盖setContentView:并忽略自动布局零高度setContentSize:消息。
@interface MyView : UIScrollView {} @end @implementation MyView - (void)setContentSize:(CGSize)aSize { if (aSize.height > 0) [super setContentSize:aSize]; } @end
我曾经以编程方式设置uiscrollview直到我看了下面的精彩教程,一步一步如何让uiscrollview和uiview工作: https : //www.youtube.com/watch?v= PgeNPRBrB18
在观看video后,您肯定会开始喜欢Interface Builder。
投票
如果你正在使用AutoLayout
,设置UIScrollView
的contentSize
的一个非常简单的方法就是像这样添加:
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];
当标签的dynamic高度超过视图高度时仍然不滚动。
我做了yuf的回答标记为正确的上面说的做(我添加了一个内容视图到我的滚动视图,并设置从内容视图到滚动视图的约束前导,尾随,顶部底部和等宽),但仍然我的看法是当内部控件高度超过scrollview的高度时不滚动。
在我的内容视图中,我有一个图像和下面的3个标签。 每个标签都根据文本的大小来调整自己的高度(为了达到这个目的,它们被设置为自动换行,numberoflines = 0)。
我遇到的问题是我的内容视图的高度超出了滚动视图/主视图的高度时,标签的dynamic高度无法调整。
为了解决这个问题,我想出了我需要在底部标签和内容视图之间设置底部空间到容器的约束,并赋予它40的值(任意select,以在底部给它一个不错的余量)。 这意味着我的contentview会调整它的高度,以便在最后一个标签的底部和它自己之间有一个空格,并且它完全滚动 !
好极了!
试试这个…
添加所有约束,就像你为UIView
做的一样(请参阅Storyboard中ViewControler的screenShot )
现在把戏开始了。 select你的最后一个对象并select它的底部约束。 (见上面的screenShot,Instagram的button的底部约束(黄线))和更改大小检查器中的常量像在波纹pipe截图。
我需要常数= 8,但你可以根据你的要求改变。 这个常量是橙色button的底部和scrollView之间的空间。
编辑
确保您的视图的层次结构。
0)ViewController.view( 可选 )
1)UIScrollView
2)UIView(重命名为“contentView”)
3)UIView(这个视图是你的内容,将使scrollView滚动)
我得到了Autolayout工作分页滚动视图的网页占据屏幕的全angular。 页面会根据滚动视图的大小自动resize。 我没有testing这个较小宽度的滚动视图,但做评论,如果它的作品 – 我beleieve应该。 针对iOS 9,在Swift 2中编写代码,在awakeFromNib
混合使用IB和自定义代码。
脚步:
- 定义一个全屏滚动视图。
- 在滚动视图中,添加一个
UIView
(我称之为我的contentView
),其顶部,尾部,底部和前沿边界滚动视图都是零; 高度等于滚动视图的高度; 但宽度是滚动视图的宽度乘以页数。 如果您以可视方式进行此操作,则会看到您的内容视图超出了“界面构build器”中的滚动视图。 - 对于
contentView
每一个“页面”,添加Autolayout规则将它们并排放置,但最重要的是给它们一个约束,使得它们的宽度等于滚动视图的宽度,而不是内容视图的宽度。
下面的示例代码。 embedChildViewController
只是我添加子VC的便捷方法 – 查看setupLayoutRulesForPages
。 我有两页,所以这个function太简单了,但是你可以把它扩展到你的需要。
在我的视图控制器中:
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) } }