Как настроить размер содержимого UIScrollView динамически

У меня возник вопрос о UIScrollview.

История: у меня есть UIView с именем ChartsView, который я повторно рисую сам, переопределив метод drawRect(). Содержимое чертежа генерировалось динамически. Поэтому я не знаю его размер до времени исполнения. Вопрос в том, как/где можно установить динамический размер содержимого супервизора (scrollView)? Любая идея об этом?

    - (void)viewDidLoad
    {
        [super viewDidLoad];

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

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

        [self.scrollView addSubview:chartsView];

    }

Ответ 1

Еще один простой способ

- (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);
}

Ответ 2

Не гарантируется на 100%, что последний объект в массиве scrollView.subviews вернет самый высокий объект y-origin в вашем представлении прокрутки. Массив подпредставлений упорядочен по Z-индексу (то есть последним объектом в массиве подпредставлений будет объект, уложенный в наивысший уровень, и будет самым верхним подпредставлением в подпредставлениях прокрутки. Вместо этого более точно использовать базовую функцию сортировки перебрать подпредставления и получить объект с наивысшим значением y-источника.

Swift 4

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

Использование (в viewDidLayoutSubviews или всякий раз, когда обновляется размер вашего контента):

myScrollView.updateContentView()

Ответ 3

быстрый (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

Ответ 4

Благодаря IOS Rocks и CularBytes для потенциальных клиентов. Я нашел две проблемы (для меня) с приведенными выше решениями:

  • У меня всегда есть контейнер UIView как единственный дочерний элемент моего UIScrollView, поэтому мне пришлось обновить способ поиска последнего вида в этом дочернем UIView (см. ниже).
  • Я компенсирую свой контент в UIScrollView и, как таковой, должен вычислить абсолютную позицию этого последнего UIView (так, относительно окна, а не родительского представления)

Также я использую autolayout для привязки сторон 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().

Ответ 5

попробуйте это

- (void)viewDidLoad
        {
            [super viewDidLoad];

    // not this way. it 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];

    }

Ответ 6

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
}

Ответ 7

Попробуйте это -

- (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it 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];

    }

Ответ 8

При использовании scrollviews в раскадровке лучше рассчитать размер контента в соответствии с количеством представлений, представленных в scrollview, а не задавать размер контента программно со статическим значением. Вот шаги, чтобы получить размер контента динамически.

Шаг 1: Добавьте Scrollview для просмотра в раскадровке и добавьте начальные, конечные, верхние и нижние ограничения (все значения равны нулю).

Шаг 2: Не добавляйте непосредственно представления, которые вам нужны, непосредственно в scrollview. Сначала добавьте одно представление в scrollview (это будет наше представление содержимого для всех элементов пользовательского интерфейса). Добавьте ниже ограничения для этого представления. Ведущие, конечные, верхние и нижние ограничения (все значения равны нулю). Добавьте равную высоту, равную ширину к основному виду (то есть, который содержит представление прокрутки). Для равной высоты установите приоритет на низкий. (Это важный шаг для настройки размера контента). Высота этого представления содержимого будет соответствовать количеству просмотров, добавленных к представлению. Допустим, если вы добавили последний вид, это одна метка, а его позиция Y равна 420, а высота равна 20, тогда ваш контентный вид будет 440.

Шаг 3. Добавьте ограничения для всех представлений, которые вы добавили в представление содержимого, согласно вашему требованию.

enter image description here

enter image description here

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

Ответ 9

Это расширение, написанное на 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
    }
}

Ответ 10

Рассчитать UIScrollview contentSize динамически (в зависимости от фрейма подпредставлений)

Swift:

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