这是我在Stack Overflow上的第一篇文章,我是iOS初学者,所以请耐心等待我!
我有一个示例应用程序,其中我在父UIView(topView)中有三个UIViews(headerView,scrollViewContainer和bodyView),并且所有这些视图都是在代码中创建的。 topView被添加到在故事板中创建的UIScrollView(pageScrollView)。
pageScrollView正在填充iPhone的全屏,我使用了Autolayout。该应用程序仅包含ViewController.h和下面的伴随.m文件,以及Appdelegate.x。我想我开始使用单一视图应用程序模板。我正在使用iOS 6和Xcode 4.6,但我也试过4.5。
我尝试尽可能删除与此问题无关的其他代码。
问题: 当应用程序启动时,它会正确显示其所有视图,并且scrollView允许按预期查看所有三个视图。但是在旋转到横向之后,scrollView以某种方式抵消了内容。例如:保持在顶部并且旋转=内容看起来没问题,但向下滚动一点并旋转使内容的顶部不显示。
我尝试过:我在网上寻求帮助,但我找不到任何对我有帮助的东西。我添加了各种数据的记录,如origin和contentSize,并尝试设置其中一些但没有任何成功。我还使用'po [[UIWindow keyWindow] _autolayoutTrace]'来确保约束条件正常。
我看不出我做错了什么。我的代码中是否有任何明显的缺失?
提前致谢!
这是ViewController.m:
#import "ViewController.h"
@interface ViewController ()
{
UIView *topView;
UIView *headerView;
UIView *bodyView;
UIView *scrollViewContainer;
UIInterfaceOrientation newOrientation;
CGFloat bodyViewHeight;
CGSize newBounds;
float pictureScrollHeight;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
newOrientation = [UIApplication sharedApplication].statusBarOrientation;
bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation
self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
topView = [[UIView alloc] init];
[topView setBackgroundColor:[UIColor clearColor]];
topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.pageScrollView addSubview:topView];
headerView = [[UIView alloc] init];
[headerView setBackgroundColor:[UIColor redColor]];
headerView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:headerView];
scrollViewContainer = [[UIView alloc] init];
[scrollViewContainer setBackgroundColor:[UIColor blueColor]];
scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:scrollViewContainer];
bodyView = [[UIView alloc] init];
[bodyView setBackgroundColor:[UIColor greenColor]];
bodyView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:bodyView];
[self updateViewConstraints];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)updateViewConstraints
{
[super updateViewConstraints];
// Remove old constraints
[self.view removeConstraints:self.view.constraints];
[self.pageScrollView removeConstraints:self.pageScrollView.constraints];
[topView removeConstraints:topView.constraints];
[scrollViewContainer removeConstraints:scrollViewContainer.constraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
[headerView setNeedsDisplay];
[bodyView setNeedsDisplay];
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
//self.pageScrollView = _pageScrollView
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer);
NSDictionary *metricsDict = @{@"topViewHeight": [NSNumber numberWithFloat:topViewHeight],
@"newBoundsWidth": [NSNumber numberWithFloat:newBounds.width],
@"pictureScrollHeight": [NSNumber numberWithFloat:pictureScrollHeight],
@"bodyViewHeight": [NSNumber numberWithFloat:bodyViewHeight]};
// pageScrollView - child to self.view
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
// topView - child to pageScrollView
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topView(newBoundsWidth)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topView(topViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
// headerView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]];
// scrollViewContainer - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView]-0-[scrollViewContainer(pictureScrollHeight)]" options:0 metrics:metricsDict views:viewsDict]];
// bodyView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[scrollViewContainer]-0-[bodyView(bodyViewHeight)]-0-|" options:0 metrics:metricsDict views:viewsDict]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
newOrientation = toInterfaceOrientation;
newBounds = [self sizeInOrientation:toInterfaceOrientation];
}
-(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation
{
CGSize size = [UIScreen mainScreen].bounds.size;
UIApplication *application = [UIApplication sharedApplication];
if (UIInterfaceOrientationIsLandscape(orientation))
{
size = CGSizeMake(size.height, size.width);
}
if (application.statusBarHidden == NO)
{
size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
}
return size;
}
@end
答案 0 :(得分:1)
首先,您不需要在-updateViewConstraints方法中重新创建所有约束。你需要在这个地方更新它们。 为实现您的目标,请执行以下操作:
这里的ViewController.m应该是这样的:
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) IBOutlet UIScrollView* pageScrollView;
@property (nonatomic, strong) NSLayoutConstraint* pictureHeightConstraint;
@property (nonatomic, strong) NSLayoutConstraint* topViewWidthConstraint;
@property (nonatomic, strong) NSLayoutConstraint* topViewHeightConstraint;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
newBounds = [self sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
newOrientation = [UIApplication sharedApplication].statusBarOrientation;
bodyViewHeight = 1200; // The height of the body view varies in size depending on orientation
self.pageScrollView.translatesAutoresizingMaskIntoConstraints = NO;
topView = [[UIView alloc] init];
[topView setBackgroundColor:[UIColor clearColor]];
topView.translatesAutoresizingMaskIntoConstraints = NO;
[self.pageScrollView addSubview:topView];
headerView = [[UIView alloc] init];
[headerView setBackgroundColor:[UIColor redColor]];
headerView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:headerView];
scrollViewContainer = [[UIView alloc] init];
[scrollViewContainer setBackgroundColor:[UIColor blueColor]];
scrollViewContainer.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:scrollViewContainer];
bodyView = [[UIView alloc] init];
[bodyView setBackgroundColor:[UIColor greenColor]];
bodyView.translatesAutoresizingMaskIntoConstraints = NO;
[topView addSubview:bodyView];
[self setupConstraints];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)setupConstraints {
// Remove old constraints
[self.view removeConstraints:self.view.constraints];
[self.pageScrollView removeConstraints:self.pageScrollView.constraints];
[topView removeConstraints:topView.constraints];
[scrollViewContainer removeConstraints:scrollViewContainer.constraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
[headerView setNeedsDisplay];
[bodyView setNeedsDisplay];
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
//self.pageScrollView = _pageScrollView
NSDictionary *viewsDict = NSDictionaryOfVariableBindings(_pageScrollView, topView, headerView, bodyView, scrollViewContainer);
// pageScrollView - child to self.view
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0- [_pageScrollView]-0-|" options:0 metrics:nil views:viewsDict]];
// topView - child to pageScrollView
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]];
[self.pageScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topView]-0-|" options:0 metrics:nil views:viewsDict]];
NSLayoutConstraint* topViewWidthConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:newBounds.width];
self.topViewWidthConstraint = topViewWidthConstraint;
[topView addConstraint:self.topViewWidthConstraint];
NSLayoutConstraint* topViewHeightConstraint = [NSLayoutConstraint constraintWithItem:topView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:topViewHeight];
self.topViewHeightConstraint = topViewHeightConstraint;
[topView addConstraint:self.topViewHeightConstraint];
// headerView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView(55.0)]" options:0 metrics:nil views:viewsDict]];
// scrollViewContainer - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[scrollViewContainer]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView]-0-[scrollViewContainer]" options:0 metrics:nil views:viewsDict]];
NSLayoutConstraint* pictureHeightConstraint = [NSLayoutConstraint constraintWithItem:scrollViewContainer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:pictureScrollHeight];
self.pictureHeightConstraint = pictureHeightConstraint;
[scrollViewContainer addConstraint:self.pictureHeightConstraint];
// bodyView - child to topView
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
[topView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V: [scrollViewContainer]-0-[bodyView]-0-|" options:0 metrics:nil views:viewsDict]];
}
- (void)updateViewConstraints
{
[super updateViewConstraints];
if ((newOrientation == UIDeviceOrientationLandscapeLeft) || (newOrientation == UIDeviceOrientationLandscapeRight)) {
pictureScrollHeight = 300;
} else {
pictureScrollHeight = 203;
}
CGFloat topViewHeight = bodyViewHeight + 55 + pictureScrollHeight;
self.pictureHeightConstraint.constant = pictureScrollHeight;
self.topViewHeightConstraint.constant = topViewHeight;
self.topViewWidthConstraint.constant = newBounds.width;
[self.pageScrollView setNeedsUpdateConstraints];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
newBounds = [self sizeInOrientation:toInterfaceOrientation];
}
-(CGSize)sizeInOrientation:(UIInterfaceOrientation)orientation
{
CGSize size = [UIScreen mainScreen].bounds.size;
UIApplication *application = [UIApplication sharedApplication];
if (UIInterfaceOrientationIsLandscape(orientation))
{
size = CGSizeMake(size.height, size.width);
}
if (application.statusBarHidden == NO)
{
size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
}
return size;
}
@end
ScrollView会根据添加到其中的子视图约束自动计算其内容大小。当然,它仅适用于自动布局环境。
答案 1 :(得分:0)
检查自动调整大小的面具。
[self.pageScrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
答案 2 :(得分:0)
看起来你在willRotateToInterfaceOrientation中没有对newBounds做任何事情。在获取新边界后,不应该调用updateView方法。