如何在iPad上重新定位动态UIViews(具有固定大小)和方向更改

时间:2012-03-25 02:37:54

标签: xcode uiview orientation

我正在构建一个iPad应用程序,其主屏幕由一个UIScrollView组成,其中填充了动态数量的固定大小的UIViews。我目前正在以编程方式创建UIViews并通过在添加到scrollview之前设置中心(setCenter)来手动放置它们。该功能看起来非常像iPad上的Pages打开屏幕的简化版本。当每行用UIViews填充时,我以编程方式更改scrollview容器的垂直长度。我必须手动放置每个新创建的UIView,因为数字将由用户创建的对象数量动态确定。

由于我还想允许更改方向,因此我使用通知中心来捕获方向更改事件。我想让单个UIViews保持相同的大小,无论方向如何,但需要对方向更改进行重新排序,因为纵向方向每行的UIView少一个。

我能想到在滚动视图中重新排序UIViews的唯一方法是以编程方式更改每个UIView中心(setCenter),将它们包装在动画中。

除了走动子视图和调整中心位置之外,还有其他方法可以重新排列我没想过的UIViews吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

当您有一个需要以特定方式布置其子视图的视图时,一般方法是创建您自己的视图子类并覆盖其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);
}