37

我有关于UIScrollview.

故事是我有一个UIView名为 ChartsView 的我自己通过 override 方法重新绘制它drawRect()。绘图内容是动态生成的。所以直到运行时我才知道它的大小。问题是我如何/在哪里可以动态设置其超级视图(scrollView)的内容大小?对此有任何想法吗?

    - (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        self.scrollView.contentSize = chartsView.frame.size;

        [self.scrollView addSubview:chartsView];

    }
4

12 回答 12

62

另一种简单的方法

- (void)viewDidLoad
{
    float sizeOfContent = 0;
    UIView *lLast = [scrollView.subviews lastObject];
    NSInteger wd = lLast.frame.origin.y;
    NSInteger ht = lLast.frame.size.height;

    sizeOfContent = wd+ht;

    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
}
于 2013-02-13T11:33:45.573 回答
23

不能 100% 保证 scrollView.subviews 数组中的最后一个对象将返回滚动视图中最高的 y 原点对象。subviews 数组按 Z-Index 排列(即 subviews 数组中的最后一个对象将是堆叠最高的对象,并且将是滚动视图的子视图中最顶层的子视图。相反,使用基本排序功能更准确遍历子视图并获取具有最高 y 原点的对象。

斯威夫特 4

extension UIScrollView {
    func updateContentView() {
        contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
    }
}

用法(在viewDidLayoutSubviews内容大小更新时或更新时):

myScrollView.updateContentView()
于 2016-10-14T19:30:22.727 回答
7

迅速(2.0)

@IBOutlet weak var btnLatestButton: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    let height = btnLatestButton.frame.size.height
    let pos = btnLatestButton.frame.origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent

}

当然,以上是当您的滚动视图只有固定数量的视图时。IOS Rocks 方法可用,但对我不利,创造了比我需要的更多空间。

    let lastView : UIView! = scrollview.subviews.last
    let height = lastView.frame.size.height
    let pos = lastView.frame.origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent
于 2015-07-08T15:07:47.850 回答
4

感谢 IOS Rocks 和 CularBytes 提供的线索。我发现上述解决方案有两个问题(对我来说):

  1. 我总是有一个容器 UIView 作为我的 UIScrollView 的唯一子级,所以我必须更新在该子级 UIView 中查找最后一个视图的方式(见下文)
  2. 我在 UIScrollView 中偏移了我的内容,因此需要计算最后一个 UIView 的绝对位置(因此,相对于窗口而不是父视图)

我也使用自动布局来固定 UIScrollView 的侧面,所以我不需要担心宽度(就像 CularBytes 一样)。

这是我想出和工作的(在 Swift 3.0 中):

func setScrollViewContentSize() {

    var height: CGFloat
    let lastView = self.myScrollView.subviews[0].subviews.last!
    print(lastView.debugDescription) // should be what you expect

    let lastViewYPos = lastView.convert(lastView.frame.origin, to: nil).y  // this is absolute positioning, not relative
    let lastViewHeight = lastView.frame.size.height

    // sanity check on these
    print(lastViewYPos)
    print(lastViewHeight)

    height = lastViewYPos + lastViewHeight

    print("setting scroll height: \(height)")

    myScrollView.contentSize.height = height
}

viewDidAppear()我在我的方法中称之为。

于 2016-06-28T00:41:37.870 回答
3
override func viewDidAppear(_ animated: Bool) {
    var height: CGFloat
    let lastView = self.scrollView.subviews[0].subviews.last!

    let lastViewYPos = lastView.convert(lastView.frame.origin, to: nil).y  
    let lastViewHeight = lastView.frame.size.height

    height = lastViewYPos + lastViewHeight
    scrollView.contentSize.height = height
}
于 2019-03-25T10:57:38.410 回答
2

尝试这个

- (void)viewDidLoad
        {
            [super viewDidLoad];

    // not this way. it's fixed size.....
            ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

            self.scrollView.contentSize = chartsView.frame.size;
            [self.scrollView setNeedsDisplay];
            [self.scrollView addSubview:chartsView];

    }
于 2012-05-09T15:15:21.773 回答
2

动态计算 UIScrollview contentSize(取决于子视图框架)

迅速:

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;
                       });
}
于 2019-02-11T09:44:00.053 回答
2

在情节提要中使用滚动视图时,最好根据滚动视图中存在的视图数量计算内容大小,而不是通过静态值以编程方式给出内容大小。以下是动态获取内容大小的步骤。

第 1 步: 添加 Scrollview 以在情节提要中查看并添加前导、尾随、顶部和底部约束(所有值均为零)。

第 2 步: 不要直接在滚动视图上添加您需要的视图,首先向滚动视图添加一个视图(这将是我们所有 UI 元素的内容视图)。将以下约束添加到此视图。前导、尾随、顶部和底部约束(所有值均为零)。将等高、等宽添加到主视图(即包含滚动视图)。对于相等的高度,将优先级设置为低。(这是设置内容大小的重要步骤)。此内容视图的高度将根据添加到视图中的视图数量而定。假设您添加的最后一个视图是一个标签,并且他的 Y 位置为 420,高度为 20,那么您的内容视图将为 440。

第 3 步:根据您的要求为您在内容视图中添加的所有视图添加约束。

在此处输入图像描述

在此处输入图像描述

参考:https ://medium.com/@javedmultani16/uiscrollview-dynamic-content-size-through-storyboard-in-ios-fb873e9278e

于 2019-08-24T22:32:26.673 回答
2

斯威夫特 5

您还可以UIScrollView通过调整以编程方式更新 contentView UIScrollView.contentLayoutGuide,这是将 contentview 限制为高度的示例yourView

self.scrollView.translatesAutoresizingMaskIntoConstraints = false
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
self.scrollView.heightAnchor.constraint(equalTo: self.view.heightAnchor).isActive = true
self.scrollView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
self.scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.scrollView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true

self.scrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: yourView.heightAnchor, multiplier: 1).isActive = true
self.scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 1).isActive = true
self.scrollView.contentLayoutGuide.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
self.scrollView.contentLayoutGuide.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
于 2021-04-13T14:10:43.080 回答
1

使用 contentInset

故事板

以编程方式

跟随这个效果最好

于 2020-10-14T10:01:34.353 回答
1

尝试这个 -

- (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        //self.scrollView.contentSize = chartsView.frame.size;
        [self.scrollView setContentSize:CGSizeMake(chartsView.frame.size.width, chartsView.frame.size.height)];
        [self.scrollView addSubview:chartsView];

    }
于 2016-06-28T04:03:45.980 回答
0

这是在 Swift 3 上编写的扩展

extension UIScrollView {
    func updateContentViewSize() {
        var newHeight: CGFloat = 0
        for view in subviews {
            let ref = view.frame.origin.y + view.frame.height
            if ref > newHeight {
                newHeight = ref
            }
        }
        let oldSize = contentSize
        let newSize = CGSize(width: oldSize.width, height: newHeight + 100)
        contentSize = newSize
    }
}
于 2017-03-01T12:38:19.723 回答