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

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

История: у меня есть UIView именем ChartsView, который я повторно рисую сам, переопределив метод 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]; } 

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

 - (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.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 

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

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

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

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

Вот базовая функция в swift 3, которая может сделать это:

 func calculateContentSize(scrollView: UIScrollView) -> CGSize { var topPoint = CGFloat() var height = CGFloat() for subview in scrollView.subviews { if subview.frame.origin.y > topPoint { topPoint = subview.frame.origin.y height = subview.frame.size.height } } return CGSize(width: scrollView.frame.size.width, height: height + topPoint) } 

Использование (в viewDidLayoutSubviews или при каждом обновлении размера содержимого):

 scrollView.contentSize = calculateContentSize(scrollView: scrollView) 

ОБНОВЛЕНИЕ SWIFT 4

Вот более часовая версия в быстрой версии 4

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

Применение:

 myScrollView.updateContentView() 

попробуй это

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

Попробуй это –

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

Это расширение, написанное на 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 } } 
  • Переменные экземпляра для объектов Objective C
  • Почему NSError нуждается в двойной косвенности? (указатель на указатель)
  • В чем разница между «отображаемым именем пакета» и «именем пакета» в информационном plist приложения cocoa
  • Интеграция CFNetwork и Bonjour для интеграции iPhone и Mac
  • Как проспать от сна программно, если крышка закрыта?
  • Open Source Cocoa / Cocoa-Touch POP3 / SMTP библиотека?
  • захват себя в этом блоке, вероятно, приведет к циклу сохранения
  • Программный пример UIPickerView?
  • iPhone: UITableView CellAccessory Checkmark
  • iPhone SDK: в чем разница между loadView и viewDidLoad?
  • Управление несколькими асинхронными соединениями NSURLConnection
  • Давайте будем гением компьютера.