I have not found a quick, easy or elegant solution to this problem. I have however found a tedious brute force solution. I worked on this months ago and actually don't think I'm totally finished. However, I'm going to post the basic frame work for anyone interested.
The basic concept is create two UIWindow objects, one that rotates and one that does not. Then before the rotation starts to flip all the controls from the rotating window to the non-rotating window. After the rotation completes to flip them back:
- (void) hideHovers {
for (Hover* hover in self.hovers)
hover.alpha = 0;
}
- (void) showHovers {
for (Hover* hover in self.hovers)
hover.alpha = 1;
}
// Public ==========================================================================================
- (void) addHover:(Hover*)hover {
[[Oovium aetherWindow] addSubview:hover];
[self.hovers addObject:hover];
}
- (void) beforeRotation {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
for (Hover* hover in self.hovers) {
hover.orientation = orientation;
[hover removeFromSuperview];
[controlWindow_ addSubview:hover];
}
controlWindow_.hidden = NO;
[self showHovers];
[UIView animateWithDuration:0.5 animations:^{
[self hideHovers];
}];
}
- (void) afterRotation {
for (Hover* hover in self.hovers) {
hover.transform = CGAffineTransformIdentity;
[hover removeFromSuperview];
[[Oovium aetherWindow] addSubview:hover];
[hover place];
}
controlWindow_.hidden = YES;
[UIView animateWithDuration:0.5 animations:^{
[self showHovers];
}];
}
Actually, that is the easy part. The difficult part is handling the transformation of the controls. The code below is not entirely working for all rotations. I will amend it when I complete it, but I'm not sure when I'll be able to get back to it.
//
// Hover.m
// Oovium
//
// Created by Joe Charlier on 2/22/15.
// Copyright (c) 2015 Aepryus Software. All rights reserved.
//
#import "Controls.h"
#import "Hover.h"
#import "Oovium.h"
#import "Utility.h"
@interface Hover ()
@property (nonatomic) OOAnchor anchor;
@property (nonatomic) CGPoint offset;
@property (nonatomic) CGSize size;
@end
@implementation Hover
// Static ==========================================================================================
static CGPoint points_[5][5];
static CGPoint shift_[5];
+ (void) initialize {
CGFloat width = [Utility deviceBounds].size.width;
CGFloat height = [Utility deviceBounds].size.height;
CGPoint topLeft = CGPointMake(0,0);
CGPoint topRight = CGPointMake(width,0);
CGPoint bottomLeft = CGPointMake(0,height);
CGPoint bottomRight = CGPointMake(width,height);
CGPoint center = CGPointMake(width/2,height/2);
points_[UIInterfaceOrientationPortrait][OOAnchorTopLeft] = topLeft;
points_[UIInterfaceOrientationPortrait][OOAnchorTopRight] = topRight;
points_[UIInterfaceOrientationPortrait][OOAnchorBottomLeft] = bottomLeft;
points_[UIInterfaceOrientationPortrait][OOAnchorBottomRight] = bottomRight;
points_[UIInterfaceOrientationPortrait][OOAnchorCenter] = center;
points_[UIInterfaceOrientationLandscapeRight][OOAnchorTopLeft] = topRight;
points_[UIInterfaceOrientationLandscapeRight][OOAnchorTopRight] = bottomRight;
points_[UIInterfaceOrientationLandscapeRight][OOAnchorBottomLeft] = topLeft;
points_[UIInterfaceOrientationLandscapeRight][OOAnchorBottomRight] = bottomLeft;
points_[UIInterfaceOrientationLandscapeRight][OOAnchorCenter] = center;
points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorTopLeft] = bottomRight;
points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorTopRight] = bottomLeft;
points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorBottomLeft] = topRight;
points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorBottomRight] = topLeft;
points_[UIInterfaceOrientationPortraitUpsideDown][OOAnchorCenter] = center;
points_[UIInterfaceOrientationLandscapeLeft][OOAnchorTopLeft] = bottomLeft;
points_[UIInterfaceOrientationLandscapeLeft][OOAnchorTopRight] = topLeft;
points_[UIInterfaceOrientationLandscapeLeft][OOAnchorBottomLeft] = bottomRight;
points_[UIInterfaceOrientationLandscapeLeft][OOAnchorBottomRight] = topRight;
points_[UIInterfaceOrientationLandscapeLeft][OOAnchorCenter] = center;
shift_[OOAnchorTopLeft] = CGPointMake(0, 0);
shift_[OOAnchorTopRight] = CGPointMake(1, 0);
shift_[OOAnchorBottomLeft] = CGPointMake(0, 1);
shift_[OOAnchorBottomRight] = CGPointMake(1, 1);
shift_[OOAnchorCenter] = CGPointMake(0.5, 0.5);
}
// =================================================================================================
+ (CGRect) placeInRect:(CGRect)rect anchor:(OOAnchor)anchor offset:(CGPoint)offset size:(CGSize)size {
CGPoint shift = shift_[anchor];
CGFloat x = shift.x*(rect.size.width-size.width)+offset.x;
CGFloat y = shift.y*(rect.size.height-size.height)+offset.y;
return CGRectMake(x, y, size.width, size.height);
}
- (id) initWithAnchor:(OOAnchor)anchor offset:(CGPoint)offset size:(CGSize)size {
if (self = [super initWithFrame:[Hover placeInRect:[UIScreen mainScreen].bounds anchor:anchor offset:offset size:size]]) {
self.anchor = anchor;
self.offset = offset;
self.size = size;
self.backgroundColor = [UIColor purpleColor];
}
return self;
}
- (void) setOrientation:(UIInterfaceOrientation)orientation {
_orientation = orientation;
CGPoint aO = self.frame.origin;
CGPoint aN = points_[orientation][_anchor];
double w = self.size.width;
double h = self.size.height;
double q = (self.size.height-self.size.width)/2;
double ox = self.offset.x;
double oy = self.offset.y;
double ax = aN.x-aO.x;
double ay = aN.y-aO.y;
double dx=0;
double dy=0;
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
dx += q;
dy += q;
}
switch (orientation) {
case UIInterfaceOrientationPortrait:
dx = 0;
dy = 0;
break;
case UIInterfaceOrientationPortraitUpsideDown:
switch (_anchor) {
case OOAnchorTopLeft:
dx += -ax+w+ox;
dy += -ay+h+oy;
break;
case OOAnchorTopRight:
dx += -ax+ox;
dy += -ay+h+oy;
break;
case OOAnchorBottomLeft:
dx += -ax+w+ox;
dy += -ay+oy;
break;
case OOAnchorBottomRight:
dx += -ax+ox;
dy += -ay+oy;
break;
}
break;
case UIInterfaceOrientationLandscapeRight:
switch (_anchor) {
case OOAnchorTopLeft:
dx += 0;
dy += ax-h-ox;
break;
case OOAnchorTopRight:
dx += -ay+w+oy;
dy += ax-h+ox;
break;
case OOAnchorBottomLeft:
dx += -ay+oy;
dy += 0;
break;
case OOAnchorBottomRight:
dx += -ay+w-oy;
dy += ax-ox;
break;
}
break;
case UIInterfaceOrientationLandscapeLeft:
switch (_anchor) {
case OOAnchorTopLeft:
dx += ay-h-oy;
dy += -w;
break;
case OOAnchorTopRight:
dx += -w;
dy += -ax-w-ox;
break;
case OOAnchorBottomLeft:
dx += ay-h+oy;
dy += -ay-h;
break;
case OOAnchorBottomRight:
dx += ay-w-oy;
dy += -ax+w-ox;
break;
}
break;
}
CGFloat angle = 0;
switch (orientation) {
case UIInterfaceOrientationPortrait: angle = 0; break;
case UIInterfaceOrientationLandscapeRight: angle = M_PI_2*3; break;
case UIInterfaceOrientationPortraitUpsideDown: angle = M_PI; break;
case UIInterfaceOrientationLandscapeLeft: angle = M_PI_2; break;
case UIInterfaceOrientationUnknown:break;
}
[self setTransform:CGAffineTransformConcat(
CGAffineTransformMakeTranslation(dx,dy),
CGAffineTransformMakeRotation(angle)
)];
}
- (void) invoke {
[[Oovium controls] invoke:self];
}
- (void) place {
CGSize sz = [UIScreen mainScreen].bounds.size;
CGPoint shift = shift_[self.anchor];
CGFloat x = shift.x*(sz.width-self.size.width)+self.offset.x;
CGFloat y = shift.y*(sz.height-self.size.height)+self.offset.y;
self.frame = CGRectMake(x, y, self.size.width, self.size.height);
}
@end