我有以下用例:
嗯,它没有正常工作。问题是每次旋转后,都会调用RotationVC viewDidLayoutSubviews方法,该方法设置旋转的视图框架。这是错误的,因为根据Apple的文档,当视图的变换不是身份时,使用frame属性是错误的(就像在这种情况下一样)。结果,旋转的视图“歪斜”。以下是代理的源代码,您应该能够将其粘贴到单个文件中并运行。如果你这样做,我想要实现的是旋转的子视图保持其形状(在这个例子中它是一个矩形):
#import "AppDelegate.h"
@interface RotationVC : UIViewController
@property (nonatomic, weak) UIView *background;
@property (nonatomic, weak) UIView *foreground;
@property (nonatomic) int degrees;
@end
static const double DURATION = 0.5;
@implementation RotationVC
- (void)viewDidLoad {
[super viewDidLoad];
UIView *tmp = [UIView new];
self.background = tmp;
self.background.layer.borderWidth = 2;
self.background.layer.borderColor = [UIColor redColor].CGColor;
[self.view addSubview:self.background];
tmp = [UIView new];
self.foreground = tmp;
self.foreground.layer.borderWidth = 2;
self.foreground.layer.borderColor = [UIColor blueColor].CGColor;
[self.view addSubview:self.foreground];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.background.frame = self.view.bounds;
CGAffineTransform tmp = self.foreground.transform;
self.foreground.transform = CGAffineTransformIdentity;
self.foreground.frame = self.view.bounds;
self.foreground.transform = tmp;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self performSelector:@selector(rotate) withObject:self];
}
- (void)rotate {
self.degrees = (self.degrees + 15) % 360;
[UIView animateWithDuration:DURATION
delay:0
options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.foreground.transform = CGAffineTransformMakeRotation(self.degrees * M_PI/180);
}
completion:^(BOOL finished) {
[self performSelector:_cmd withObject:self afterDelay:0];
}];
}
@end
@interface ParentVC : UIViewController
@property (nonatomic, weak) RotationVC *rotationVC;
@end
@implementation ParentVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
RotationVC *tmp = [RotationVC new];
self.rotationVC = tmp;
[self addChildViewController:self.rotationVC];
[self.rotationVC didMoveToParentViewController:self];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.rotationVC.view];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.rotationVC.view.bounds = CGRectMake(0, 0, 100, 100);
self.rotationVC.view.center = self.view.center;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:[ParentVC new]];
navi.navigationBarHidden = YES;
self.window.rootViewController = navi;
[self.window makeKeyAndVisible];
return YES;
}
@end
有一个有效的黑客 - 在viewDidLayoutSubviews方法中,将旋转的视图变换存储到临时变量,将视图变换设置为标识,设置框架,并再次将其设置为旋转 - 这太丑了,我打赌必须有一个更好的方法。我还能够设计一些其他的解决方法,但每一个都比前一个更难...
在这种情况下,有人会暗示该怎么做吗?
答案 0 :(得分:1)
我能够解决这个问题。只需使用以下代码:
self.foreground.bounds = self.view.bounds;
self.foreground.center = self.background.center;
而不是设置框架。
重要说明:如果视图的transform属性不是identity变换,则该视图的frame属性的值是未定义的,必须忽略。将变换应用于视图时,必须使用视图的边界和中心属性来获取视图的大小和位置。任何子视图的框架矩形仍然有效,因为它们相对于视图的边界。
我一直认为设置框架同时设置边界和中心,但显然这是非常不真实的。