UIModalTransitionStylePartialCurl与UITabBarController

时间:2011-07-29 13:29:57

标签: iphone ios4 iphone-sdk-3.0 uitabbarcontroller mkmapview

这个问题已被大量提出,例如: here但据我所知,尚未完全回答。

我有UITabBarControllerUINavigationController作为其中一个标签的根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];

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:4)

我已经搜索了StackOverflow(和Internet)来解决这个问题。问题已被多次询问,但正如您所指出的那样,从未得到足够的回答。许多solutions提供了一个可接受的解决方案,如果它不重要,例如,下工具栏是否也卷曲。

Others提供了使用UIView动画/ CoreAnimation而非UIModalTransitionStylePartialCurl作为模态转换样式的解决方案;这是最糟糕的App Store中不允许的解决方案,最好与UIModalTransitionStylePartialCurl得到的效果不完全相同(例如卷曲的形状不同)。

这些解决方案都没有提供在地图应用中模仿Apple解决方案的答案(即使用UIModalTransitionStylePartialCurl但在屏幕底部留下未卷曲的UIToolbar

我会继续这个不完整答案的传统,因为你问的是UITabBarController而我的解决方案没有具体解决这个问题。然而,它解决了我遇到的问题,即在底部有一个非卷曲工具栏的半页卷曲。

必须有更优雅的方式来做到这一点,但这就是我管理的方式。

rootViewController的{​​{1}}是AppDelegate的子类,我将其称为UIViewControllerTAContainerViewController管理a)屏幕的实际内容(“要卷曲的东西”),TAContainerViewController和b)TAContentViewController后面的内容(例如设置),我会打电话给TAContentViewController

我的TAUnderCurlViewController实例具有TAContainerViewControllerTAContentViewController的属性。我的内容TAUnderCurlViewControllerUIView的{​​{1}}属性的子视图;同样,用户在curl下看到的是TAContentViewController的{​​{1}}属性。

view的{​​{1}}方法中,我确保执行以下操作:

view

要卷曲在页面下显示的内容,我设置了一个调用此代码的操作:

TAUnderCurlViewController

其中initTAContainerViewController _underCurlVC.modalTransitionStyle = UIModalTransitionStylePartialCurl; [self.contentVC presentModalViewController:self.underCurlVC animated:YES];` 的实例,selfTAContainerViewController的实例。

要取消视图,只需contentVC

当模态视图被解除时,TAContentViewController的框架似乎会出现一些奇怪现象,因此我在解除模态视图时手动重置框架。

我发布了一个示例项目,详细介绍了Github。希望有人可以把它变成一个稍微优雅的解决方案,或者扩展它以使用underCurlVCTAUnderCurlViewController。我认为诀窍是将视图控制器从Cocoa子类中明确定义的关系中拉出来,因此可能会对这些专业视图控制器进行子类化。

答案 1 :(得分:1)

Tim Arnold的回复对我很有帮助,谢谢!

需要注意的一个陷阱:如果您的内容视图控制器被添加为容器视图控制器的子级,则您的模态页面卷曲转换将占据整个屏幕。你可以不把它作为一个孩子添加,但是你的内容控制器上不会调用任何视图生命周期方法(例如viewDidLoadviewWillAppear),这可能是个问题。

幸运的是,有一种解决方法。在容器控制器中:

  • 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