SizeToFit on UIScrollView的内容大小

问题描述:

UIView有一个SizeToFit方法,它将使UIView适合所有的子视图。有没有类似的东西,它只会返回它计算的大小,而不会修改任何视图的框架。SizeToFit on UIScrollView的内容大小

我在UIScrollView上有几个子视图,我想在scroll view的contentSize上做SizeToFit,而不是它的框架。我必须在contentSize上做,因为我不想增加UIScrollView的“实际”大小,并且内容是动态加载和异步加载的,所以当我将子视图添加到UIScrollView时我不能手动加载。

+0

从此开始赏金。目前,我的最佳答案是遍历子视图并查看其框架。我想知道是否有更好的方法。 SizeThatFits:似乎没有帮助。 – 2010-11-22 20:47:04

+0

尝试覆盖sizeThatFits:执行所需的计算。 – titaniumdecoy 2010-11-29 18:51:22

+0

[夫特分机(http://*.com/a/36504526/1634890) – 2016-04-08 16:19:26

目前,这是最好的我:

CGRect contentRect = CGRectZero; 
for (UIView *view in self.subviews) 
    contentRect = CGRectUnion(contentRect, view.frame); 
self.contentSize = contentRect.size; 
+0

这种方法很好,但是...由于某种原因,如果手机处于横向模式,它不适用于我。有任何想法吗? – Reuven 2012-03-29 07:05:38

+0

该解决方案不考虑到已经存在的UIScrollView子视图如果滚动条设置为显示的UIImageViews(见本SO后(http://*.com/questions/5664281/uiscrollview-phantom-subviews ))。将这些过滤出来的一种方法是将用户希望包含在for循环计算中的子视图的标签属性设置为相同的非零值,并使用if语句进行过滤。 – 2012-06-01 09:43:12

+1

@adamjansch或使用'isKindOfClass:'代替'标签'。或使用:'[self.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@ “级=%@”,[UILabel类]]];' - 不正确,因为它使用'class'而不是'isKindOfClass:',但不够好最使用。 – 2012-06-15 16:14:28

将UIView放入具有相同宽度和高度的UIScrollView,并将所有子视图添加到IT而不是滚动视图。然后将scrollview上的clipToBounds属性设置为TRUE,并在您的UIView上调用sizeToFit。您还可以将UIView背景的不透明度设置为0,使其不可见,但仍显示其子视图。

+0

我只是意识到,它应该是周围的其他方法:包封视图应该是UIView的,而内(较大的)视图应透明的UIScrollView。那么它应该工作。 – thgc 2010-10-28 14:07:58

+0

你肯定,你在你的答案写是有道理的,我有什么,虽然你说有,但似乎有点“unproper” – 2010-10-28 20:52:22

+0

对不起,我迟到反应......我部分用于自己的项目将上述溶液在上周工作。不幸的是,sizeToFit似乎对UIView中的UIScrollView没有任何影响。所以我已经添加了所有子视图后手动设置它的contentSize。这样做甚至不需要封闭的UIView了。 – thgc 2010-11-02 15:06:11

如果你的函数被频繁调用,您不希望每次在子视图进行迭代。相反,无论何时添加子视图,都要对当前的contentSize和新子视图的框架进行联合。

- (void)didAddSubview:(UIView *)subview { 
    CGRect tmp; 
    tmp.origin = CGPointZero; 
    tmp.size = self.contentSize; 
    tmp = CGRectUnion(tmp,subview.frame); 
    self.contentSize = tmp.size; 
} 
+0

在某些情况下可能是一个很好的解决方案。不幸的是,我的子视图经常会调整大小。所以在我的情况下,这不是一个好的解决方案。 – 2010-11-29 14:03:16

+0

@WilliamJockusch如果子视图频繁调整大小,您可以为'frame'或'bounds'添加一个KVO观察者并相应地更新'contentSize'。这将变得棘手,但取决于子视图的数量,可能是值得的。 – 2012-06-15 16:16:42

找到了解决办法在这里ScrollView ContentSize,你就能找到子视图的大小和找到的总含量的大小,也选择说子视图是否水平或垂直排列。

这里是从上面的链接代码:

@interface UIScrollView(auto_size) 
- (void) adjustHeightForCurrentSubviews: (int) verticalPadding; 
- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding; 
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding; 
@end 

@implementation UIScrollView(auto_size) 
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding { 
    float contentWidth = horizontalPadding; 
    float contentHeight = verticalPadding; 
    for (UIView* subview in self.subviews) { 
     [subview sizeToFit]; 
     contentWidth += subview.frame.size.width; 
     contentHeight += subview.frame.size.height; 
    } 

    contentWidth = changeWidth ? contentWidth : self.superview.frame.size.width; 
    contentHeight = changeHeight ? contentHeight : self.superview.frame.size.height; 

    NSLog(@"Adjusting ScrollView size to %fx%f, verticalPadding=%d, horizontalPadding=%d", contentWidth, contentHeight, verticalPadding, horizontalPadding); 
    self.contentSize = CGSizeMake(contentWidth, contentHeight); 
} 

- (void) adjustHeightForCurrentSubviews: (int) verticalPadding { 
    [self adjustWidth:NO andHeight:YES withHorizontalPadding:0 andVerticalPadding:verticalPadding]; 
} 

- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding { 
    [self adjustWidth:YES andHeight:NO withHorizontalPadding:horizontalPadding andVerticalPadding:0]; 
} 
@end 

同时一定要看看博客页面上的评论作为提供替代解决方案。

-anoop

我已经作出一个功能设置滚动视图的内容大小尝试它,享受

首先写这个函数...

-(void)setContentSizeOfScrollView:(UIScrollView*)scroll 
{ 
    CGRect rect = CGRectZero; 

    for(UIView * vv in [scroll subviews]) 
    { 
     rect = CGRectUnion(rect, vv.frame); 
    } 

    [scroll setContentSize:CGSizeMake(rect.size.width, rect.size.height)]; 
} 

再加入所有元素之后只需调用该函数并将滚动视图作为参数传递即可.....

[self setContentSizeOfScrollView:self.YourScrollView]; 

我100%肯定它会工作.........

在SWIFT 2.1,添加到您的视图控制器:

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    let aggregateView = contentView.subviews.reduce(CGRect()) 
     { aggRect, view in aggRect.union(view.frame) } 

    scrollView.contentSize = aggregateView.size 

} 

斯威夫特2扩展:

用法:

scrollView.contentResize
scrollView.contentWidthResize
scrollView.contentHeightResize

extension UIScrollView { 

    ///Will resize content size to fit all subviews. 
    func contentResize(){ 

     var w = CGFloat(0) 
     var h = CGFloat(0) 

     for view in self.subviews{ 

      let fw = view.frame.origin.x + view.frame.width 
      let fh = view.frame.origin.y + view.frame.height 

      w = max(fw, w) 
      h = max(fh, h) 

     } 

     contentSize = CGSize(width: w, height: h) 

    } 

    ///Will resize content width size to fit all subviews. 
    func contentWidthResize(){ 

     var w = CGFloat(0) 

     for view in self.subviews{ 

      let fw = view.frame.origin.x + view.frame.width 

      w = max(fw, w) 

     } 

     contentSize.width = w 

    } 

    ///Will resize content height size to fit all subviews. 
    func contentHeightResize(){ 

     var h = CGFloat(0) 

     for view in self.subviews{ 

      let fh = view.frame.origin.y + view.frame.height 

      h = max(fh, h) 

     } 

     contentSize.height = h 

    } 

} 
+1

'view.w'和'view.h'未定义配对。 – 2016-07-14 20:42:37

+0

@YoussefSami编辑...,请考虑删除downvote和投票,如果你觉得有用,谢谢你的信息。 – 2016-07-14 21:58:15

这是Swift 3的答案。0

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    var contentRect: CGRect = CGRect.zero 
    for view in self.scrollView.subviews { 
     debugPrint("view frame \(view.frame)") 
     contentRect = contentRect.union(view.frame) 
     debugPrint("frame \(contentRect)") 
    } 
    self.scrollView.contentSize = contentRect.size 
    debugPrint("content size \(self.scrollView.contentSize)") 
} 

虽然William's answer是非常有用的,它并不完美,因为滚动条也滚动视图的子视图的工作。原来,诀窍是在计算内容大小之前将其隐藏起来。这里的斯威夫特3码会是什么样子:

override func viewDidLayoutSubviews() { 
    scrollView.layoutSubviews() 

    // disable scrollbars so they don't interfere during resizing 
    scrollView.showsVerticalScrollIndicator = false 
    scrollView.showsHorizontalScrollIndicator = false 

    scrollView.contentSize = scrollView.subViewArea() 

    // re-enable the scrollbars 
    scrollView.showsVerticalScrollIndicator = true 
    scrollView.showsHorizontalScrollIndicator = true 
} 

您还需要在某处添加以下扩展名在您的项目:

extension UIScrollView { 
    func subViewArea() -> CGSize { 
     var rect = CGRect.zero 
     for subview in subviews { 
      rect = rect.union(subview.frame) 
     } 

     return rect.size 
    } 
} 

它不够的,工会帧大小来计算内容尺寸。因为有时候,你的子视图需要重叠,有时你在子视图之间有空白。你必须知道和计算子视图的来源。

联盟的做法给出了A和B的设计相同的内容HIGHT。但如果你知道去年最大的子视图,就可以计算出正确的内容高度:

enter image description here

该扩展程序可以计算真正的内容高度。

extension UIScrollView { 

func adjustContentHeight(bottomPadding: Int = 0) { 

    var lastSub: CGRect = .zero 
    self.subviews.forEach({ 
     let sub = $0.frame 
     if(sub.maxY > lastSub.maxY) { 
      lastSub = sub 
     } 
    }) 

    self.contentSize.height = lastSub.maxY + CGFloat(bottomPadding) 
} 
}