web-dev-qa-db-fra.com

iOS 11 navigationItem.titleView Width Not Set

Voir un comportement sur iOS11 avec un objet navigationItem.titleView où la largeur de titleView n'est pas la largeur totale de l'écran.

J'ai une vue personnalisée que j'ai définie comme titleView. Avant iOS11, la vue remplissait la zone de la barre de navigation. Mais iOS 11 n’est pas en train de redimensionner pour remplir la largeur de l’écran.

J'ai essayé de définir le cadre de la vue avant de définir titleView, mais sans succès. J'ai essayé de forcer le titleViews superview aux contraintes de mise en page, mais pas de chance. 

Captures d'écran ci-joint:

iOS10:

 enter image description here

iOS11:

 enter image description here

Quelqu'un d'autre en fait l'expérience?

52
gngrwzrd

Je l'ai compris. J'ai dû remplacer le getter intrinsicContentSize pour la vue et le champ de texte.

J'ai défini la largeur sur CGFloat.greatestFiniteMagnitude afin qu'elle soit toujours aussi large que l'écran.

Mettre à jour:

Depuis que j'ai passé quelques heures sur cette question, j'espère que d'autres parviendront à se rattraper plus rapidement en rapprochant tout

J'ai créé une sous-classe personnalisée de TitleView, appelée CustomTitleView, voici le code:

import UIKit

class CustomTitleView: UIView {

  override var intrinsicContentSize: CGSize {
    return UIView.layoutFittingExpandedSize
  }
}

et la partie la plus importante que j'ai manquée dès le début était la suivante:

 enter image description here

89
gngrwzrd

En utilisant la réponse de @ falkon, voici le code:

Ajouter ce code à la vue utilisée comme titleView

override var intrinsicContentSize: CGSize {
    return UILayoutFittingExpandedSize
} 
37
João Nunes

Corrigé en créant une sous-classe de UIView et en lui affectant une vue de titre de UINavigationController

Objectif c:

#import "FLWCustomTitleView.h"

@implementation FLWCustomTitleView

- (CGSize )intrinsicContentSize {
  return UILayoutFittingExpandedSize;
}

@end

 enter image description here  enter image description here

14
Alex Kosyakov

régler intrinsicContentSize sur UILayoutFittingExpandedSize fonctionne aussi très bien

12
konradowy

Je devais adapter un UIImageView en tant que navigationItem.titleView. Le rapport de format était correct, mais la taille intrinsèque de ContentSize le rendait trop volumineux. La mise à l'échelle de l'image entraînait une qualité d'image médiocre.

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 30)];
[imageView setImage:image];
[imageView.widthAnchor constraintEqualToConstant:80].active = YES;
[imageView.heightAnchor constraintEqualToConstant:30].active = YES;
[imageView setContentMode:UIViewContentModeScaleAspectFit];
self.navigationItem.titleView = imageView;
6
Yedy

Le plus important est que vous devez écraser customTitleView en tant que titleView:

self.navigationItem.titleView = [auto titleView]; 

#pragma mark - getter

- (UIView *)titleView {
    UIView *navTitleView = [HFCalenderTitleView new];
    navTitleView.frame = CGRectMake(0.0, 0.0, HorizontalFrom750(200.0), 44.0);

    [navTitleView addSubview:self.titleLabel];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(navTitleView);
    }];

    CGFloat btnWidth = 30.0;
    [navTitleView addSubview:self.previousButton];
    self.previousButton.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 15.0);
    [self.previousButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(navTitleView);
        make.top.bottom.equalTo(navTitleView);
        make.width.equalTo(@(btnWidth));
    }];
    [navTitleView addSubview:self.nextBtn];
    self.nextBtn.imageEdgeInsets = UIEdgeInsetsMake(0.0, 15.0, 0.0, 0.0);
    [self.nextBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(navTitleView);
        make.top.bottom.equalTo(navTitleView);
        make.width.equalTo(@(btnWidth));
    }];

    return navTitleView;
}
#pragma mark - customTitleView

#import "HFCalenderTitleView.h"
@implementation HFCalenderTitleView
- (CGSize)intrinsicContentSize{
    return CGSizeMake(HorizontalFrom750(200.0), 40); // the target size
}

 enter image description here

 enter image description here

2
Qun Li

Lorsque vous avez une vue UIView en tant que sous-vue dans CustomTitleView, la solution intrinsicContentSize ne fonctionne pas. Pour moi, dans XCODE 9 sous iOS 11 uniquement. donc j'ai aimé comme ci-dessous, fonctionne bien pour moi, cela pourrait-il aider quelqu'un. 

