Как настроить размер содержимого 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 } } 
  • Ошибка: протокол недоступен, сброс backtrace
  • Изменить цвет курсора в UITextField
  • Программно извлекать использование памяти на iPhone
  • С ARC, что лучше: alloc или autorelease инициализаторы?
  • Как я смогу удалить объекты из NSMutableArray?
  • Создание UIImage в форме круга
  • Сравните два массива с одинаковым значением, но с другим порядком
  • Восстановить пре-iOS7 UINavigationController pushViewController animation
  • Сохранить фотографии в пользовательский альбом в iPhones Photo Library
  • как сделать программный снимок экрана для iPhone?
  • Как добавить userInfo в UIAlertView?
  • Давайте будем гением компьютера.