我长期以来一直在研究同样的问题,我可能在这里错过了一个简单的解决方案。
我创建了一个小型库来提供一个自定义的UIView,它可以像iMessage那样粘在键盘上(也就是不用键盘隐藏):https://github.com/oseparovic/MessageComposerView
基本上我遇到的问题是,当用户初始化自定义视图时,我想要一个具有以下默认rect初始化视图的视图:
CGFloat defaultHeight = 44.0;
CGRect frame = CGRectMake(0,
[self currentScreenSize].height-defaultHeight,
[self currentScreenSize].width,
defaultHeight)
这要求在UIView中计算currentScreenSize。我尝试了多种实现,所有这些都有其缺点。由于MVC的这一突破性原则,似乎并不是一个好的解决方案。
关于SO有很多重复的问题,但大多数人都认为你可以访问其他代码库(例如app delegate),而这个自定义视图并不是这样,所以我正在寻找一个自包含的解决方案。 / p>
以下是我使用的两个主要实现:
NextResponder
此解决方案似乎在各种场景中都相当成功。它所做的就是获得下一个响应者的帧,它非常方便地不包含导航或状态栏,可以用来将UIView定位在屏幕的底部。
主要问题是UIView中的self.nextResponder
在初始化时为nil
,这意味着无法使用它(至少不是我所知道的)来设置初始值帧。一旦视图被初始化并添加为子视图,虽然这看起来像是各种重新定位用途的魅力。
- (CGSize)currentScreenSize {
// return the screen size with respect to the orientation
return ((UIView*)self.nextResponder).frame.size;
}
ApplicationFrame
这是我长时间使用的解决方案,但它更笨重并且有几个问题。首先,通过使用applicationFrame,您必须处理导航栏高度,否则将偏移视图的位置。这意味着您必须确定它是否可见,获取其高度并从currentSize中减去它。
不幸的是,获取导航栏意味着您需要访问UINavigationController,这不像访问UIViewController那么简单。我到目前为止所获得的最佳解决方案是以下currentNavigationBarHeight
。我最近发现了一个问题,但是如果存在UIAlertView,那么这将无法获得导航栏高度[UIApplication sharedApplication].keyWindow.rootViewController
将评估为_UIAlertShimPresentingViewController
- (CGSize)currentScreenSize {
// there are a few problems with this implementation. Namely nav bar height
// especially was unreliable. For example when UIAlertView height was present
// we couldn't properly determine the nav bar height. The above method appears to be
// working more consistently. If it doesn't work for you try this method below instead.
return [self currentScreenSizeInInterfaceOrientation:[self currentInterfaceOrientation]];
}
- (CGSize)currentScreenSizeInInterfaceOrientation:(UIInterfaceOrientation)orientation {
// http://stackoverflow.com/a/7905540/740474
// get the size of the application frame (screensize - status bar height)
CGSize size = [UIScreen mainScreen].applicationFrame.size;
// if the orientation at this point is landscape but it hasn't fully rotated yet use landscape size instead.
// handling differs between iOS 7 && 8 so need to check if size is properly configured or not. On
// iOS 7 height will still be greater than width in landscape without this call but on iOS 8
// it won't
if (UIInterfaceOrientationIsLandscape(orientation) && size.height > size.width) {
size = CGSizeMake(size.height, size.width);
}
// subtract the height of the navigation bar from the screen height
size.height -= [self currentNavigationBarHeight];
return size;
}
- (UIInterfaceOrientation)currentInterfaceOrientation {
// Returns the orientation of the Interface NOT the Device. The two do not happen in exact unison so
// this point is important.
return [UIApplication sharedApplication].statusBarOrientation;
}
- (CGFloat)currentNavigationBarHeight {
// TODO this will fail to get the correct height when a UIAlertView is present
id nav = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([nav isKindOfClass:[UINavigationController class]]) {
UINavigationController *navc = (UINavigationController *) nav;
if(navc.navigationBarHidden) {
return 0;
} else {
return navc.navigationBar.frame.size.height;
}
}
return 0;
}
有没有人建议如何从这个UIView中最好地计算UIViewController大小。我完全接受有关如何在我可能忽略的初始化时将UIView粘贴到屏幕底部的其他建议。谢谢!
答案 0 :(得分:0)
+ (id) getCurrentUIViewController : (id)res {
if([res isKindOfClass:[UIViewController class]]) {
return res;
}
else if ([res isKindOfClass:[UIView class]]) {
return [Function getCurrentUIViewController:[res nextResponder]];
}
else {
return nil;
}
}