iOS 11 navigationItem.titleView Ancho no establecido
uinavigationcontroller uinavigationbar (13)
Adición a las respuestas existentes:
Si su vista de título personalizada es una vista
que ya tiene un tamaño de contenido intrínseco
por defecto (que no sea
.zero
), por ejemplo, un
UILabel
, un
UITextView
o un
UIButton
, simplemente puede configurar
yourCustomTitleView.translatesAutoresizingMaskIntoConstraints = false
y se ajustará automáticamente para encerrar su contenido, pero nunca se superpondrá con las vistas de elementos izquierdo y derecho.
Por ejemplo, puede arrastrar un botón al área de vista de título de una barra de navegación en Interface Builder, crear un
titleButton
de
titleButton
salida en su controlador de vista y luego hacer
override func viewDidLoad() {
super.viewDidLoad()
titleButton.translatesAutoresizingMaskIntoConstraints = false
}
Ver un comportamiento en iOS11 con un navigationItem.titleView donde el ancho de titleView no es el ancho completo de la pantalla.
Tengo una vista personalizada que configuré como titleView. Antes de iOS11, la vista ocupaba el área de la barra de navegación. Pero iOS 11 no cambia el tamaño para llenar el ancho de la pantalla.
Intenté configurar el marco de la vista antes de configurar titleView, pero no tuve suerte. Intenté forzar la supervista titleViews a restricciones de diseño también, pero no tuve suerte.
Capturas de pantalla adjuntas:
iOS10:
iOS11:
¿Alguien más experimenta esto?
Cuando tiene una UIView como subvista dentro de CustomTitleView, la solución intrinsicContentSize no funciona, solo para mí en XCODE 9 en iOS 11. así que me gustó a continuación, funciona bien para mí, podría ayudar a alguien.
@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];
}
}
Lo más importante es que necesita sobrescribir customTitleView como titleView:
self.navigationItem.titleView = [self 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
}
Me lo imaginé. Tuve que anular el captador intrinsicContentSize para la vista y el campo de texto.
Establecí el ancho en CGFloat.greatestFiniteMagnitude para que siempre sea tan ancho como la pantalla.
Actualizar:
Como he pasado un par de horas en este tema, espero que alguien más se ponga al día más rápido al tener todas las cosas juntas
He creado una subclase personalizada de
TitleView
, llamada
CustomTitleView
, aquí está el código:
import UIKit
class CustomTitleView: UIView {
override var intrinsicContentSize: CGSize {
return UIView.layoutFittingExpandedSize
}
}
y la parte más importante que me perdí desde el principio fue esta:
Swift 4.2 Versión de la respuesta 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
Convertido con la ayuda de Swiftify .
También puede usar restricciones si no desea anular
intrinsicContentSize
.
Aquí hay una demostración 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 = ...
}
Pero si hay más de un elemento de barra de navegación en cualquier barra de navegación lateral (izquierda o derecha), debe usar intrinsicContentSize;
Tuve el mismo problema pero al configurar un
UIImage
como el elemento de
navigationItem
titleView
Lo que hice es escalar la imagen al tamaño necesario usando lo siguiente:
-(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;
}
Y llámalo como sigue:
-(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;
}
Tuve que ajustar un UIImageView como navigationItem.titleView. La relación de aspecto se ajustaba pero el tamaño intrínseco del contenido lo hizo demasiado grande. Escalar la imagen condujo a una mala calidad de imagen. Establecer anclajes de diseño funcionó para mí:
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;
Usando la respuesta de @ falkon, aquí está el código:
Agregue este código a la vista que se usa como titleView
override var intrinsicContentSize: CGSize {
return UILayoutFittingExpandedSize
}
establecer
intrinsicContentSize
en
UILayoutFittingExpandedSize
funciona bien
return UILayoutFittingExpandedSize
no me ayudó, porque la vista se agregó verticalmente unas pocas veces más para completar el diseño.
La solución fue anular
intrinsicContentSize
en el ancho de configuración de vista personalizada al ancho máximo de pantalla:
- (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;
}
Intente usar el estándar UISearchBar / UISearchController
En realidad, lo que debe hacer: si puede usar un UISearchBar estándar / un UISearchController, debe mostrar la barra de búsqueda de la siguiente manera que respeta el área segura y, por lo tanto, se ve perfecta en el iPhone X y en la orientación de cada dispositivo:
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)
}
}
Referencias
https://developer.apple.com/videos/play/fall2017/201/ https://medium.com/@PavelGnatyuk/large-title-and-search-in-ios-11-514d5e020cee