両側に左と右の両方のバーボタンがあるナビゲーションバーがあります。 customTitlelabel
のtitleViewとして設定したUINavigationItem
があります。
[self.navigationItem setTitleView:customTitleLabel];
今はすべて元気です。問題は、rightbarButtonのサイズが、テキストフィールドの1つで取得した入力に基づいて動的になることです。
したがって、タイトルはボタン間の使用可能なスペースに基づいて自動的に中央に配置されます。
タイトルを固定位置に設定するにはどうすればよいですか?
あなたが直接やりたいことを行うことはできません-タイトルビューの位置はあなたのコントロールの外にあります(UINavigationBar
によって管理されている場合)。
ただし、必要な効果を得るには、少なくとも2つの方法があります。
1)タイトルビューを、ナビゲーションバーの「適切な」タイトルビューとしてではなく、UINavigationBar
のサブビューとして追加します。 (注:これは「公式」に認可されたわけではありませんが、私はそれが完了し、機能することを確認しました。明らかに、タイトルラベルがボタンのビットを上書きすることに注意し、さまざまな方向のさまざまなサイズのナビゲーションバーなどを処理する必要があります。 -少し手間がかかります。)
2)完全に画面の中央に配置されたサブビューを効果的に表示するように計算された位置に特定のサブビュー(UILabelとなる)を表示するインテリジェントなUIViewサブクラスを作成します。これを行うために、インテリジェントUIViewサブクラスは、ラベルサブビューの位置(frame
)を変更することにより、レイアウトイベント(またはframe
プロパティの変更など)に応答します。
個人的に、私はアプローチ2)のアイデアが好きです。
ナビゲーションバーのtitleViewプロパティの設定は問題なく機能します。カスタムビューのフレーム以外のフレームをサブクラス化したり変更したりする必要はありません。
UINavigationBarの幅全体に対して中央に配置するコツは、次のとおりです。
以下は、向き、左または右のバーボタンの幅に関係なく、UINavigationBarの中央に配置されたままのラベルを持つカスタムtitleViewを作成するコードの例です。
self.title = @"My Centered Nav Title";
// Init views with rects with height and y pos
CGFloat titleHeight = self.navigationController.navigationBar.frame.size.height;
UIView *titleView = [[UIView alloc] initWithFrame:CGRectZero];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
// Set font for sizing width
titleLabel.font = [UIFont boldSystemFontOfSize:20.f];
// Set the width of the views according to the text size
CGFloat desiredWidth = [self.title sizeWithFont:titleLabel.font
constrainedToSize:CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, titleLabel.frame.size.height)
lineBreakMode:UILineBreakModeCharacterWrap].width;
CGRect frame;
frame = titleLabel.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleLabel.frame = frame;
frame = titleView.frame;
frame.size.height = titleHeight;
frame.size.width = desiredWidth;
titleView.frame = frame;
// Ensure text is on one line, centered and truncates if the bounds are restricted
titleLabel.numberOfLines = 1;
titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
titleLabel.textAlignment = NSTextAlignmentCenter;
// Use autoresizing to restrict the bounds to the area that the titleview allows
titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
titleView.autoresizesSubviews = YES;
titleLabel.autoresizingMask = titleView.autoresizingMask;
// Set the text
titleLabel.text = self.title;
// Add as the nav bar's titleview
[titleView addSubview:titleLabel];
self.navigationItem.titleView = titleView;
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.topItem?.title = ""
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.title = "Make peace soon"
}
正しい答えは、sizeThatFits:
をカスタムtitleView
のコンテンツサイズとして返します。ナビゲーションバーは、そのためのスペースがなくなるまでカスタムタイトルビューを中央に配置します。
たとえば、内部にUIView
を含むUILabel
コンテナがある場合:
@interface CustomTitleView : UIView
@property UILabel* textLabel;
@end
@implementation CustomTitleView
- (CGSize)sizeThatFits:(CGSize)size {
CGSize textSize = [self.textLabel sizeThatFits:size];
CGSize contentSize = size;
contentSize.width = MIN( size.width, textSize.width );
return contentSize;
}
@end
私はaopsfanの答えを試しましたが、うまくいきませんでした。ブレークポイントにより、バーの中心が "(480.0、22.0)"(X座標はオフ)であることがわかりました。
だから私はそれをこれに変えました:
- (void)layoutSubviews
{
[super layoutSubviews];
// Center Title View
UINavigationItem* item = [self topItem]; // (Current navigation item)
[item.titleView setCenter:CGPointMake(160.0, 22.0)];
// (...Hard-coded; Assuming portrait iPhone/iPod touch)
}
...そしてそれは魅力のように機能します。ビューコントローラーを押したときのスライド/フェード効果はそのままです。 (iOS 5.0)
同様の問題がありました。 私の解決策は、元の戻るボタンを非表示にし、独自の実装を追加することです。システムは左のアイテムのためにスペースを予約するので。
UIImage* cancelIcon = [UIImage imageNamed:@"ic_clear"];
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithImage:cancelIcon style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
セレクターはシンプルです
- (void)back:(UIButton *) sender
{
[self.navigationController popViewControllerAnimated:YES];
}
ああ...そして、ラベルのような動的な長さのコンテンツがある場合は、カスタムタイトルビューで自動レイアウトを使用することを忘れないでください。カスタムビューに追加のレイアウトを追加して、Androidの中央に配置し、先頭と末尾のスペースを "> =" 0に設定することで、「wrap_content」のようにします。
titleView
をUINavigationBarの中央に配置する必要がある同様の状況がありました。 UIViewをサブクラス化し、setFrame:
をオーバーライドするというocculusのアプローチが好きです。次に、フレームをUINavigationBarの寸法の中央に配置します。
UIViewサブクラスで:
-(void)setFrame:(CGRect)frame{
super.frame = CGRectMake(320 / 2 - 50, 44 / 2 - 15, 100, 30);
}
その後、UIViewサブクラスは、通常、各navigationItemのtitleView
に割り当てることができます。開発者は、プログラムで特別なサブビューをUINavigationBarに追加および削除する必要はありません。