編輯:不依賴於UIWindow
的替代解決方案。我認爲效果與日曆應用非常相似。
@interface SearchResultsController() <UINavigationControllerDelegate>
@end
@implementation SearchResultsController
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// this will be the UINavigationController that provides the push animation.
// its rootViewController is a placeholder that exists so we can actually push and pop
UIViewController* rootVC = [UIViewController new]; // this is the placeholder
rootVC.view.backgroundColor = [UIColor clearColor];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController: rootVC];
nc.modalPresentationStyle = UIModalPresentationCustom;
nc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[UIView transitionWithView: self.view.window
duration: 0.25
options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
animations: ^{
[self.parentViewController presentViewController: nc animated: NO completion: ^{
UIViewController* resultDetailViewController = [UIViewController alloc];
resultDetailViewController.title = @"Result Detail";
resultDetailViewController.view.backgroundColor = [UIColor whiteColor];
[nc pushViewController: resultDetailViewController animated: YES];
}];
}
completion:^(BOOL finished) {
nc.delegate = self;
}];
}
- (void) navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// pop to root? then dismiss our window.
if (navigationController.viewControllers[0] == viewController)
{
[UIView transitionWithView: self.view.window
duration: [CATransaction animationDuration]
options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
animations: ^{
[self.parentViewController dismissViewControllerAnimated: YES completion: nil];
}
completion: nil];
}
}
@end
原來的解決方案:
這裏是我的解決方案。我開始了使用您在UICatalog例如發現了顯示搜索控制器相同的技術:
- (IBAction)search:(id)sender
{
SearchResultsController* searchResultsController = [self.storyboard instantiateViewControllerWithIdentifier: @"SearchResultsViewController"];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.hidesNavigationBarDuringPresentation = NO;
[self presentViewController:self.searchController animated:YES completion: nil];
}
在我的例子,SearchResultsController是一個UITableViewController派生類。當搜索結果被點擊時,它會創建一個帶有根UINavigationController的新UIWindow,並將結果 - 詳細視圖控制器推送到該UIWindow。它監視UINavigationController彈出到根目錄,以便它可以關閉特殊的UIWindow。
現在,UIWindow並不是嚴格要求的。我使用它,因爲它有助於在推送/彈出過渡期間保持SearchViewController可見。相反,您可以僅從UISearchController提供UINavigationController(並從navigationController:didShowViewController:delegate方法中將其解除)。但默認情況下呈現在視圖控制器上的視圖控制器隱藏了下面的內容。你可以通過編寫一個自定義的轉換來解決這個問題,這個轉換將作爲UINavigationController的transitioningDelegate應用。
@interface SearchResultsController() <UINavigationControllerDelegate>
@end
@implementation SearchResultsController
{
UIWindow* _overlayWindow;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// this will be the UINavigationController that provides the push animation.
// its rootViewController is a placeholder that exists so we can actually push and pop
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController: [UIViewController new]];
// the overlay window
_overlayWindow = [[UIWindow alloc] initWithFrame: self.view.window.frame];
_overlayWindow.rootViewController = nc;
_overlayWindow.windowLevel = self.view.window.windowLevel+1; // appear over us
_overlayWindow.backgroundColor = [UIColor clearColor];
[_overlayWindow makeKeyAndVisible];
// get this into the next run loop cycle:
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* resultDetailViewController = [UIViewController alloc];
resultDetailViewController.title = @"Result Detail";
resultDetailViewController.view.backgroundColor = [UIColor whiteColor];
[nc pushViewController: resultDetailViewController animated: YES];
// start looking for popping-to-root:
nc.delegate = self;
});
}
- (void) navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// pop to root? then dismiss our window.
if (navigationController.viewControllers[0] == viewController)
{
[_overlayWindow resignKeyWindow];
_overlayWindow = nil;
}
}
@end
有趣。我希望這會比這更簡單。 :)看起來像很多工作來僞造一個導航控制器。您不僅需要創建動畫,還需要交互式轉換滑動手勢。 –
這個互動部分並不像看起來那麼複雜。 Ash Furrow在幾年前寫了一篇文章[Custom UIViewController Transitions](http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions/)文章解釋它,並且在GitHub上還有其他的例子。 –
謝謝,我來看看。所以我想這是一個自定義的模式轉換,看起來像是推送轉換。 –