PresentViewController и отображение панели навигации

100

У меня есть иерархия контроллеров представления, и самый верхний контроллер отображается как модальный, и я хотел бы знать, как отображать панель навигации при использовании

'UIViewController:presentViewController:viewControllerToPresent:animated:completion'

Документы для PresentViewController: animated: Завершение: примечание:

'На iPhone и iPod touch изображение всегда отображается в полноэкранном режиме. На iPad представление зависит от значения свойства modalPresentationStyle. '

Для 'modalPresentationStyle' в документах говорится:

Стиль представления определяет, как модально представленный контроллер представления отображается на экране. На iPhone и iPod touch контроллеры модального представления всегда отображаются в полноэкранном режиме, но на iPad есть несколько различных вариантов представления.

Есть ли способ убедиться, что панель навигации отображается под строкой состояния после отображения самого элемента управления представлением? Должен ли я интерпретировать документ так: у вас нет вариантов iPhone / iPod и только на iPad?

Раньше я использовал тот, 'UIViewController:presentModalViewController:animated'который работал нормально, но, начиная с iOS 5.0, API устарел, поэтому я перехожу на новый.

Визуально я хочу, чтобы новый контроллер выдвигался из нижней части экрана, как это делал старый API.

[обновление с кодом]:

// My root level view:
UIViewController *vc = [[RootViewController alloc] 
                            initWithNibName:nil 
                            bundle:[NSBundle mainBundle]];
navController = [[UINavigationController alloc] initWithRootViewController:vc];        
....

// Within the RootViewController, Second view controller is created and added 
// to the hierarchy. It is this view controller that is responsible for 
// displaying the DetailView:
SecondTierViewController *t2controller = [[SecondTierViewController alloc] 
                                           initWithNibName:nil
                                           bundle:[NSBundle mainBundle]];

[self.navigationController pushViewController:t2controller animated:YES];

// Created by SecondTierViewController 
DetailViewController *controller = [[DetailViewController alloc] initWithNibName:nil                                                                                 
                                        bundle:[NSBundle mainBundle]];  

controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
controller.modalPresentationStyle = UIModalPresentationCurrentContext;

[self.navigationController presentViewController:controller 
                                        animated:YES 
                                        completion:nil];
Йонас Гарднер
источник

Ответы:

193

Это правда, что если вы представляете контроллер представления модально на iPhone, он всегда будет отображаться в полноэкранном режиме, независимо от того, как вы представляете его на контроллере вида сверху контроллера навигации или любым другим способом. Но вы всегда можете отобразить панель навигации следующим способом:

Вместо того, чтобы представлять этот контроллер представления модально, представьте контроллер навигации модально с его корневым контроллером представления, установленным в качестве контроллера представления, который вы хотите:

MyViewController *myViewController = [[MyViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc] initWithRootViewController:myViewController];

//now present this navigation controller modally 
[self presentViewController:navigationController
                   animated:YES
                   completion:^{

                        }];

Вы должны увидеть панель навигации, когда ваше представление представлено модально.

Маниш Ахуджа
источник
Это в значительной степени то, с чего я начал. Но причина, по которой я не использую PresentModalViewController, заключается в том, что он отмечен как устаревший API.
Йонас Гарднер
это то, что было написано в классе UIViewController: // Отображение другого контроллера представления как модального потомка. Использует вертикальный переход листа при анимации. Этот метод был заменен на presentViewController: animated: completion: // Он будет УСТАРЕВШИМ, планируйте соответственно. - (void) presentModalViewController: (UIViewController *) modalViewController анимированный: (BOOL) анимированный; поэтому просто вызовите новый метод и передайте nil для завершения, и все будет хорошо.
Маниш Ахуджа
Отличный ответ. Обновлено для использования(void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
Уэйн
2
Когда я пытаюсь представить контроллер навигации, он вылетает ( 'NSInvalidArgumentException', reason: 'Pushing a navigation controller is not supported'). Как это может работать?
oarfish
В моем случае отображается панель, но другой контент размещен неправильно при представлении анимации. И только после этой анимации он переходит в правильную позицию.
Вячеслав Герчиков
47

Swift 5.*

Навигация:

guard let myVC = self.storyboard?.instantiateViewController(withIdentifier: "MyViewController") else { return }
let navController = UINavigationController(rootViewController: myVC)

self.navigationController?.present(navController, animated: true, completion: nil)

Возвращаться:

self.dismiss(animated: true, completion: nil)

Swift 2.0

Навигация:

let myVC = self.storyboard?.instantiateViewControllerWithIdentifier("MyViewController");
let navController = UINavigationController(rootViewController: myVC!)

self.navigationController?.presentViewController(navController, animated: true, completion: nil)

Возвращаться:

self.dismissViewControllerAnimated(true, completion: nil)
Тал Цион
источник
1
Но как установить, когда я пробую ваш код, тогда устанавливаю только панель навигации, но я не могу изменить ее свойства, такие как цвет оттенка полосы, заголовок и т. Д.
Jaydip
Не имеет отношения к этому вопросу, но вы можете найти ответ здесь stackoverflow.com/questions/26008536/…
Tal Zion
23

Вы можете использовать:

[self.navigationController pushViewController:controller animated:YES];

Возвращаясь (думаю):

[self.navigationController popToRootViewControllerAnimated:YES];
марроп
источник
3
Спасибо, лучший способ сделать это, если у вас уже есть дизайн контроллера навигации в вашей раскадровке. Вы мне очень помогли
физалис
вернуться назад - [self.navigationController popViewControllerAnimated: YES]; popToRoot - возвращаясь к 1-му контроллеру просмотра
Борис Гафуров
2

У меня такая же проблема была на ios7. Я вызвал его в селекторе, и он работал как на ios7, так и на ios8.

[self performSelector: @selector(showMainView) withObject: nil afterDelay: 0.0];

- (void) showMainView {
    HomeViewController * homeview = [
        [HomeViewController alloc] initWithNibName: @
        "HomeViewController"
        bundle: nil];
    UINavigationController * navcont = [
        [UINavigationController alloc] initWithRootViewController: homeview];
    navcont.navigationBar.tintColor = [UIColor whiteColor];
    navcont.navigationBar.barTintColor = App_Theme_Color;
    [navcont.navigationBar
    setTitleTextAttributes: @ {
        NSForegroundColorAttributeName: [UIColor whiteColor]
    }];
    navcont.modalPresentationStyle = UIModalPresentationFullScreen;
    navcont.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self.navigationController presentViewController: navcont animated: YES completion: ^ {

    }];
}
Мохаммад Парвез
источник
1

