20 ответов:
лучший метод, с которым я когда-либо сталкивался, чтобы обновить размер содержимого
UIScrollViewна основе содержащихся в нем подвидов:ObjC
CGRect contentRect = CGRectZero; for (UIView *view in self.scrollView.subviews) { contentRect = CGRectUnion(contentRect, view.frame); } self.scrollView.contentSize = contentRect.size;Свифт
var contentRect = CGRect.zero for view in mainScrollView.subviews { contentRect = contentRect.union(view.frame) } mainScrollView.contentSize = contentRect.size
UIScrollView не знает высоту своего контента автоматически. Вы должны рассчитать высоту и ширину для себя
сделать это с чем-то вроде
CGFloat scrollViewHeight = 0.0f; for (UIView* view in scrollView.subviews) { scrollViewHeight += view.frame.size.height; } [scrollView setContentSize:(CGSizeMake(320, scrollViewHeight))];но это работает только в том случае, если представления находятся один под другим. Если у вас есть вид рядом друг с другом, вам нужно только добавить высоту одного, если вы не хотите устанавливать содержимое скроллера больше, чем на самом деле.
Я добавил Это к ответу 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; }
решение, если вы используете автоматический макет:
Set
translatesAutoresizingMaskIntoConstraintsдоNOдля всех задействованных представлений.положение и размер вашего вида прокрутки с ограничениями, внешними по отношению к виду прокрутки.
используйте ограничения для размещения подвидов в виде прокрутки,будучи уверенным, что ограничения привязаны ко всем четырем краям вида прокрутки и не полагайтесь на вид прокрутки, чтобы получить их размер.
источник: https://developer.apple.com/library/ios/technotes/tn2154/_index.html
вот принятый ответ в swift для тех, кто слишком ленив, чтобы преобразовать его:)
var contentRect = CGRectZero for view in self.scrollView.subviews { contentRect = CGRectUnion(contentRect, view.frame) } self.scrollView.contentSize = contentRect.size
следующее расширение было бы полезно в Свифт.
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.hidden { 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и расчет выполняется после того, как индикаторы прокрутки установлены скрытыми.кроме того, есть дополнительный параметр функции, и вы можете добавить значение смещения, передав параметр в функцию.
отличное и лучшее решение от @leviathan. Просто перевод на swift с использованием подхода FP (функциональное программирование).
self.scrollView.contentSize = self.scrollView.subviews.reduce(CGRect(), { CGRectUnion(, .frame) }.size
вот быстрая адаптация 3 ответа @leviatan:
расширение
import UIKit extension UIScrollView { func resizeScrollViewContentSize() { var contentRect = CGRect.zero for view in self.subviews { contentRect = contentRect.union(view.frame) } self.contentSize = contentRect.size } }использование
scrollView.resizeScrollViewContentSize()очень проста в использовании !
вы можете получить высоту содержимого внутри 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))];делая вещи таким образом, элементы (подвиды) не должны быть сложены непосредственно друг под другом.
Я придумал другое решение, основанное на решении @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)];в основном, мы выясняем, какой элемент находится дальше всего вниз в представлении и добавляет 10px заполнение в нижней части
поскольку scrollView может иметь другие scrollViews или другое дерево глубинных вложенных представлений, рекурсивно запускать глубину предпочтительнее.
Swift 2
extension UIScrollView { //it will block the mainThread func recalculateVerticalContentSize_synchronous () { let unionCalculatedTotalRect = recursiveUnionInDepthFor(self) self.contentSize = CGRectMake(0, 0, self.frame.width, unionCalculatedTotalRect.height).size; } private func recursiveUnionInDepthFor (view: UIView) -> CGRect { var totalRect = CGRectZero //calculate recursevly for every subView for subView in view.subviews { totalRect = CGRectUnion(totalRect, recursiveUnionInDepthFor(subView)) } //return the totalCalculated for all in depth subViews. return CGRectUnion(totalRect, view.frame) } }использование
scrollView.recalculateVerticalContentSize_synchronous()
или просто:
int y = CGRectGetMaxY(((UIView*)[_scrollView.subviews lastObject]).frame); [_scrollView setContentSize:(CGSizeMake(CGRectGetWidth(_scrollView.frame), y))];(Это решение было добавлено мной в качестве комментария на этой странице. Получив 19 голосов за этот комментарий, я решил добавить это решение в качестве официального ответа на благо сообщества!)
размер зависит от содержимого, загруженного внутри него, и варианты обрезки. Если это textview, то это также зависит от обертывания, сколько строк текста, размер шрифта и так далее и так далее. Почти невозможно для вас вычислить себя. Хорошей новостью является то, что он вычисляется после загрузки представления и в viewWillAppear. До этого все это неизвестно, и размер содержимого будет таким же, как размер кадра. Но, в методе viewWillAppear и после (например, viewDidAppear) размер контента будет актуальна.
обертывание кода Ричи я создал пользовательский класс UIScrollView, который автоматизирует контент изменяется полностью!
SBScrollView.h
@interface SBScrollView : UIScrollView @endSBScrollView.м:
@implementation SBScrollView - (void) layoutSubviews { CGFloat scrollViewHeight = 0.0f; self.showsHorizontalScrollIndicator = NO; self.showsVerticalScrollIndicator = NO; for (UIView* view in self.subviews) { if (!view.hidden) { CGFloat y = view.frame.origin.y; CGFloat h = view.frame.size.height; if (y + h > scrollViewHeight) { scrollViewHeight = h + y; } } } self.showsHorizontalScrollIndicator = YES; self.showsVerticalScrollIndicator = YES; [self setContentSize:(CGSizeMake(self.frame.size.width, scrollViewHeight))]; } @endкак использовать:
Просто импортируйте .H-файл для вашего контроллера представления и объявите экземпляр SBScrollView вместо обычного экземпляра UIScrollView.
установите динамический размер контента, как это.
self.scroll_view.contentSize = CGSizeMake(screen_width,CGRectGetMaxY(self.controlname.frame)+20);
Это действительно зависит от содержания.рамка.высота может дать вам то, что вы хотите ? Зависит от того, является ли контент одной вещью или коллекцией вещей.
Я также нашел ответ Левиафана, чтобы работать лучше. Тем не менее, он был расчетлив странной высоты. При циклическом просмотре вложенных представлений, если scrollview настроен на отображение индикаторов прокрутки, они будут находиться в массиве вложенных представлений. В этом случае решение состоит в том, чтобы временно отключить индикаторы прокрутки перед циклом, а затем восстановить их предыдущую настройку видимости.
-(void)adjustContentSizeToFitявляется открытым методом в пользовательском подклассе UIScrollView.-(void)awakeFromNib { dispatch_async(dispatch_get_main_queue(), ^{ [self adjustContentSizeToFit]; }); } -(void)adjustContentSizeToFit { BOOL showsVerticalScrollIndicator = self.showsVerticalScrollIndicator; BOOL showsHorizontalScrollIndicator = self.showsHorizontalScrollIndicator; self.showsVerticalScrollIndicator = NO; self.showsHorizontalScrollIndicator = NO; CGRect contentRect = CGRectZero; for (UIView *view in self.subviews) { contentRect = CGRectUnion(contentRect, view.frame); } self.contentSize = contentRect.size; self.showsVerticalScrollIndicator = showsVerticalScrollIndicator; self.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator; }
Я думаю, что это может быть аккуратный способ обновления размера представления содержимого UIScrollView.
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 + 20) contentSize = newSize } }
почему не одна строка кода??
_yourScrollView.contentSize = CGSizeMake(0, _lastView.frame.origin.y + _lastView.frame.size.height);
для swift4 с помощью reduce:
self.scrollView.contentSize = self.scrollView.subviews.reduce(CGRect.zero, { return .union(.frame) }).size

Comments