ios - guidelines - navigation bar swift 4
No se puede establecer titleView en el centro de la barra de navegación porque el botón Atrás (10)
1) Puedes intentar configurar tu imagen como imagen de fondo de UINavigationBar llamando
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"color.png"] forBarMetrics:UIBarMetricsDefault];
dentro del método viewDidLoad
.
De esa forma, siempre estará centrado, pero si tiene el botón back
con título largo como elemento de navegación a la izquierda, puede aparecer encima de su logotipo. Y probablemente debería, al principio, crear otra imagen del mismo tamaño que la barra de navegación, luego dibujar su imagen en el centro y luego establecerla como imagen de fondo.
2) O en lugar de configurar su vista de imagen como titleView
, puede intentar simplemente agregar como una subvista, por lo que no tendrá las restricciones relacionadas con los elementos del botón de barra derecha e izquierda.
Estoy usando una vista de imagen para mostrar una imagen en mi barra de navegación. El problema es que no puedo establecerlo en el centro correctamente debido al botón Atrás. Revisé las preguntas relacionadas y tuve casi el mismo problema antes que lo resolví, pero esta vez no tengo idea.
Anteriormente resolví este problema con botones de barra falsos, así que traté de agregar un botón de barra falso al lado derecho (e izquierdo), pero no ayudó.
- (void) searchButtonNavBar {
CGRect imageSizeDummy = CGRectMake(0, 0, 25,25);
UIButton *dummy = [[UIButton alloc] initWithFrame:imageSizeDummy];
UIBarButtonItem
*searchBarButtonDummy =[[UIBarButtonItem alloc] initWithCustomView:dummy];
self.navigationItem.rightBarButtonItem = searchBarButtonDummy;
}
- (void)setNavBarLogo {
[self setNeedsStatusBarAppearanceUpdate];
CGRect myImageS = CGRectMake(0, 0, 44, 44);
UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
[logo setImage:[UIImage imageNamed:@"color.png"]];
logo.contentMode = UIViewContentModeScaleAspectFit;
self.navigationItem.titleView = logo;
[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0.0f, 0.0f) forBarMetrics:UIBarMetricsDefault];
}
Creo que debería funcionar bien porque en este caso el titleView
tiene botones de barra en el mismo lado. ¿Hay alguna explicación de por qué funcionó con los botones de barra que se creó mediante programación pero que no funciona con el botón de retroceso común?
En Swift, esto es lo que funcionó para mí, sin embargo, no es la mejor solución (básicamente, agréguelo a navigationBar):
let titleIV = UIImageView(image: UIImage(named:"some"))
titleIV.contentMode = .scaleAspectFit
titleIV.translatesAutoresizingMaskIntoConstraints = false
if let navigationController = self.navigationController{
navigationController.navigationBar.addSubview(titleIV)
titleIV.centerXAnchor.constraint(equalTo:
navigationController.navigationBar.centerXAnchor).isActive = true
titleIV.centerYAnchor.constraint(equalTo: navigationController.navigationBar.centerYAnchor).isActive = true
}
else{
view.addSubview(titleIV)
titleIV.topAnchor.constraint(equalTo: view.topAnchor, constant: UIApplication.shared.statusBarFrame.height).isActive = true
titleIV.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Extendiendo la respuesta de Darren, una solución para mí fue devolver un sizeThatFits
con el tamaño UILabel
. Resulta que esto se llama después de layoutSubViews por lo que la etiqueta tiene un tamaño.
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: titleLabel.frame.width + titleInset*2, height: titleLabel.frame.height)
}
También tenga en cuenta que tengo + titleInset*2
porque estoy configurando las restricciones horizontales de esta manera:
titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: titleInset),
titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -titleInset)
No use titleView.
Solo agregue su imagen a navigationController.navigationBar
CGRect myImageS = CGRectMake(0, 0, 44, 44);
UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
[logo setImage:[UIImage imageNamed:@"color.png"]];
logo.contentMode = UIViewContentModeScaleAspectFit;
logo.center = CGPointMake(self.navigationController.navigationBar.width / 2.0, self.navigationController.navigationBar.height / 2.0);
logo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self.navigationController.navigationBar addSubview:logo];
Qun Li funcionó perfectamente para mí. Aquí está el código rápido 2.3:
override var frame: CGRect {
set(newValue) {
super.frame = newValue
if let superview = self.superview {
self.center = CGPoint(x: superview.center.x, y: self.center.y)
}
}
get {
return super.frame
}
}
Si está utilizando una vista personalizada desde una punta, asegúrese de desactivar la distribución automática en el archivo de punta.
Sugiero que anule la función - (void) setFrame: (CGRect) fram como este:
- (void)setFrame:(CGRect)frame {
[super setFrame:frame]; //systom function
self.center = CGPointMake(self.superview.center.x, self.center.y); //rewrite function
}
para que titleView.center siempre sea el lugar correcto
Un ejemplo en la versión Swift 3 de la segunda forma de Darren:
let imageView = UIImageView(image: UIImage(named: "test"))
imageView.contentMode = UIViewContentMode.scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
UINavigationBar
centra automáticamente su titleView
siempre que haya espacio suficiente. Si el título no está centrado, significa que la vista del título es demasiado ancha para UIImageView
, y si configuras el backgroundColor si tu UIImageView
verás que eso es exactamente lo que está sucediendo.
La vista del título es demasiado amplia porque esa barra de navegación cambiará automáticamente el tamaño del título para mantener su contenido, usando -sizeThatFits:
Esto significa que su vista de título siempre se redimensionará al tamaño de su imagen.
Dos posibles soluciones:
La imagen que estás usando es demasiado grande. Utilice una imagen de 44x44 pt de tamaño adecuado con versiones 2x y 3x.
Envuelva UIImageView dentro de una UIView regular para evitar el cambio de tamaño.
Ejemplo:
UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"test.jpeg"]];
imageView.contentMode = UIViewContentModeScaleAspectFit;
UIView* titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
imageView.frame = titleView.bounds;
[titleView addSubview:imageView];
self.navigationItem.titleView = titleView;
UINavigationController
un UINavigationController
personalizado que después de UINavigationController
, lo único que tienes que hacer es llamar a showNavBarTitle(title:font:)
cuando quieras mostrar y removeNavBarTitle()
cuando quieras ocultar:
class NavigationController: UINavigationController {
private static var mTitleFont = UIFont(name: <your desired font (String)> , size: <your desired font size -- however, font size will automatically adjust so the text fits in the label>)!
private static var mNavBarLabel: UILabel = {
let x: CGFloat = 60
let y: CGFloat = 7
let label = UILabel(frame: CGRect(x: x, y: y, width: UIScreen.main.bounds.size.width - 2 * x, height: 44 - 2 * y))
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
label.font = NavigationController.mTitleFont
label.numberOfLines = 0
label.textAlignment = .center
return label
}()
func showNavBarLabel(title: String, font: UIFont = mTitleFont) {
NavigationController.mNavBarLabel.text = title
NavigationController.mNavBarLabel.font = font
navigationBar.addSubview(NavigationController.mNavBarLabel)
}
func removeNavBarLabel() {
NavigationController.mNavBarLabel.removeFromSuperview()
}
}
Encuentro el mejor lugar para llamar a showNavBarTitle(title:font:)
y removeNavBarTitle()
en los viewWillAppear()
y viewWillDisappear()
del controlador de vista, respectivamente:
class YourViewController: UIViewController {
func viewWillAppear() {
(navigationController as! NavigationController).showNavBarLabel(title: "Your Title")
}
func viewWillDisappear() {
(navigationController as! NavigationController).removeNavBarLabel()
}
}