Вопрос по iphone, uiscrollview, uiview, objective-c – Как динамически установить размер содержимого UIScrollView

25

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

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

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

    }
</code>

Ваш Ответ

8   ответов
0

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

swift (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
58

Еще один легкий способ

- (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);
}
Возникла проблема при возврате в поп навигационный контроллер
Я просто хотел бы добавить одну вещь. Некоторые из вас могут захотеть поместить этот код в viwDidAppear: потому что ваш UIView может быть нарисован до viewDidAppear, но после вызова viewDidLoad; Это позволит вам иметь доступ к самой последней высоте представления.
хороший трюк Может использоваться для любогоUIScrollView, +1 за это.
По какой-то причине это никогда не возвращало мне правильное подпредставление, даже если оно было правильным в моем файле пера. Я закончил тем, что просто отбросил вызов для последнего подпредставления и жестко запрограммировал, на каком подпредставлении я хотел, чтобы он был основан.
lastObject возвращает последний объект, проиндексированный в массиве подпредставлений, а не самое нижнее подпредставление на экране. фактически, lastObject не имеет ничего общего с позицией представления, и его использование неверно.
4

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

Вот основная функция в 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)

UPDATE SWIFT 4

Вот более краткая версия в Swift 4

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

Использование:

myScrollView.updateContentView()
1

попробуй это

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

    }
все еще не повезло. Я пытаюсь найти обходной путь, установить размер содержимого scrollview в представлении Charts при рисовании. Теперь вопрос в том, какой тип API я могу использовать для получения действительного размера chartsView ((UIScrollView *) [self superview]). ContentSize = CGSizeMake (320, 480); Roger Lee
0

Рассчитать 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;
                       });
}
3

Спасибо IOS Rocks и CularBytes за помощь в этом. Я нашел две проблемы (для меня) с вышеуказанными решениями:

I always have a container UIView as the only child of my UIScrollView, so I had to update the way I look up the last view in that child UIView (see below) I am offset'ing my content in the UIScrollView and as such needed to calculate the absolute position of that last UIView (so, relative to the window not the parent view)

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

1

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

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

    }

Похожие вопросы