presentViewController e exibição da barra de navegação

99

Eu tenho uma hierarquia de controlador de visualização e o controlador mais superior é exibido como modal e gostaria de saber como exibir a barra de navegação ao usar

'UIViewController:presentViewController:viewControllerToPresent:animated:completion'

Os documentos para 'presentViewController: animado: conclusão:' nota:

'No iPhone e no iPod touch, a exibição apresentada é sempre em tela inteira. No iPad, a apresentação depende do valor da propriedade modalPresentationStyle. '

Para 'modalPresentationStyle', os documentos dizem:

O estilo de apresentação determina como um controlador de visualização apresentado modalmente é exibido na tela. No iPhone e no iPod touch, os controladores de visualização modal são sempre apresentados em tela inteira, mas no iPad há várias opções de apresentação diferentes.

Existe uma maneira de garantir que a barra de navegação fique visível abaixo da barra de status quando o controle de exibição for exibido? Devo interpretar o documento como, você não tem nenhuma opção de iPhone / iPod e apenas no iPad?

Anteriormente, eu estava usando o 'UIViewController:presentModalViewController:animated'que funcionava bem, mas desde o iOS 5.0, a API foi descontinuada, então estou mudando para a nova.

Visualmente, o que estou procurando é que o novo controlador deslize na parte inferior da tela, assim como a API antiga costumava fazer.

[atualizando com código]:

// 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];
Jonas Gardner
fonte

Respostas:

193

É verdade que se você apresentar um controlador de visualização modalmente no iPhone, ele sempre será apresentado em tela cheia, não importa como você o apresente no controlador de visualização superior de um controlador de navegação ou de qualquer outra forma. Mas você sempre pode mostrar a barra de navegação com a seguinte solução alternativa:

Em vez de apresentar esse controlador de visualização modalmente, apresente um controlador de navegação modalmente com seu controlador de visualização raiz definido como o controlador de visualização que você deseja:

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:^{

                        }];

Você deverá ver uma barra de navegação quando sua visualização for apresentada modalmente.

Manish ahuja
fonte
Isso é basicamente o que eu comecei. Mas o motivo pelo qual não estou usando 'presentModalViewController' é porque ele é considerado uma API obsoleta.
Jonas Gardner,
isso é o que foi escrito na classe UIViewController: // Exibe outro controlador de visualização como um filho modal. Usa uma transição de folha vertical se animado. Este método foi substituído por presentViewController: animated: completed: // Será DESCONTINUADO, planeje de acordo. - (void) presentModalViewController: (UIViewController *) modalViewController animado: (BOOL) animado; então simplesmente chame o novo método e passe nil para a conclusão e você estará bem.
Manish Ahuja
Ótima resposta. Atualizado para uso(void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
Wayne
2
Quando tento apresentar um controlador de navegação, ele trava ( 'NSInvalidArgumentException', reason: 'Pushing a navigation controller is not supported'). Como isso pode funcionar?
oarfish de
No meu caso, mostra a barra, mas o outro conteúdo é colocado incorretamente na apresentação da animação. E só depois dessa animação ele salta para a posição correta.
Vyachaslav Gerchicov
46

Swift 5.*

Navegação:

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

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

Voltando:

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

Swift 2.0

Navegação:

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

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

Voltando:

self.dismissViewControllerAnimated(true, completion: nil)
Tal Zion
fonte
1
Mas How to set quando tento seu código, então só
seto a
Não relacionado a esta pergunta, mas você pode encontrar a resposta aqui stackoverflow.com/questions/26008536/…
Tal Zion,
23

Você pode usar:

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

Voltando (eu acho):

[self.navigationController popToRootViewControllerAnimated:YES];
marrop
fonte
3
Obrigado, a melhor maneira de fazer isso se você já tiver um design de controlador de navegação em seu storyboard. Você me ajudou muito
phyzalis
voltar é [self.navigationController popViewControllerAnimated: YES]; popToRoot - voltando ao primeiro viewcontroller
Boris Gafurov
2

Eu tive o mesmo problema no iOS7. Chamei-o no seletor e funcionou no iOS7 e no 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: ^ {

    }];
}
Mohammad Parvez
fonte
1

Tudo o que o a [self.navigationController pushViewController:controller animated:YES];faz é animar uma transição e adicioná-la à pilha do controlador de navegação e alguns outros itens legais de animação da barra de navegação. Se você não se importa com a animação da barra, este código deve funcionar. A barra aparece no novo controlador e você obtém um gesto pop interativo!

//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.

Edit: Desculpe, presentViewController irá preencher a tela inteira. Você precisará fazer uma transição personalizada, com CGAffineTransform.translation ou algo assim, animar o controlador com a transição e adicioná-la aos viewControllers do navigationController.

Ignat
fonte
1

Swift 3

        let vc0 : ViewController1 = ViewController1()
        let vc2: NavigationController1 = NavigationController1(rootViewController: vc0)
        self.present(vc2, animated: true, completion: nil)
BennyTheNerd
fonte
Como adicionar o botão VOLTAR ao UIViewController
zulkarnain shah
1

Versão Swift: Apresenta um ViewController que está embutido em um Controlador de Navegação.

    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
fonte
1

Eu uso este código. Está funcionando bem no iOS 8.

MyProfileEditViewController *myprofileEdit=[self.storyboard instantiateViewControllerWithIdentifier:@"myprofileeditSid"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:myprofileEdit];
[self presentViewController:navigationController animated:YES completion:^{}];
Anil Prasad
fonte
0

Uma solução

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];
Yatin Sarbalia
fonte
0

Se você não definiu a propriedade modalPresentationStyle (como UIModalPresentationFormSheet), a barra de navegação será exibida sempre. Para garantir, sempre faça

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

Isso sempre mostrará a barra de navegação.

rakeshNS
fonte
Hmm ... mesmo com a referência fixa a 'topViewController', ainda estou vendo o mesmo comportamento. Não acho que estou adicionando os outros controladores de visualização à pilha de navegação de nenhuma maneira especial.
Jonas Gardner
0

Se você usa NavigationController no Swift 2.x

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let targetViewController = storyboard.instantiateViewControllerWithIdentifier("targetViewControllerID") as? TargetViewController
self.navigationController?.pushViewController(targetViewController!, animated: true)
Ego Slayer
fonte
0

tente isso

     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)
tsinghan
fonte