UIScrollView自动旋转问题 - 子视图坚持原始位置并同时移动到新位置

时间:2014-02-15 17:13:27

标签: ios objective-c layout uiscrollview auto-rotation

在我的iOS应用中,部分内容是视频播放器(使用YouTube API)。我决定使用滚动视图在代码中布局此视图,以确保在所有轮换中在应用程序的iPad版本中正确布局视图。在继续之前,这是我的子视图布局代码。每当我的观点出现在屏幕上时,我都会打电话。

- (void)setupView {

// Set up Open in YouTube App button
self.openInYouTubeAppButton = [[UIBarButtonItem alloc] initWithTitle:@"Open in YouTube App" style:UIBarButtonItemStylePlain target:self action:@selector(openInYouTubeApp)];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"youtube://"]]) {
    self.navigationItem.rightBarButtonItems = @[self.shareButton, self.openInYouTubeAppButton];
} else {
    self.navigationItem.rightBarButtonItems = @[self.shareButton];
}

self.scrollView.frame = self.view.frame;

// Set up video embed view
self.videoEmbedView = ({
    // Frame
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 768, 432)];
    webView.center = CGPointMake(self.scrollView.center.x, (webView.bounds.size.height / 2));

    // View Properties
    webView.scrollView.contentInset = UIEdgeInsetsMake((-72 + 64), -8, 0, 0); // makes sure the video is fully seen in the view at first glance
    webView.scrollView.scrollEnabled = NO; // doesn't allow the user to mistakenly scroll the video

    webView;
});

self.videoTitleLabel = ({
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, (self.videoEmbedView.bounds.size.height + 14), 0, 0)]; // initial frame

    label.text = self.videoTitle; // text is video title
    label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; // dynamic type style
    label.preferredMaxLayoutWidth = self.view.bounds.size.width; // makes sure label text does not extend outside the view.
    [label sizeToFit];
    label.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + (label.bounds.size.height / 2))); // set center

    label;
});

self.videoDateLabel = ({
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8), 0, 0)]; // initial frame

    label.text = [NSDateFormatter localizedStringFromDate:self.videoDate dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterNoStyle];
    label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; // dynamic type style
    label.preferredMaxLayoutWidth = self.view.bounds.size.width; // makes sure label text does not extend outside the view.
    [label sizeToFit];
    label.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + (label.bounds.size.height / 2))); // set center

    label;
});

self.videoDescriptionTextView = ({
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25, 768, 200) textContainer:nil]; // initial frame

    textView.text = self.videoDescription;
    textView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    textView.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25 + (textView.bounds.size.height / 2))); // set center

    textView;
});

// Update scroll view content size
[self.scrollView setContentSize:CGSizeMake(self.view.bounds.size.width, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25 + self.videoDescriptionTextView.bounds.size.height))];

// Add views to scroll view
[self.scrollView addSubview:self.videoEmbedView];
[self.scrollView addSubview:self.videoTitleLabel];
[self.scrollView addSubview:self.videoDateLabel];
[self.scrollView addSubview:self.videoDescriptionTextView];

// Set description text view frame to content size
CGRect frame = self.videoDescriptionTextView.frame;
frame.size.height = self.videoDescriptionTextView.contentSize.height;
self.videoDescriptionTextView.frame = frame;

// Update scroll view content size
[self.scrollView setContentSize:CGSizeMake(self.view.bounds.size.width, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25 + self.videoDescriptionTextView.bounds.size.height))];

// Load video into embed view
NSString *embed = [NSString stringWithFormat:@"<iframe width='%f' height='%f' src='http://www.youtube.com/embed/%@' frameborder='0' allowfullscreen></iframe>", 768.0, 432.0, self.videoID];
[self.videoEmbedView loadHTMLString:embed baseURL:self.videoURL];
}

此代码在纵向方向上工作正常(但是,有一个错误,即动态设置文本视图的描述大小以适应内容;我也可以使用它的帮助)。 This is my screen in Portrait

然后在旋转到横向(或者在景观中启动视图时),我想我需要编辑我的子视图位置;像这样(我被告知这是覆盖自转的最佳方法;它产生与自动旋转定制的所有其他方式相同的结果):

- (void)viewWillLayoutSubviews {
CGFloat screenHeight =[UIScreen mainScreen].bounds.size.height;
CGFloat screenWidth =[UIScreen mainScreen].bounds.size.width;
self.scrollView.frame = CGRectMake(0, 0, screenWidth, screenHeight);

[self.scrollView setContentSize:CGSizeMake(self.view.bounds.size.width, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25 + self.videoDescriptionTextView.bounds.size.height))];

// Scroll view subviews
self.videoEmbedView.center = CGPointMake(self.scrollView.center.x, (self.videoEmbedView.bounds.size.height / 2));
self.videoTitleLabel.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + (self.videoTitleLabel.bounds.size.height / 2)));
self.videoDateLabel.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + (self.videoDateLabel.bounds.size.height / 2)));
self.videoDescriptionTextView.center = CGPointMake(self.view.center.x, (self.videoEmbedView.bounds.size.height + 14 + self.videoTitleLabel.bounds.size.height + 8 + self.videoDateLabel.bounds.size.height + 25 + (self.videoDescriptionTextView.bounds.size.height / 2)));
}

但这并不像我希望的那样好,我希望一切都是中心合理的,甚至是风景,但我得到了这个:Landscape autorotation is error

正如你所看到的,这些观点坚持他们以前的立场,并出现在他们的新职位上;并且视频嵌入视图根本不移动!

有人能帮助我吗?我卡住了,我到处寻找关于自动旋转中UIScrollView子视图的一般指导,所以现在我觉得是时候得到一些具体的答案了解我的情况。在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这个问题没有一个简单的“修复这行代码”。根据我的经验,滚动视图中的这种旋转大小调整最好通过使用自动布局来对UIScrollView中的视图进行排序,并使用自动布局根据滚动视图的容器调整大小。

从您的代码中看起来您已经拥有了这种视图结构:

UIScrollView (a)
    UIWebView (b)
    UILabel (c)
    UILabel (d)
    UILabel (e)
    etc.

我会创建一个稍微不同的结构:

UIView (Z)
    UIScrollView (a)
       UIWebView (b)
       UILabel (c)
       UILabel (d)
       UILabel (e)
       etc.

使用自动布局语法我会做这些约束:H:| [Z] |和V:| [Z] |和H:| [a] |和V:| [a] | 有了这些,容器UIView和UIScrollView将始终填充他们分配的空间。 然后我会做的内容是: 五:| [B] [C] [d] [E] | H:|并[b] H:| [C] H:| [d] H:| [E] 您可能希望将“a”的大小设置为固定高度以适应视频,但是一旦您这样做,其余视图将以高度方式流动。水平轴约束,例如H:| [a]告诉自动布局所有视图都固​​定在UIScrollView(它们的父级)的前沿。

下一部分无法用自动布局可视化格式语言真正表达,但您所做的是创建约束,使得UIScrollView(b,c,d和e)中每个视图的宽度相同宽度为容器UIView(Z)。

当自动布局完成它的布局魔术时,它将使用内容的固有高度垂直布局视图,并使用容器的宽度来水平调整大小。