Как мне автоматически изменить размер UIScrollView, чтобы соответствовать его содержимому - PullRequest
121 голосов
/ 31 мая 2010

Есть ли способ автоматически настроить UIScrollView на высоту (или ширину) прокручиваемого содержимого?

Что-то вроде:

[scrollView setContentSize:(CGSizeMake(320, content.height))];

Ответы [ 20 ]

293 голосов
/ 24 июня 2013

Лучший метод, с которым я когда-либо сталкивался, для обновления размера контента UIScrollView на основе содержащихся в нем подпредставлений:

Objective-C

CGRect contentRect = CGRectZero;

for (UIView *view in self.scrollView.subviews) {
    contentRect = CGRectUnion(contentRect, view.frame);
}
self.scrollView.contentSize = contentRect.size;

Swift

var contentRect = CGRect.zero

for view in mainScrollView.subviews {
   contentRect = contentRect.union(view.frame)
}
mainScrollView.contentSize = contentRect.size
75 голосов
/ 31 мая 2010

UIScrollView не знает высоту своего содержимого автоматически. Вы должны рассчитать высоту и ширину для себя

Сделайте это с чем-то вроде

CGFloat scrollViewHeight = 0.0f;
for (UIView* view in scrollView.subviews)
{
   scrollViewHeight += view.frame.size.height;
}

[scrollView setContentSize:(CGSizeMake(320, scrollViewHeight))];

Но это работает только в том случае, если представления располагаются один под другим. Если у вас есть вид рядом друг с другом, вам нужно добавить высоту только один, если вы не хотите устанавливать содержимое скроллера больше, чем оно есть на самом деле.

37 голосов
/ 28 марта 2014

Решение, если вы используете автоматический макет:

  • Установите translatesAutoresizingMaskIntoConstraints на NO для всех задействованных представлений.

  • Расположите и измените размер представления прокрутки с ограничениями, внешними по отношению к представлению прокрутки.

  • Используйте ограничения для разметки подпредставлений в представлении прокрутки, будучи уверенным, что ограничения привязаны ко всем четырем ребрам вида прокрутки и не полагайтесь на представление прокрутки для получения их размера .

Источник: https://developer.apple.com/library/ios/technotes/tn2154/_index.html

35 голосов
/ 14 июня 2011

Я добавил это к ответу Espuz и JCC. Он использует позицию y подпредставлений и не включает полосы прокрутки. Редактировать Используется нижняя часть самого нижнего подвида, который является видимым.

+ (CGFloat) bottomOfLowestContent:(UIView*) view
{
    CGFloat lowestPoint = 0.0;

    BOOL restoreHorizontal = NO;
    BOOL restoreVertical = NO;

    if ([view respondsToSelector:@selector(setShowsHorizontalScrollIndicator:)] && [view respondsToSelector:@selector(setShowsVerticalScrollIndicator:)])
    {
        if ([(UIScrollView*)view showsHorizontalScrollIndicator])
        {
            restoreHorizontal = YES;
            [(UIScrollView*)view setShowsHorizontalScrollIndicator:NO];
        }
        if ([(UIScrollView*)view showsVerticalScrollIndicator])
        {
            restoreVertical = YES;
            [(UIScrollView*)view setShowsVerticalScrollIndicator:NO];
        }
    }
    for (UIView *subView in view.subviews)
    {
        if (!subView.hidden)
        {
            CGFloat maxY = CGRectGetMaxY(subView.frame);
            if (maxY > lowestPoint)
            {
                lowestPoint = maxY;
            }
        }
    }
    if ([view respondsToSelector:@selector(setShowsHorizontalScrollIndicator:)] && [view respondsToSelector:@selector(setShowsVerticalScrollIndicator:)])
    {
        if (restoreHorizontal)
        {
            [(UIScrollView*)view setShowsHorizontalScrollIndicator:YES];
        }
        if (restoreVertical)
        {
            [(UIScrollView*)view setShowsVerticalScrollIndicator:YES];
        }
    }

    return lowestPoint;
}
13 голосов
/ 16 июля 2016

Вот быстрый ответ для тех, кому лень его конвертировать:)

var contentRect = CGRectZero
for view in self.scrollView.subviews {
    contentRect = CGRectUnion(contentRect, view.frame)
}
self.scrollView.contentSize = contentRect.size
8 голосов
/ 15 мая 2017

Вот адаптация Swift 3 ответа @ leviatan:

EXTENSION

import UIKit


extension UIScrollView {

    func resizeScrollViewContentSize() {

        var contentRect = CGRect.zero

        for view in self.subviews {

            contentRect = contentRect.union(view.frame)

        }

        self.contentSize = contentRect.size

    }

}

* 1009 USAGE *

scrollView.resizeScrollViewContentSize()

Очень прост в использовании!

6 голосов
/ 14 апреля 2016

Следующее расширение будет полезно в Swift .

extension UIScrollView{
    func setContentViewSize(offset:CGFloat = 0.0) {
        // dont show scroll indicators
        showsHorizontalScrollIndicator = false
        showsVerticalScrollIndicator = false

        var maxHeight : CGFloat = 0
        for view in subviews {
            if view.isHidden {
                continue
            }
            let newHeight = view.frame.origin.y + view.frame.height
            if newHeight > maxHeight {
                maxHeight = newHeight
            }
        }
        // set content size
        contentSize = CGSize(width: contentSize.width, height: maxHeight + offset)
        // show scroll indicators
        showsHorizontalScrollIndicator = true
        showsVerticalScrollIndicator = true
    }
}

Логика одинакова с данными ответами. Тем не менее, он пропускает скрытые виды в пределах UIScrollView, и вычисление выполняется после скрытых указателей прокрутки.

Также имеется необязательный параметр функции, и вы можете добавить значение смещения, передав параметр в функцию.

5 голосов
/ 27 ноября 2016

Отличное и лучшее решение от @leviathan. Просто перевод на swift с использованием подхода FP (функциональное программирование).

self.scrollView.contentSize = self.scrollView.subviews.reduce(CGRect(), { 
  CGRectUnion($0, $1.frame) 
}.size
4 голосов
/ 21 мая 2013

Вы можете получить высоту содержимого внутри UIScrollView, рассчитав, какой дочерний элемент "достигает дальнейших шагов". Чтобы рассчитать это, вы должны принять во внимание происхождение Y (начало) и высоту предмета.

float maxHeight = 0;
for (UIView *child in scrollView.subviews) {
    float childHeight = child.frame.origin.y + child.frame.size.height;
    //if child spans more than current maxHeight then make it a new maxHeight
    if (childHeight > maxHeight)
        maxHeight = childHeight;
}
//set content size
[scrollView setContentSize:(CGSizeMake(320, maxHeight))];

Делая вещи таким образом, предметы (подпредставления) не должны укладываться непосредственно один под другим.

3 голосов
/ 05 апреля 2014

Я придумал другое решение, основанное на решении @ emenegro

NSInteger maxY = 0;
for (UIView* subview in scrollView.subviews)
{
    if (CGRectGetMaxY(subview.frame) > maxY)
    {
        maxY = CGRectGetMaxY(subview.frame);
    }
}
maxY += 10;
[scrollView setContentSize:CGSizeMake(scrollView.frame.size.width, maxY)];

По сути, мы выясняем, какой элемент находится дальше всего в представлении, и добавляем отступ в 10 пикселей к основанию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...