プログラムで作成したUINavigationController
(ウィザードページのように使用する)があり、[キャンセル]ボタンを表示してUIViewController
のプロセスをキャンセルする必要があります。
UINavigationController
の作成:
FirstVC *firstVC = [[[FirstVC alloc] initWithNibName:@"FirstPage" bundle:nil] autorelease];
firstVC.delegate = self;
navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC];
[self.view addSubview:navigationController.view];
キャンセルボタンの追加:
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelRequestNewLeave:)];
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
[cancelButton release];
しかし、2番目のページをUINavigationController
にプッシュすると、キャンセルボタンがUINavigationBar
に表示されません。最初のページに戻ると、キャンセルボタンがあります。つまり、ボタンは最初のビューにのみ追加されます。これは、サブビューで使用する必要があるため、UINavigationController
をサブクラス化していないためだと思います。しかし、プログラムで作成されたrightBarButtonItem
にUINavigationController
を設定する方法がわかりません。
navigationController.topViewController.navigationItem.rightBarButtonItem = cancelButton;
誰かがこれに光を当てることができますか?
前もって感謝します。
ナビゲーション項目はビューコントローラごとです。ナビゲーションバーは、現在フレーミングしているビューのビューコントローラーのナビゲーションアイテムからコンテンツを描画します。これは、ナビゲーションコントローラーのスタックの最上部にあるビューコントローラーに対応します。
基本的に、ナビゲーション項目にキャンセルボタンを貼り付けるには、各ビューコントローラーが必要です。次のいずれかを実行できます。
UINavigationcontroller
をサブクラス化して、次のようないくつかのメソッドをオーバーライドすることもできます。
- (id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if (self) {
[self setCloseButtonToController:rootViewController];
}
return self;
}
- (void)dismissController {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)setCloseButtonToController:(UIViewController *)viewController {
UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(dismissController)];
[viewController.navigationItem setRightBarButtonItem:closeItem];
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
[self setCloseButtonToController:viewController];
}
代わりに、UINavigationControllerDelegate
インスタンスを作成するクラスでUINavigationController
プロトコルを採用できます。事前にcancelButton
を作成してから、次のようにnavigationController:willShowViewController:animated:
を実装することもできます。
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
viewController.navigationItem.rightBarButtonItem = cancelButton;
}
cancelButton
を作成して保持し、解放しないでください。これは、cancelRequestNewLeave:
がUINavigationController
インスタンスを作成するクラスのメソッドである必要があることも意味します。
そのように
CommonViewController.h
@interface CommonViewController : UIViewController
-(void) initializeCartBarButton;
@end
CommonViewController.m
#import "CommonViewController.h"
@interface CommonViewController ()
@end
@implementation CommonViewController
-(void) initializeCartBarButton {
UIBarButtonItem *cartBarButton = [[UIBarButtonItem alloc] init];
cartBarButton.title = @"cart";
[cartBarButton setTarget: self];
[cartBarButton setAction: @selector(goToCart:)];
self.navigationItem.rightBarButtonItem = cartBarButton;
}
- (IBAction) goToCart:(id)sender {
NSLog(@"");
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
@interface FirstViewController : CommonViewController
@end
FirstViewController.m
#import "FirstViewController.h"
@interface FirstViewController ()
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeCartBarButton];
}
@end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "CommonViewController.h"
@interface SecondViewController : CommonViewController
@end
SecondViewController.m
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeCartBarButton];
}
@end
注:initializeCartBarButtonのコードをCommonViewControllerのviewDidLoadに追加して、この機能をCommonViewControllerおよび子クラスから削除できます
これは、プッシュされたすべてのviewControllerを閉じることができるUINavigationController
サブクラスを使用して行った方法です。
class CustomNavigationController: UINavigationController, UINavigationControllerDelegate{
//TODO: Use when we have more right bar button types.
var rightBarButtonType: RightBarButtonType = .Close
enum RightBarButtonType{
case Close
}
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
// MARK: Private Functions
private func addRightBarButtonTo(viewController: UIViewController){
let barButtonItem: UIBarButtonItem!
switch self.rightBarButtonType {
case .Close:
barButtonItem = UIBarButtonItem(image: UIImage(named: "ic_close_white"), style: .Done, target: self, action: #selector(CustomNavigationController.dismiss(_:)))
}
viewController.navigationItem.rightBarButtonItem = barButtonItem
}
// MARK: UINavigationController Delegate
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
self.addRightBarButtonTo(viewController)
}
@objc func dismiss(sender: AnyObject){
self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
}
}
すべてのビューコントローラにボタンを追加する必要があります。一度設定するか、(賢明な方法で)View Controller間で共有することはできません。ボタンを追加する適切な場所は、ビューコントローラのviewDidLoadメソッドです。これが繰り返し発生すると思われる場合は、基本的なUIViewConteollerサブクラスを1つ作成できます。
このコードをルートビューのviewDidLoadメソッドに追加し、ルートビューコントローラーにcancelMethodを実装します。これはすべてのビューコントローラーで使用できます。ボタンフレームを変更することでボタンの位置を調整できます。方向を変更するには、ボタンの位置を手動で調整します。
UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnCancel addTarget:self
action:@selector(cancelMethod)
forControlEvents:UIControlEventTouchDown];
[btnCancel setBackgroundImage:[UIImage imageNamed:@"image"]
forState:UIControlStateNormal];
btnCancel.frame = CGRectMake(280, 27, 45, 25);
[self.navigationController.view addSubview: btnCancel];
UIBarButtonItemを使用する代わりに、カスタム 'キャンセル' UIButtonをNavigationBarのビューに直接追加できます。
UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.imageView = // Some custom image
cancelButton.frame = CGRectMake(...); // Something far to the right.
[self.navigationController.navigationBar addSubview: cancelButton];
これを行う通常の方法は、そのキャンセルボタンをナビゲーションスタック内のすべての単一のビューコントローラーのnavigationItemに追加することです。上記のアプローチは、より少ないコードを書くことを可能にすることでそれをより単純にすることができますが、それはほんの少しのハックです。