这个问题已被大量提出,例如: here但据我所知,尚未完全回答。
我有UITabBarController
个UINavigationController
作为其中一个标签的根vc,其本身有一个MKMapView
作为其根vc。我想要的行为是让地图向上部分卷曲,同时保留标签栏(类似于地图应用)。
到目前为止,我设法完成的工作是整个视图卷曲,这不是很好。
我看到的解决方案是将hidesBottomBarWhenPushed
属性设置为NO,这有意义但是这似乎不起作用(除非我做错了)。
为清楚起见,我的代码如下:
MyVC *aView = [MyVC init];
aView.modalTransitionStyle = UIModalTransitionStylePartialCurl;
aView.hidesBottomBarWhenPushed = NO;
对于演示部分,我尝试了下面的两个替代方案,两者似乎都不起作用:
[self presentModalViewController:updateStatus animated:YES];
[[self navigationController] presentModalViewController:updateStatus animated:YES];
任何帮助都非常感激。
答案 0 :(得分:4)
我已经搜索了StackOverflow(和Internet)来解决这个问题。问题已被多次询问,但正如您所指出的那样,从未得到足够的回答。许多solutions提供了一个可接受的解决方案,如果它不重要,例如,下工具栏是否也卷曲。
Others提供了使用UIView
动画/ CoreAnimation而非UIModalTransitionStylePartialCurl
作为模态转换样式的解决方案;这是最糟糕的App Store中不允许的解决方案,最好与UIModalTransitionStylePartialCurl
得到的效果不完全相同(例如卷曲的形状不同)。
这些解决方案都没有提供在地图应用中模仿Apple解决方案的答案(即使用UIModalTransitionStylePartialCurl
但在屏幕底部留下未卷曲的UIToolbar
。
我会继续这个不完整答案的传统,因为你问的是UITabBarController
而我的解决方案没有具体解决这个问题。然而,它解决了我遇到的问题,即在底部有一个非卷曲工具栏的半页卷曲。
必须有更优雅的方式来做到这一点,但这就是我管理的方式。
rootViewController
的{{1}}是AppDelegate
的子类,我将其称为UIViewController
。 TAContainerViewController
管理a)屏幕的实际内容(“要卷曲的东西”),TAContainerViewController
和b)TAContentViewController
后面的内容(例如设置),我会打电话给TAContentViewController
。
我的TAUnderCurlViewController
实例具有TAContainerViewController
和TAContentViewController
的属性。我的内容TAUnderCurlViewController
是UIView
的{{1}}属性的子视图;同样,用户在curl下看到的是TAContentViewController
的{{1}}属性。
在view
的{{1}}方法中,我确保执行以下操作:
view
要卷曲在页面下显示的内容,我设置了一个调用此代码的操作:
TAUnderCurlViewController
其中init
是TAContainerViewController
, _underCurlVC.modalTransitionStyle = UIModalTransitionStylePartialCurl;
是 [self.contentVC presentModalViewController:self.underCurlVC animated:YES];`
的实例,self
是TAContainerViewController
的实例。
要取消视图,只需contentVC
。
当模态视图被解除时,TAContentViewController
的框架似乎会出现一些奇怪现象,因此我在解除模态视图时手动重置框架。
我发布了一个示例项目,详细介绍了Github。希望有人可以把它变成一个稍微优雅的解决方案,或者扩展它以使用underCurlVC
或TAUnderCurlViewController
。我认为诀窍是将视图控制器从Cocoa子类中明确定义的关系中拉出来,因此可能会对这些专业视图控制器进行子类化。
答案 1 :(得分:1)
Tim Arnold的回复对我很有帮助,谢谢!
需要注意的一个陷阱:如果您的内容视图控制器被添加为容器视图控制器的子级,则您的模态页面卷曲转换将占据整个屏幕。你可以不把它作为一个孩子添加,但是你的内容控制器上不会调用任何视图生命周期方法(例如viewDidLoad
,viewWillAppear
),这可能是个问题。
幸运的是,有一种解决方法。在容器控制器中:
viewDidLoad
viewDidAppear
viewWillDisappear
。这样,您的内容控制器就会调用其生命周期方法,同时仍然可以在不占用整个屏幕的情况下进行模态页面卷曲转换。
这是一个简单的解决方案的完整代码:
@interface XXContainerController : UIViewController
@property (strong, nonatomic) UIViewController *contentController;
@property (nonatomic) BOOL curled;
@end
@implementation XXContainerController
@synthesize contentController = _contentController;
@synthesize curled = _curled;
- (void)viewDidLoad
{
[super viewDidLoad];
self.contentController = [self.storyboard
instantiateViewControllerWithIdentifier:@"SomeControllerInStoryboard"];
// Add content controller as child view controller.
// This way, it will receive all the view lifecycle events
[self addChildViewController:self.contentController];
self.contentController.view.frame = self.view.bounds;
[self.view addSubview:self.contentController.view];
[self.contentController didMoveToParentViewController:self];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Remove the content controller as child view controller.
// This way, the modal page curl transition will
// not take over the whole screen.
// NOTE: need to wait until content controller has appeared
// (which will happen later).
// Achieve this by running the code at the end of the animation loop
[UIView animateWithDuration:0 animations:nil completion:^(BOOL finished) {
[self.contentController removeFromParentViewController];
}];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Add the content controller as child view controller again
// so it receives the view lifecycle events
[self addChildViewController:self.contentController];
}
- (void)setCurled:(BOOL)curled
{
if (curled == _curled) return;
_curled = curled;
// Curl up the content view and show underneath controller's view
if (curled) {
// Note you can specify any modal transition in storyboard
// E.g. page curl, flip horizontal
[self.contentController
performSegueWithIdentifier:@"SomeModalSegueDefinedInStoryboard"
sender:self];
// Uncurl and show the content controller's view again
} else {
[self.contentController dismissModalViewControllerAnimated:YES];
// Have to do this, otherwise the content controller's view
// gets messed up for some reason
self.contentController.view.frame = self.view.bounds;
}
}
@end