Room preview header in landscape

- Smooth header change during screen rotation
This commit is contained in:
giomfo
2016-06-08 18:22:50 +02:00
parent 10813d1e50
commit 6f139ad63b
+122 -102
View File
@@ -359,6 +359,25 @@
// Adjust the top constraint of the bubbles table
self.bubblesTableViewTopConstraint.constant = self.expandedHeaderContainerHeightConstraint.constant - self.bubblesTableView.contentInset.top;
}
if (previewHeader && previewHeader.mainHeaderContainer.isHidden)
{
// Check here the main background height to display a correct navigation bar background.
CGRect frame = self.navigationController.navigationBar.frame;
CGFloat mainHeaderBackgroundHeight = frame.size.height + (frame.origin.y > 0 ? frame.origin.y : 0);
if (previewHeader.mainHeaderBackgroundHeightConstraint.constant != mainHeaderBackgroundHeight)
{
previewHeader.mainHeaderBackgroundHeightConstraint.constant = mainHeaderBackgroundHeight;
// Force the layout of previewHeader to update the position of 'bottomBorderView' which
// is used to define the actual height of the preview container.
[previewHeader layoutIfNeeded];
self.previewHeaderContainerHeightConstraint.constant = previewHeader.bottomBorderView.frame.origin.y + 1;
}
}
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
@@ -388,18 +407,34 @@
}
else if (previewHeader)
{
if (previewHeader.mainHeaderContainer.hidden)
// Refresh here the preview header according to the coming screen orientation.
// Retrieve the affine transform indicating the amount of rotation being applied to the interface.
// This transform is the identity transform when no rotation is applied;
// otherwise, it is a transform that applies a 90 degree, -90 degree, or 180 degree rotation.
CGAffineTransform transform = coordinator.targetTransform;
// Consider here only the transform that applies a +/- 90 degree.
if (transform.b * transform.c == -1)
{
// Patch: Adjust the main background height to display a correct navigation bar background until the preview header is refreshed.
CGRect frame = self.navigationController.navigationBar.frame;
previewHeader.mainHeaderBackgroundHeightConstraint.constant = frame.size.height - frame.origin.y;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((coordinator.transitionDuration + 0.5) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self refreshPreviewHeader:YES];
UIInterfaceOrientation currentScreenOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL isLandscapeOriented = YES;
});
switch (currentScreenOrientation)
{
case UIInterfaceOrientationLandscapeRight:
case UIInterfaceOrientationLandscapeLeft:
{
// We leave here landscape orientation
isLandscapeOriented = NO;
break;
}
default:
break;
}
[self refreshPreviewHeader:isLandscapeOriented];
}
}
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
@@ -871,7 +906,10 @@
self.previewHeaderContainer.hidden = NO;
// Finalize preview header display according to the screen orientation
[self refreshPreviewHeader:YES];
UIInterfaceOrientation currentScreenOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL isLandscapeOriented = (currentScreenOrientation == UIInterfaceOrientationLandscapeRight || currentScreenOrientation == UIInterfaceOrientationLandscapeLeft);
[self refreshPreviewHeader:isLandscapeOriented];
}
else
{
@@ -911,110 +949,92 @@
}
}
- (void)refreshPreviewHeader:(BOOL)force
- (void)refreshPreviewHeader:(BOOL)isLandscapeOriented
{
if (previewHeader)
{
// Adjust the preview header layout according to the screen orientation
UIInterfaceOrientation screenOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL hidePreviewMainHeader = NO;
MXKImageView *roomAvatarView = nil;
switch (screenOrientation)
if (isLandscapeOriented)
{
case UIInterfaceOrientationLandscapeRight:
case UIInterfaceOrientationLandscapeLeft:
{
hidePreviewMainHeader = YES;
break;
}
default:
break;
}
if (force || (previewHeader.mainHeaderContainer.isHidden != hidePreviewMainHeader))
{
MXKImageView *roomAvatarView = nil;
CGRect frame = self.navigationController.navigationBar.frame;
if (hidePreviewMainHeader)
previewHeader.mainHeaderContainer.hidden = YES;
previewHeader.mainHeaderBackgroundHeightConstraint.constant = frame.size.height + (frame.origin.y > 0 ? frame.origin.y : 0);
[self setRoomTitleViewClass:RoomTitleView.class];
// We don't want to handle tap gesture here
// Remove details icon
RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView;
[roomTitleView.roomDetailsIconImageView removeFromSuperview];
roomTitleView.roomDetailsIconImageView = nil;
}
else
{
previewHeader.mainHeaderContainer.hidden = NO;
previewHeader.mainHeaderBackgroundHeightConstraint.constant = previewHeader.mainHeaderContainer.frame.size.height;
[self setRoomTitleViewClass:RoomAvatarTitleView.class];
// Note the avatar title view does not define tap gesture.
RoomAvatarTitleView *roomAvatarTitleView = (RoomAvatarTitleView*)self.titleView;
roomAvatarView = roomAvatarTitleView.roomAvatar;
roomAvatarView.alpha = 0.0;
// Set the avatar provided in preview data
if (roomPreviewData.roomAvatarUrl)
{
CGRect frame = self.navigationController.navigationBar.frame;
NSString *roomAvatarUrl = [self.mainSession.matrixRestClient urlOfContentThumbnail:roomPreviewData.roomAvatarUrl toFitViewSize:roomAvatarView.frame.size withMethod:MXThumbnailingMethodCrop];
previewHeader.mainHeaderContainer.hidden = YES;
previewHeader.mainHeaderBackgroundHeightConstraint.constant = frame.size.height + (frame.origin.y > 0 ? frame.origin.y : 0);
[self setRoomTitleViewClass:RoomTitleView.class];
// We don't want to handle tap gesture here
// Remove details icon
RoomTitleView *roomTitleView = (RoomTitleView*)self.titleView;
[roomTitleView.roomDetailsIconImageView removeFromSuperview];
roomTitleView.roomDetailsIconImageView = nil;
roomAvatarTitleView.roomAvatarURL = roomAvatarUrl;
}
else if (roomPreviewData.roomId && roomPreviewData.roomName)
{
roomAvatarTitleView.roomAvatarPlaceholder = [AvatarGenerator generateRoomAvatar:roomPreviewData.roomId andDisplayName:roomPreviewData.roomName];
}
else
{
previewHeader.mainHeaderContainer.hidden = NO;
previewHeader.mainHeaderBackgroundHeightConstraint.constant = previewHeader.mainHeaderContainer.frame.size.height;
[self setRoomTitleViewClass:RoomAvatarTitleView.class];
// Note the avatar title view does not define tap gesture.
RoomAvatarTitleView *roomAvatarTitleView = (RoomAvatarTitleView*)self.titleView;
roomAvatarView = roomAvatarTitleView.roomAvatar;
roomAvatarView.alpha = 0.0;
// Set the avatar provided in preview data
if (roomPreviewData.roomAvatarUrl)
{
NSString *roomAvatarUrl = [self.mainSession.matrixRestClient urlOfContentThumbnail:roomPreviewData.roomAvatarUrl toFitViewSize:roomAvatarView.frame.size withMethod:MXThumbnailingMethodCrop];
roomAvatarTitleView.roomAvatarURL = roomAvatarUrl;
}
else if (roomPreviewData.roomId && roomPreviewData.roomName)
{
roomAvatarTitleView.roomAvatarPlaceholder = [AvatarGenerator generateRoomAvatar:roomPreviewData.roomId andDisplayName:roomPreviewData.roomName];
}
else
{
roomAvatarTitleView.roomAvatarPlaceholder = [UIImage imageNamed:@"placeholder"];
}
roomAvatarTitleView.roomAvatarPlaceholder = [UIImage imageNamed:@"placeholder"];
}
// Force the layout of previewHeader to update the position of 'bottomBorderView' which is used to define the actual height of the preview container.
[previewHeader layoutIfNeeded];
self.previewHeaderContainerHeightConstraint.constant = previewHeader.bottomBorderView.frame.origin.y + 1;
// Consider the main navigation controller if the current view controller is embedded inside a split view controller.
UINavigationController *mainNavigationController = self.navigationController;
if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count)
{
mainNavigationController = self.splitViewController.viewControllers.firstObject;
}
// When the preview header is displayed, we hide the bottom border of the navigation bar (the shadow image).
// The default shadow image is nil. When non-nil, this property represents a custom shadow image to show instead
// of the default. For a custom shadow image to be shown, a custom background image must also be set with the
// setBackgroundImage:forBarMetrics: method. If the default background image is used, then the default shadow
// image will be used regardless of the value of this property.
UIImage *shadowImage = [[UIImage alloc] init];
[mainNavigationController.navigationBar setShadowImage:shadowImage];
[mainNavigationController.navigationBar setBackgroundImage:shadowImage forBarMetrics:UIBarMetricsDefault];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
if (roomAvatarView)
{
roomAvatarView.alpha = 1;
}
// Force to render the view
[self.view layoutIfNeeded];
}
completion:^(BOOL finished){
}];
}
// Force the layout of previewHeader to update the position of 'bottomBorderView' which is used
// to define the actual height of the preview container.
[previewHeader layoutIfNeeded];
self.previewHeaderContainerHeightConstraint.constant = previewHeader.bottomBorderView.frame.origin.y + 1;
// Consider the main navigation controller if the current view controller is embedded inside a split view controller.
UINavigationController *mainNavigationController = self.navigationController;
if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count)
{
mainNavigationController = self.splitViewController.viewControllers.firstObject;
}
// When the preview header is displayed, we hide the bottom border of the navigation bar (the shadow image).
// The default shadow image is nil. When non-nil, this property represents a custom shadow image to show instead
// of the default. For a custom shadow image to be shown, a custom background image must also be set with the
// setBackgroundImage:forBarMetrics: method. If the default background image is used, then the default shadow
// image will be used regardless of the value of this property.
UIImage *shadowImage = [[UIImage alloc] init];
[mainNavigationController.navigationBar setShadowImage:shadowImage];
[mainNavigationController.navigationBar setBackgroundImage:shadowImage forBarMetrics:UIBarMetricsDefault];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn
animations:^{
if (roomAvatarView)
{
roomAvatarView.alpha = 1;
}
// Force to render the view
[self.view layoutIfNeeded];
}
completion:^(BOOL finished){
}];
}
}