In my iOS app, part of it is a video player (using the YouTube API). I've decided to layout this view in code with a scroll view in order to make sure that the views are correctly laid out in the iPad version of the app in all rotations. Before I continue, here's my code for the laying out of the subviews. I call this whenever my view comes on the screen.
- (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 code works fine in the portrait orientation (there is, however, an error with setting the text view for the description's size dynamically to fit the content; i could use help with that also).
Then in the rotation to landscape (or when the view is launched in landscape, for that matter), I figured I need to edit my subviews locations; like so (I was told that this was the best method to override for autorotation; it yields the same result as all the other ways of autorotation customization):
- (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)));
}
But this is not working as well as I hoped, I wanted everything to be center-justified and even-ish in landscape, but I get this instead:
As you can see, the views stick to their previous positions as well as appear in their new positions; and the video embed view doesn't even move at all!
Can someone help me? I am stuck and I've looked everywhere for SOME guidance as to what generally to do with UIScrollView subviews in autorotation, so now I thought it was time to get some specific answers to my situation. Thanks in advance for your help.