Все, что [self.navigationController pushViewController:controller animated:YES];делает a , - это анимация перехода и добавление его в стек контроллера навигации, а также некоторые другие интересные элементы анимации панели навигации. Если вас не волнует анимация полосы, этот код должен работать. Панель появляется на новом контроллере, и вы получаете интерактивный всплывающий жест!

//Make Controller
DetailViewController *controller = [[DetailViewController alloc] initWithNibName:nil                                                                                 
                                    bundle:[NSBundle mainBundle]];  
//Customize presentation
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
controller.modalPresentationStyle = UIModalPresentationCurrentContext;

//Present controller
[self presentViewController:controller 
                   animated:YES 
                 completion:nil];
//Add to navigation Controller
[self navigationController].viewControllers = [[self navigationController].viewControllers arrayByAddingObject:controller];
//You can't just [[self navigationController].viewControllers addObject:controller] because viewControllers are for some reason not a mutable array.

Изменить: извините, PresentViewController заполнит весь экран. Вам нужно будет сделать настраиваемый переход с помощью CGAffineTransform.translation или чего-то еще, анимировать контроллер с переходом, а затем добавить его в viewControllers navigationController.

Игнат
источник
1

Swift 3

        let vc0 : ViewController1 = ViewController1()
        let vc2: NavigationController1 = NavigationController1(rootViewController: vc0)
        self.present(vc2, animated: true, completion: nil)
BennyTheNerd
источник
Как добавить кнопку НАЗАД в представленный UIViewController
zulkarnain shah
1

Версия Swift: представляет собой ViewController, встроенный в контроллер навигации.

    override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    //  Identify the bundle by means of a class in that bundle.
    let storyboard = UIStoryboard(name: "Storyboard", bundle: NSBundle(forClass: SettingsViewController.self))

    // Instance of ViewController that is in the storyboard.
    let settingViewController = storyboard.instantiateViewControllerWithIdentifier("SettingsVC")

    let navController = UINavigationController(rootViewController: settingViewController)

    presentViewController(navController, animated: true, completion: nil)

}
ioopl
источник
1

Я использую этот код. В iOS 8 все работает нормально.

MyProfileEditViewController *myprofileEdit=[self.storyboard instantiateViewControllerWithIdentifier:@"myprofileeditSid"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:myprofileEdit];
[self presentViewController:navigationController animated:YES completion:^{}];
Анил Прасад
источник
0

Одно решение

DetailViewController *controller = [[DetailViewController alloc] initWithNibName:nil                                                                                 
                                        bundle:[NSBundle mainBundle]];  

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navController.modalPresentationStyle = UIModalPresentationCurrentContext;



[self.navigationController presentViewController:navController 
                                        animated:YES 
                                        completion:nil];
Ятин Сарбалия
источник
0

Если вы не установили свойство modalPresentationStyle (например, UIModalPresentationFormSheet), панель навигации будет отображаться всегда. Чтобы гарантировать, всегда делайте

[[self.navigationController topViewController] presentViewController:vieController 
                                                            animated:YES 
                                                          completion:nil];

Это всегда будет отображать панель навигации.

rakeshNS
источник
Хм .. даже с фиксированной ссылкой на 'topViewController' я все еще наблюдаю то же поведение. Я не думаю, что добавляю другие контроллеры представления в стек навигации каким-либо особым образом.
Йонас Гарднер
0

Если вы используете NavigationController в Swift 2.x

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let targetViewController = storyboard.instantiateViewControllerWithIdentifier("targetViewControllerID") as? TargetViewController
self.navigationController?.pushViewController(targetViewController!, animated: true)
Убийца Эго
источник
0

попробуй это

     let transition: CATransition = CATransition()
    let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.duration = 1
    transition.timingFunction = timeFunc
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromRight
    self.view.window!.layer.addAnimation(transition, forKey: kCATransition)
    self.presentViewController(vc, animated:true, completion:nil)
Цинхан
источник