代码之家  ›  专栏  ›  技术社区  ›  Jonathan.

大小以适应UIScrollView的内容大小

  •  19
  • Jonathan.  · 技术社区  · 14 年前

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

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

    10 回复  |  直到 14 年前
        1
  •  40
  •   William Jockusch    14 年前

    目前,这是我所拥有的最好的:

    CGRect contentRect = CGRectZero;
    for (UIView *view in self.subviews)
        contentRect = CGRectUnion(contentRect, view.frame);
    self.contentSize = contentRect.size;
    
        2
  •  4
  •   Ivan Vučica    13 年前

    如果频繁调用函数,则不希望每次都在子视图上迭代。相反,每当添加子视图时,请将当前contentSize和新子视图的框架合并。

    - (void)didAddSubview:(UIView *)subview {
        CGRect tmp;
        tmp.origin = CGPointZero;
        tmp.size = self.contentSize;
        tmp = CGRectUnion(tmp,subview.frame);
        self.contentSize = tmp.size;
    }
    
        3
  •  2
  •   Sebastien F.    12 年前

    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
    

    另外,请确保查看博客页面上的评论,以提供另一种解决方案。

    -阿诺普

        4
  •  1
  •   Nirav Gadhiya    12 年前

    我做了一个设置滚动视图内容大小的函数,试试看

    首先编写这个函数。。。

    -(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];
    

    我百分之百肯定它会起作用的。。。。。。。。。

        5
  •  1
  •   Anjaneyulu Battula    8 年前

    下面是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)")
    }
    
        6
  •  1
  •   Community CDub    8 年前

    William's answer 非常有用,因为滚动条也是滚动视图的子视图,所以它不能完美地工作。结果,诀窍是在计算内容大小之前隐藏它们。下面是Swift 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
        }
    }
    
        7
  •  0
  •   gchbib    14 年前

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

        8
  •  0
  •   nottombrown    9 年前

    在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
    
    }
    
        9
  •  0
  •   ali6p    7 年前

    联合方法为A和B设计提供相同的内容高度。但如果您知道最大的最后一个子视图,您可以计算正确的内容高度:

    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)
     }   
    } 
    
        10
  •  -1
  •   Juan Boero    8 年前

    用法:

    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
    
        }
    
    }