我正在开发一个开源库,以提供类似iMessage的文本输入视图 - MessageComposerView(与问题相关)。该视图将像inputAccessoryView
一样粘在键盘上并随文本一起增长,但在键盘出现时不会消失。
旋转此自定义UIView时,我最近遇到了令人抓狂的问题,只有在通过initWithFrame
实例化视图时才会出现该问题。基本上,如果视图已通过initWithFrame
实例化,则捕获到UIDeviceOrientationDidChangeNotification通知时,UIInterfaceOrientation和框架尚未更新。以下是实例化的两种方式。
loadNibNamed
:
self.messageComposerView = [[NSBundle mainBundle] loadNibNamed:@"MessageComposerView" owner:nil options:nil][0];
self.messageComposerView.frame = CGRectMake(0,
self.view.frame.size.height - self.messageComposerView.frame.size.height,
self.messageComposerView.frame.size.width,
self.messageComposerView.frame.size.height);
initWithFrame
:
self.messageComposerView = [[MessageComposerView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-54, 320, 54)];
在通过loadNibNamed
初始化并在收到UIDeviceOrientationDidChangeNotification
通知后轮播到横向时:
UIDeviceOrientation
= [[通知对象]方向] = UIInterfaceOrientationLandscapeLeft UIInterfaceOrientation
= [UIApplication sharedApplication] .statusBarOrientation = UIDeviceOrientationLandscapeRight self.frame.size
=(width = 480,height = 90)这里要注意的重要一点是界面和设备方向都是横向的,宽度已经改为横向宽度(在iPhone 6.1模拟器上测试)。现在执行相同的测试,但使用initWithFrame
:
UIDeviceOrientation
= [[通知对象]方向] = UIDeviceOrientationLandscapeRight UIInterfaceOrientation
= [UIApplication sharedApplication] .statusBarOrientation = UIInterfaceOrientationPortrait self.frame.size
=(width = 320,height = 54)此时请注意界面方向仍为纵向,并且框架宽度未更改为横向宽度。如果我在setFrame:(CGRect)frame
方法中设置了一个断点,我可以看到在捕获并处理了UIDeviceOrientationDidChangeNotification后,框架被设置为Landscape框架。
两种init方法都具有几乎相同的设置:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.frame = frame;
self.sendButton = [[UIButton alloc] initWithFrame:CGRectZero];
self.messageTextView = [[UITextView alloc] initWithFrame:CGRectZero];
[self setup];
[self addSubview:self.sendButton];
[self addSubview:self.messageTextView];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
setup
进行必要的视图调整:
- (void)setup {
self.backgroundColor = [UIColor lightGrayColor];
self.autoresizesSubviews = YES;
self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth;
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = NO;
CGRect sendButtonFrame = self.bounds;
sendButtonFrame.size.width = 50;
sendButtonFrame.size.height = 34;
sendButtonFrame.origin.x = self.frame.size.width - kComposerBackgroundRightPadding - sendButtonFrame.size.width;
sendButtonFrame.origin.y = kComposerBackgroundRightPadding;
self.sendButton.frame = sendButtonFrame;
self.sendButton.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin;
self.sendButton.layer.cornerRadius = 5;
[self.sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self.sendButton setTitleColor:[UIColor colorWithRed:210/255.0 green:210/255.0 blue:210/255.0 alpha:1.0] forState:UIControlStateHighlighted];
[self.sendButton setTitleColor:[UIColor grayColor] forState:UIControlStateSelected];
[self.sendButton setBackgroundColor:[UIColor orangeColor]];
[self.sendButton setTitle:@"Send" forState:UIControlStateNormal];
self.sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
CGRect messageTextViewFrame = self.bounds;
messageTextViewFrame.origin.x = kComposerBackgroundLeftPadding;
messageTextViewFrame.origin.y = kComposerBackgroundTopPadding;
messageTextViewFrame.size.width = self.frame.size.width - kComposerBackgroundLeftPadding - kComposerTextViewButtonBetweenPadding - sendButtonFrame.size.width - kComposerBackgroundRightPadding;
messageTextViewFrame.size.height = 34;
self.messageTextView.frame = messageTextViewFrame;
self.messageTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
self.messageTextView.showsHorizontalScrollIndicator = NO;
self.messageTextView.layer.cornerRadius = 5;
self.messageTextView.font = [UIFont systemFontOfSize:14];
self.messageTextView.delegate = self;
[self addNotifications];
[self resizeTextViewForText:@"" animated:NO];
}
所以我的问题是,为什么我的自定义UIView init initWithFrame
仍然具有纵向框架和界面方向以及收到UIDeviceOrientationDidChangeNotification的时间。我使用此通知进行框架调整,并且需要将宽度更新为横向宽度。
我希望在编程设置中我缺少某种自动旋转属性,这种属性隐藏在XIB的某个地方,但却无法找到它。我已经查看了十几个UIDeviceOrientationDidChangeNotification
stackoverflow帖子而没有找到解决方案。
答案 0 :(得分:4)
MessageComposerView看起来很整洁,感谢分享。
您应该实施UIDeviceOrientationDidChangeNotification
,而不是收听layoutSubviews
。响应旋转调用它以及系统需要UIView
重新定位其子视图(https://stackoverflow.com/a/5330162/1181421)的任何其他内容。在那里,您可以相对于UIView
的框架定位子视图,并确保框架正确。