@interface CustomTitleView : UIView
@property (weak, nonatomic) IBOutlet UIView *doubleTitleView;
@end

@implementation CustomTitleView
- (void)awakeFromNib {
    [super awakeFromNib];
    int width = _doubleTitleView.frame.size.width;
    int height = _doubleTitleView.frame.size.height;
    if (width != 0 && height != 0) {

        NSLayoutConstraint *widthConstraint =  [_doubleTitleView.widthAnchor constraintEqualToConstant:width];
        NSLayoutConstraint *heightConstraint = [_doubleTitleView.heightAnchor constraintEqualToConstant:height];

        [_doubleTitleView addConstraint:heightConstraint];
        [_doubleTitleView addConstraint:widthConstraint];
        [heightConstraint setActive:TRUE];
        [widthConstraint setActive:TRUE];
    }
}
2

Vous pouvez également utiliser des contraintes si vous ne souhaitez pas remplacer intrinsicContentSize. Voici une démo de SnapKit

self.navigationItem.titleView = titleView
if #available(iOS 11, *) {
    titleView.snp.makeConstraints({ (make) in
        make.width.equalTo(250) // fixed width
        make.height.equalTo(30) // less than 44(height of naviagtion bar)
    })
}else {
    titleView.frame = ...
}

Mais s'il y a plus d'une barre de navigation sur l'un des côtés (gauche ou droite), vous devez utiliser intrinsicContentSize;

1
hstdt

J'ai eu le même problème, mais avec la définition d'une UIImage comme navigationItemtitleView

Ce que j'ai fait est que j'ai redimensionné l'image à la taille souhaitée en utilisant les éléments suivants:

-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

Et appelez-le comme suit:

-(void)setHeaderImage{
    UIImage * image = [self imageWithImage:[UIImage imageNamed:@"headerImage"] scaledToSize:CGSizeMake(150, 27)];
    UIImageView *  imageView = [[UIImageView alloc]initWithImage:image];
    imageView.frame = CGRectMake(0, 0, 150, 27);
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.navigationItem.titleView = imageView;
}
0
Mutawe

return UILayoutFittingExpandedSize ne m'a pas aidé, car la vue a été ajoutée verticalement plusieurs fois pour remplir la présentation.

La solution consistait à remplacer intrinsicContentSize dans la largeur de la vue personnalisée en définissant la largeur maximale de l'écran:

 - (CGSize)intrinsicContentSize {
    //fills empty space. View will be resized to be smaller, but if it is too small - then it stays too small
    CGRect frame = self.frame;
    frame.size.width = MAX(SCREEN_WIDTH, SCREEN_HEIGHT);
    return frame.size;
}
0
Eddwhis

Essayez d'utiliser le standard UISearchBar/UISearchController

En fait, ce que vous devez faire - si vous pouvez utiliser un UISearchBar/un UISearchController standard, c’est d’afficher la barre de recherche de la manière suivante, qui respecte la zone de sécurité et est donc parfaite sur iPhone X et dans chaque orientation de périphérique:

func presentSearchController() {
    let searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.text = "any text"

    if #available(iOS 11.0, *) {
        self.navigationItem.searchController = searchController
        searchController.isActive = true
    } else {
        present(searchController, animated: true, completion: nil)
    }
}

Références

https://developer.Apple.com/videos/play/fall2017/201/https://medium.com/@PavelGnatyuk/large-title-and-search-in-ios- 11-514d5e020cee

0
blackjacx

Ajout aux réponses existantes:

Si votre vue de titre personnalisée est une vue qui a déjà une taille de contenu intrinsèque par défaut (autre que .zero), par exemple une UILabel, une UITextView ou une UIButton, vous pouvez simplement mettre

yourCustomTitleView.translatesAutoresizingMaskIntoConstraints = false

et il s'ajustera automatiquement pour ne contenir que son contenu, mais ne chevauchera jamais les vues d'élément gauche et droite.


Par exemple, vous pouvez faire glisser un bouton dans la zone d'affichage du titre d'une barre de navigation dans Interface Builder, créer un point de vente titleButton dans votre contrôleur de vue, puis effectuer les opérations suivantes:

override func viewDidLoad() {
    super.viewDidLoad()
    titleButton.translatesAutoresizingMaskIntoConstraints = false
}
0
Mischa

Swift 4.2 Version de Réponse de Yedy

let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 80, height: 30))
imageView.image = image
imageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 30).isActive = true
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView

Converti à l'aide de Swiftify .

0
Md. Ibrahim Hassan