web-dev-qa-db-ja.com

iOS 7のカスタムUINavigationBar TitleViewが新しいビューコントローラーをプッシュまたはポップすると移動する

次のコードでUINavigationBarのカスタムタイトルビューを使用しています。

// Set a label to the nav bar
THLabel *titleLabel = [[THLabel alloc] init];
titleLabel.text = @"Test";
titleLabel.font = [UIFont fontWithName:APP_FONT size:22.0];
titleLabel.frame = CGRectMake(0, 0, 100, 30);
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.textColor = CUSTOM_LIGHT_BLUE;
titleLabel.strokeColor = kStrokeColor;
titleLabel.strokeSize = kStrokeSize;
self.navigationItem.titleView = titleLabel;

問題は、新しいビューコントローラーを提示してから元のビューコントローラーに戻ると、このカスタムビューがシフトして再び中央に配置されることです。そのデモについてはビデオをご覧ください。

こちらのビデオをご覧ください https://www.youtube.com/watch?v=961CCVQmpJM&feature=youtu.be

ストーリーボードと各ビューコントローラーのコードの両方を使用して、ナビゲーションコントローラーのすべてのサブビューの自動サイズ変更を無効にしました。

    // Set the navigation bar hidded on the log in view
    UINavigationController* mainViewController = (UINavigationController*)self.appDelegate.window.rootViewController;
    [mainViewController setNavigationBarHidden:YES];
    [[mainViewController navigationBar] setAutoresizesSubviews:NO];

しかし、それでもサイズ変更されます!どうすればこれを停止できますか-何が問題なのですか?ありがとう!

24
PhilBot

titleViewコードをviewWillAppearに設定した場合にのみ、再現可能です。 viewDidLoadに移動すると、問題が修正されます

32
Alex Peda

ラベルをUIViewに埋め込みます。 Interface Builderは、問題に関連している可能性がある何らかの理由で、UILabeltitleViewを直接配置することを好みません。

また、autoResizingMaskUIViewAutoresizingFlexibleTopMarginに設定してみてください。私の経験では、バーのカスタムビューはこのように動作します。

5
Rivera

これは私にも起こりました。あなたができる2つのこと:

1)上記の回答で述べたように、ナビゲーション設定がviewDidLayoutSubviewsまたはviewDidLoadのいずれかで行われていることを確認します

2)左と右のバーボタン項目はnilでしたが、タイトルラベルが設定された後にのみ呼び出されました。 titlelabelをtitleviewに設定する前に、左右のバーボタン項目をnilに設定してください(もちろん、使用しない場合)。

1
hellorrr

上記の@Alex Pedaの回答を拡張すると、viewDidLoad以外のiOS7では、カスタムタイトルの最小タイトル幅があるように見えます。以下が私がしていることです。以下の私のコードに固有のいくつかのメソッドがあることに注意してください。

#define MAX_TITLE_WIDTH 400
#define MIN_TITLE_WIDTH 150

- (void) setNavBarTitle: (NSString *) newTitle;
{
    if (!newTitle) newTitle = @"";
    NSMutableString *title = [newTitle mutableCopy];

    if (![_titleView.text isEqualToString:title]) {

        NSAttributedString *attrTitle = [UIAppearance attributedString:title withFontType:FontTypeTitle | FontTypeBold | FontTypeItalic size: 40.0 andOtherAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]}];
        _titleView.attributedText = attrTitle;
        [_titleView sizeToFit];

        // In iOS7, if you set the nav bar title with a custom view outside of viewDidLoad, there appears to be a minimum title width. Narrower custom view titles are not centered properly. I'm working around this by centering the text in the label, and setting the width of the label to the minimum width.
        if ([Utilities ios7OrLater]) {
            if (_titleView.frameWidth < MIN_TITLE_WIDTH) {
                _titleView.textAlignment = NSTextAlignmentCenter;
                _titleView.frameWidth = MIN_TITLE_WIDTH;
            }
        }

        if (_titleView.frameWidth > MAX_TITLE_WIDTH) {
            _titleView.frameWidth = MAX_TITLE_WIDTH;
        }
    }

    self.navigationItem.titleView = _titleView;
}
1
Chris Prince

私にとってうまくいったのは、目的のタイトルビューを保持する変数をビューコントローラーに作成し、viewDidLoadで初期化することでした。次に、そのビューをviewWillAppearself.navigationItem.titleViewに設定すると、正しく表示されます。 autoResizeMask、rightBarButtonsなどを設定する必要はありません。

例:

class ViewController {
    var myTitleImage: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        myTitleImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
        myTitleImage.contentMode = .scaleAspectFit
        myTitleImage.image = #imageLiteral(resourceName: "my_title_image")
        // etc...
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationItem.titleView = self.myTitleImage
    }    
}
0
Alfonz

私の場合、titleViewの前にUIBarButtonを設定していたために起こりました。 titleViewを最初に設定する必要があります。今は完全に動作します。

0

私は上記のすべての答えを試し、最終的に次のようなビューとラベルを作成しました:

  1. VCにUIView変数を追加しました:

    _let titleView: UIView = {
        // A factory method that returns a customised `UILabel`
        let label = Factory.Label.title() 
    
        let view = UIView()
        view.addSubview(label)
        label.text = localized.mainMenuItemSettings()
        //I use EasyPeasy for my constraints, 
        //but essentially I set top, left, bottom and right anchors to fill my UIView
        label.easy.layout(Edges()) 
        return view
    }()
    _
  2. 次に、私のviewWillAppear(animated:)メソッドで、ビューをtitleViewnavigationItemとして設定します。

    _override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationItem.titleView = titleView
    }
    _

制約が非常に使いやすく、非常にコンパクトであることがわかるので、制約に EasyPeasy を使用します。

0
Septronic