Как изменить динамический UIViews (с фиксированным размером) с изменением ориентации на iPad - PullRequest
0 голосов
/ 25 марта 2012

Я создаю приложение для iPad с главным экраном, состоящим из UIScrollView, заполненного динамическим числом UIViews фиксированного размера. В настоящее время я создаю UIViews программно и размещаю их вручную, устанавливая центр (setCenter) перед добавлением в представление прокрутки. Функциональность очень похожа на упрощенную версию начального экрана Pages на iPad. Я программно изменяю вертикальную длину контейнера прокрутки, когда каждая строка заполнена UIViews. Я должен вручную разместить каждый вновь созданный UIView, так как число будет динамически определяться количеством объектов, созданных пользователем.

Поскольку я также хочу разрешить изменение ориентации, я использую центр уведомлений для захвата событий изменения ориентации. Я хочу оставить отдельные UIViews одинакового размера независимо от ориентации, но мне нужно изменить их порядок с изменением ориентации, так как ориентация портрета будет иметь на один UIView меньше на строку.

Единственный способ изменить порядок расположения UIViews в представлении прокрутки - это программно изменить каждый из центров UIView (setCenter), обернув их в анимацию.

Есть ли другой способ изменить порядок UIViews, о котором я не думаю, кроме как ходить по подпредставлениям и корректировать их центральное положение?

Спасибо!

1 Ответ

1 голос
/ 25 марта 2012

Если у вас есть представление, которому нужно определенным образом разложить свои подвиды, общий подход заключается в создании собственного подкласса представления и переопределении его метода layoutSubviews. Система автоматически отправляет layoutSubviews представлению в разное время, в том числе при изменении размера представления. Если система выполняет автоматический запуск, она отправит вам layoutSubviews из блока анимации автоматического поворота, поэтому вам не нужно беспокоиться об анимации изменений в кадрах ваших подпредставлений.

Это немного усложняется, когда ваш вид представляет собой вид с прокруткой, потому что UIScrollView часто отправляет себе layoutSubview сообщения - каждый раз, когда он его меняет contentOffset. Так что если вы подкласс UIScrollView, вы хотите быть эффективными. Вам нужно отслеживать последний размер, для которого вы выложены, и выкладывать заново, только если размер изменился. Примерно так:

@implementation MyScrollView {
    CGSize _lastLayoutSize;
}

- (void)forceLayout {
    _lastLayoutSize = CGSizeMake(-1, -1);
    [self setNeedsLayout];
}

- (void)didAddSubview:(UIView *)view {
    // UIView sends itself this whenever a subview is added.
    [super didAddSubview:view];
    [self forceLayout];
}

- (void)didRemoveSubview:(UIView *)view {
    // UIView sends itself this whenever a subview is removed.
    [super didAddSubview:view];
    [self setNeedsLayout];
}

- (void)layoutSubviews {
    [super layoutSubviews];

    CGSize mySize = self.bounds.size;
    if (CGSizeEqualToSize(mySize, _lastLayoutSize))
        return;
    _lastLayoutSize = mySize;

    static CGFloat const margin = 8;
    CGFloat yMax = 0;
    CGPoint point = CGPointMake(margin, margin);
    BOOL rowIsEmpty = YES;
    for (UIView *subview in self.subviews) {
        CGRect frame = subview.frame;
        CGFloat xNext = point.x + frame.size.width + margin;
        if (rowIsEmpty || xNext <= mySize.width) {
            rowIsEmpty = NO;
            point.x = xNext;
        } else {
            point.x = margin;
            point.y = yMax + margin;
        }
        frame.origin = point;
        subview.frame = frame;
        yMax = MAX(yMax, CGRectGetMaxY(frame));        
    }

    self.contentSize = CGSizeMake(mySize.width, yMax + margin);
}
...