web-dev-qa-db-ja.com

子ビューコントローラーをUINavigationControllerに追加する

次のコードを使用して、UIViewControllerに含まれるUINavigationControllerに子ビューコントローラを追加しようとしています。

- (void)buttonTapped:(id)sender
{
    MyChildController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"MyChild"];
    [self addChildViewController:viewController];
    [self.view addSubview:viewController.view];
    [viewController didMoveToParentViewController:self];


    viewController.view.alpha = 0.0f;
    [UIView animateWithDuration:0.4 animations:^{
        viewController.view.alpha = 1.0f;
    }];
}

しかし、これは結果です:

Image Result

ご覧のように、UINavigatioBarUIToolbarはまだ子ビューコントローラの上にあります。すべての上に子ビューコントローラーを配置するにはどうすればよいですか?私はすでにコードを次のように置き換えようとしました:

[self.navigationController addChildViewController:viewController];
    [self.navigationController.view addSubview:viewController.view];
    [viewController didMoveToParentViewController:self.navigationController];

しかし、このようにviewDidAppear:animatedviewControllerが呼び出されません。理由はわかりません。

15
Fred Collins

最初のビューコントローラで、次のようにします。

- (IBAction)buttonClick:(id)sender
{
    SecondViewController *secondView = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
    UIImage *blurryImage = [UIImage imageNamed:@"foo.jpeg"];
    secondView.imageView.image = blurryImage;
    [self.navigationController addChildViewController:secondView];
    secondView.view.frame = self.navigationController.view.frame;
    [self.navigationController.view addSubview:secondView.view];
}

次に、2番目のView Controllerで、imageviewのゲッターを追加します。

-(UIImageView *)imageView
{
    if( _imageView == nil )
    {
        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 548)];
        [self.view addSubview:_imageView];
    }
    return _imageView;
}
7
JonahGabriel

@ Sam のコメントは正しいです。 endAppearanceTransitionをトリガーするには、beginApperanceTransition:animated:およびviewDidAppearを呼び出す必要があります。子ビューコントローラーを追加するときにUINavigationControllerviewDidAppearを呼び出さない理由は、プログラマーが奇妙な場所に子ビューコントローラーを追加できないようにコンテナー構成メソッドをオーバーライドしているためです。あなたの場合、子ビューがナビゲーションバーを覆ってしまうことは望ましくありません。ナビゲーションコントローラの正しい使い方は、ナビゲーションバーの下に子を表示することです。それにもかかわらず、いつ表示され、いつ表示が終了したかを手動で子に伝えることにより、この非標準のUIを強制することができます。

UINavigationControllerに子を追加します

MyChildViewController* child = [[MyChildViewController alloc] init];
[self.navigationController addChildViewController:child];
child.view.frame = self.navigationController.view.bounds;
[self.navigationController.view addSubview:child.view];
child.view.alpha = 0.0;
[child beginAppearanceTransition:YES animated:YES];
[UIView
    animateWithDuration:0.3
    delay:0.0
    options:UIViewAnimationOptionCurveEaseOut
    animations:^(void){
        child.view.alpha = 1.0;
    }
    completion:^(BOOL finished) {
        [child endAppearanceTransition];
        [child didMoveToParentViewController:self.navigationController];
    }
];

UINavigationControllerから子を削除します

[child willMoveToParentViewController:nil];
[child beginAppearanceTransition:NO animated:YES];
[UIView
    animateWithDuration:0.3
    delay:0.0
     options:UIViewAnimationOptionCurveEaseOut
    animations:^(void){
        child.view.alpha = 0.0;
    }
    completion:^(BOOL finished) {
        [child endAppearanceTransition];
        [child.view removeFromSuperview];
        [child removeFromParentViewController];
    }
];
31
Pwner

@ Pwner の回答Swiftバージョン:

UINavigaitonControllerに子を追加します

let child = MyChildViewController()
self.navigationController?.addChildViewController(child)
guard let navigationController = navigationController else {
    return
}
child.view.frame = navigationController.view.bounds
child.beginAppearanceTransition(true, animated: true)
self.navigationController?.view.addSubview(child.view)
self.view.alpha = 0
UIView.animate(withDuration: 0.3, animations: {
    child.view.alpha = 1.0
}, completion: { _ in
    guard let navigationController = self.navigationController else {
        return
    }
    child.endAppearanceTransition()
    child.didMove(toParentViewController: navigationController)
})

UINavigationControllerから子を削除します

child.willMove(toParentViewController: nil)
child.beginAppearanceTransition(false, animated: true)
UIView.animate(withDuration: 0.3, animations: {
    child.view.alpha = 0.0
}, completion: { _ in
    guard let navigationController = self.navigationController else {
        return
    }
    child.view.removeFromSuperview()
    child.endAppearanceTransition()
    child.removeFromParentViewController()
})
0
Ivan Smetanin