custom - navigation bar iphone x xcode
iOS 11 iPhone X simulator UITabBar iconos y títulos que se representan en la parte superior cubriendo entre sí (29)
¿Alguien tiene problemas con el simulador de iPhone X alrededor del componente UITabBar?
Los míos parecen estar representando los íconos y el título uno encima del otro, no estoy seguro de si me falta algo, también lo ejecuté en el simulador de iPhone 8 y en un dispositivo real donde se ve bien tal como se muestra en el tablero de la historia
iPhone X:
iPhone 8
¡Ajá! En realidad es magia!
Finalmente descubrí esto después de horas de maldecir a Apple.
UIKit realmente maneja esto por usted, y parece que los elementos de la barra de pestañas desplazados se deben a una configuración incorrecta (y probablemente a un error real de UIKit). No hay necesidad de subclases o una vista de fondo.
UITabBar "simplemente funcionará" si está restringido a la parte inferior de la supervista, NO al área segura inferior .
Incluso funciona en el generador de interfaces.
Configuración correcta
- En el generador de interfaces, visualizando como iPhone X, arrastre una UITabBar hacia afuera, donde se engancha en el recuadro inferior seguro. Cuando lo suelte, debería verse correcto (llene el espacio hasta el borde inferior).
- ¡Entonces puede hacer un "Agregar restricciones faltantes" e IB agregará las restricciones correctas y su barra de pestañas funcionará mágicamente en todos los iPhones! (Tenga en cuenta que la restricción inferior parece tener un valor constante igual a la altura del área insegura del iPhone X, pero la constante es en realidad 0)
A veces todavía no funciona.
Lo que es realmente tonto es que también puede ver el error en IB, ¡incluso si agrega las restricciones exactas que IB agrega en los pasos anteriores!
- Arrastre un UITabBar y no lo ajuste al recuadro inferior seguro
- Agregue restricciones iniciales, finales e inferiores a la vista general (área no segura) Extrañamente, esto se solucionará solo si hace un "Invertir primero y segundo elemento" en el inspector de restricciones para la restricción inferior. ¯_ (ツ) _ / ¯
Creé un nuevo UITabBarController en mi guión gráfico y envié todos los controladores de vista a este nuevo UITabBarConttoller. Entonces, todo funciona bien en el simulador de iPhone X.
Creo que este es un error UIKit de iPhoneX. porque funciona:
if (@available(iOS 11.0, *)) {
if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.top > 0.0) {
self.tabBarBottomLayoutConstraint.constant = 1.0;
}
}
Creo que podría estar colocando la barra de pestañas contra la guía de diseño segura inferior. Probablemente esto no sea lo que desea, ya que la barra de pestañas parece hacer sus propios cálculos para colocar los elementos de la barra de pestañas de forma segura en la parte superior de la línea de inicio en el iPhone X. Configure su restricción inferior contra la parte inferior de la supervista . Debería ver que se presenta correctamente en el iPhone X , así como en otros iPhones.
De este tutorial:
https://github.com/eggswift/ESTabBarController
y después de la inicialización de la barra de pestañas escribiendo esta línea en la clase appdelegate
(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator
Resuelve mi problema de la barra de pestañas.
Espero que resuelva tu problema
Gracias
Encontré esto hoy con una UITabBar agregada manualmente al controlador de vista en el guión gráfico, cuando me alineaba en la parte inferior del área segura con una constante de 0 obtendría el problema, pero cambiarlo a 1 solucionaría el problema. Tener la UITabBar hasta 1 píxel más de lo normal era aceptable para mi aplicación.
Estaba teniendo el mismo problema cuando intentaba configurar el marco de UITabBar en mi TabBarController personalizado.
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
Cuando acabo de ajustarlo al nuevo tamaño, el problema desapareció
if(IS_IPHONE_X){
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kPhoneXTabBarHeight, self.view.frame.size.width, kPhoneXTabBarHeight);
}
else{
self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight);
}
Estaba teniendo el mismo problema que se resolvió configurando los elementos de la barra de pestañas después de que se dispusiera la barra de pestañas.
En mi caso, el problema ocurrió cuando:
- Hay un controlador de vista personalizado
- Se crea una UITabBar en el inicializador del controlador de vista
- Los elementos de la barra de pestañas se establecen antes de que se cargue la vista
- A la vista se cargó la barra de pestañas se agrega a la vista principal del controlador de vista
- Luego, los elementos se representan como usted menciona.
Hay un truco por el cual podemos resolver el problema.
Simplemente coloque su UITabBar dentro de una UIView.
Esto realmente está funcionando para mí.
O puede seguir este Link para más detalles.
La UITabBar aumenta en altura para estar por encima del botón / línea de inicio, pero dibuja la subvista en su ubicación original y superpone el UITabBarItem sobre la subvista.
Como solución alternativa, puede detectar el iPhone X y luego reducir la altura de la vista en 32 píxeles para asegurarse de que la barra de pestañas se muestre en el área segura sobre la línea de inicio.
Por ejemplo, si está creando su TabBar reemplaza programáticamente
self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = self.tabBarController;
Con este:
#define IS_IPHONEX (([[UIScreen mainScreen] bounds].size.height-812)?NO:YES)
self.tabBarController = [[UITabBarController alloc] init];
self.window.rootViewController = [[UIViewController alloc] init] ;
if(IS_IPHONEX)
self.window.rootViewController.view.frame = CGRectMake(self.window.rootViewController.view.frame.origin.x, self.window.rootViewController.view.frame.origin.y, self.window.rootViewController.view.frame.size.width, self.window.rootViewController.view.frame.size.height + 32) ;
[self.window.rootViewController.view addSubview:self.tabBarController.view];
self.tabBarController.tabBar.barTintColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0] ;
NOTA: Esto podría ser un error, ya que el sistema operativo establece los tamaños de vista y el diseño de la barra de pestañas. Probablemente debería aparecer según la captura de pantalla de Apple en las Pautas de interfaz humana del iPhone X aquí: https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/
La respuesta proporcionada por VoidLess soluciona los problemas de TabBar solo parcialmente. Soluciona problemas de diseño dentro de la barra de pestañas, pero si usa viewcontroller que oculta la barra de pestañas, la barra de pestañas se representa incorrectamente durante las animaciones (para reproducirlo es mejor 2 tener 2 segues, uno modal y otro push. Si alterna los segmentos, puede vea que la barra de pestañas está fuera de lugar). El siguiente código soluciona ambos problemas. Buen trabajo manzana.
class SafeAreaFixTabBar: UITabBar {
var oldSafeAreaInsets = UIEdgeInsets.zero
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if oldSafeAreaInsets != safeAreaInsets {
oldSafeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
size.height += bottomInset
}
}
return size
}
override var frame: CGRect {
get {
return super.frame
}
set {
var tmp = newValue
if let superview = superview, tmp.maxY !=
superview.frame.height {
tmp.origin.y = superview.frame.height - tmp.height
}
super.frame = tmp
}
}
}
Código Objective-C:
@implementation VSTabBarFix {
UIEdgeInsets oldSafeAreaInsets;
}
- (void)awakeFromNib {
[super awakeFromNib];
oldSafeAreaInsets = UIEdgeInsetsZero;
}
- (void)safeAreaInsetsDidChange {
[super safeAreaInsetsDidChange];
if (!UIEdgeInsetsEqualToEdgeInsets(oldSafeAreaInsets, self.safeAreaInsets)) {
[self invalidateIntrinsicContentSize];
if (self.superview) {
[self.superview setNeedsLayout];
[self.superview layoutSubviews];
}
}
}
- (CGSize)sizeThatFits:(CGSize)size {
size = [super sizeThatFits:size];
if (@available(iOS 11.0, *)) {
float bottomInset = self.safeAreaInsets.bottom;
if (bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90)) {
size.height += bottomInset;
}
}
return size;
}
- (void)setFrame:(CGRect)frame {
if (self.superview) {
if (frame.origin.y + frame.size.height != self.superview.frame.size.height) {
frame.origin.y = self.superview.frame.size.height - frame.size.height;
}
}
[super setFrame:frame];
}
@end
La solución más simple que encontré fue simplemente agregar un espacio de 0.2 pt entre la parte inferior de la barra de pestañas y la parte inferior de safeAreaLayoutGuide.bottomAnchor así.
tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2)
Me encontré con este error en mi guión gráfico de la pantalla de inicio, que no se puede personalizar mediante subclases.
Después de un análisis, logré descubrir la causa: estaba usando una
UITabBar
directamente.
Cambiar a un
UITabBarController
, que encapsula un
UITabBar
, resolvió el problema.
Nota: es posible que iOS 11.1 solucione esto, por lo que es posible que no afecte las aplicaciones reales de iPhone X (ya que es probable que el iPhone X se lance con iOS 11.1).
Me rasqué la cabeza por este problema.
Parece estar asociado con la forma en que tabBar se inicializa y agrega para ver la jerarquía.
También probé las soluciones anteriores, como llamar
invalidateIntrinsicContentSize
, establecer el marco y también
bottomInsets
dentro de una subclase UITabBar.
Parecen funcionar sin embargo temporalmente y se rompen de algún otro escenario o regresan a la barra de pestañas al causar un problema de diseño ambiguo.
Cuando estaba depurando el problema, intenté asignar las restricciones de altura a UITabBar y centerYAnchor, sin embargo, ninguno solucionó el problema.
En vista del depurador, me di cuenta de que la altura de tabBar era correcta antes y después de que se reprodujera el problema, lo que me llevó a pensar que el problema estaba en las subvistas.
Utilicé el siguiente código para solucionar con éxito este problema sin retroceder en ningún otro escenario.
- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
if (DEVICE_IS_IPHONEX())
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
for (UIView *view in self.tabBar.subviews)
{
if ([NSStringFromClass(view.class) containsString:@"UITabBarButton"])
{
if (@available (iOS 11, *))
{
[view.bottomAnchor constraintEqualToAnchor:view.superview.safeAreaLayoutGuide.bottomAnchor].active = YES;
}
}
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
[self.tabBar layoutSubviews];
}];
}
}
Suposiciones: estoy haciendo esto solo para iPhone X, ya que no parece reproducirse en ningún otro dispositivo en este momento. Se basa en el supuesto de que Apple no cambia el nombre de la clase UITabBarButton en futuras versiones de iOS. Estamos haciendo esto en UITabBarButton solo cuando significa que si Apple agrega más subvistas internas a UITabBar, es posible que necesitemos modificar el código para ajustarlo.
¡Déjame saber si esto funciona, estará abierto a sugerencias y mejoras!
Debería ser simple crear un equivalente rápido para esto.
Mi caso fue que había establecido una altura UITabBar personalizada en mi UITabBarController, así:
override func viewWillLayoutSubviews() {
var tabFrame = tabBar.frame
tabFrame.size.height = 60
tabFrame.origin.y = self.view.frame.size.height - 60
tabBar.frame = tabFrame
}
La eliminación de este código fue la solución para que la TabBar se mostrara correctamente en el iPhone X.
Mover la barra de pestañas 1 punto desde la parte inferior funcionó para mí.
Por supuesto, obtendrá un espacio al hacerlo que tendrá que llenar de alguna manera, pero el texto / íconos ahora están colocados correctamente.
Para iPhone, puede hacer esto, Subclase UITabBarController.
class MyTabBarController: UITabBarController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.tabBar.invalidateIntrinsicContentSize()
}
}
}
Ir a Storyboard y permitir Usar la Guía de diseño de área segura y cambiar la clase de UITabbarController a MyTabBarController
PD Esta solución no se prueba en caso de aplicación universal y iPad.
Para mí esto solucionó todos los problemas:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let currentHeight = tabBar.frame.height
tabBar.frame = CGRect(x: 0, y: view.frame.size.height - currentHeight, width: view.frame.size.width, height: currentHeight)
}
Para mí, eliminar el trabajo
[self.tabBar setBackgroundImage:]
, tal vez sea un error UIKit
Pude solucionar el problema simplemente llamando invalidateIntrinsicContentSize en la UITabBar en viewDidLayoutSubviews.
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.tabBar invalidateIntrinsicContentSize];
}
Nota: La parte inferior de la barra de pestañas deberá estar contenida en la parte inferior de la vista principal, en lugar del área segura, y la barra de pestañas no debe tener restricciones de altura.
Resuelto para mí llamando a
[tabController.view setNeedsLayout];
después de descartar el modal en el bloque de finalización.
[vc dismissViewControllerAnimated:YES completion:^(){
UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController;
[tabController.view setNeedsLayout];
}];
Se solucionó usando UITabBar subclases para aplicar safeAreaInsets:
class SafeAreaFixTabBar: UITabBar {
var oldSafeAreaInsets = UIEdgeInsets.zero
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if oldSafeAreaInsets != safeAreaInsets {
oldSafeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 {
size.height += bottomInset
}
}
return size
}
}
Si tiene alguna restricción de altura para la barra de pestañas, intente eliminarla.
Enfrenté el mismo problema y eliminarlo resolvió el problema.
Tuve el problema similar, al principio se renderizó correctamente pero después de configurar
badgeValue
en uno de los tabBarItem rompió el diseño.
Lo que funcionó para mí sin subclasificar
UITabBar
fue esto, en mi subclase
UITabBarController
ya creada.
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLayoutYAxisAnchor *tabBarBottomAnchor = self.tabBar.bottomAnchor;
NSLayoutYAxisAnchor *tabBarSuperviewBottomAnchor = self.tabBar.superview.bottomAnchor;
[tabBarBottomAnchor constraintEqualToAnchor:tabBarSuperviewBottomAnchor].active = YES;
[self.view layoutIfNeeded];
}
Utilicé la vista general tabBar para asegurarme de que las restricciones / anclajes estén en la misma jerarquía de vistas y evitar bloqueos.
Según mi entendimiento, dado que esto parece ser un error de UIKit, solo necesitamos reescribir / restablecer las restricciones de la barra de pestañas para que el motor de diseño automático pueda diseñar la barra de pestañas nuevamente correctamente.
anular
UITabBar
sizeThatFits(_)
para safeArea
extension UITabBar {
static let height: CGFloat = 49.0
override open func sizeThatFits(_ size: CGSize) -> CGSize {
guard let window = UIApplication.shared.keyWindow else {
return super.sizeThatFits(size)
}
var sizeThatFits = super.sizeThatFits(size)
if #available(iOS 11.0, *) {
sizeThatFits.height = UITabBar.height + window.safeAreaInsets.bottom
} else {
sizeThatFits.height = UITabBar.height
}
return sizeThatFits
}
}
intente cambiar la pantalla de bienvenida con tamaño @ 3x es (3726 × 6624)
viewWillAppear
esto para
viewWillAppear
de mi
UITabBarController
personalizado, porque ninguna de las respuestas proporcionadas funcionó para mí:
tabBar.invalidateIntrinsicContentSize()
tabBar.superview?.setNeedsLayout()
tabBar.superview?.layoutSubviews()