iphone - item - uitabbarcontroller swift 4
Cómo ocultar uitabbarcontroller (15)
Tengo un problema con UITabBarController
. En mi aplicación, quiero ocultarlo pero sin usar hidesBottomBarWhenPushed
porque quiero ocultarlo no cuando lo empujé. Por ejemplo, quiero ocultarlo cuando presiono un botón Ocultar en mi aplicación.
Leí muchos artículos en Google, pero no puedo averiguar cómo puedo hacer esto.
@karlbecker_com La respuesta funciona perfectamente tanto para iPhone 4 como para iPhone 5. Si alguien tiene problemas con la barra negra iOS7 en la parte inferior, configure tabBarController como translúcido.
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
// To Hide the black line in IOS7 only, this extra bit is required
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
[self.tabBarController.tabBar setTranslucent:YES];
}
Aquí hay un puerto rápido reducido de la versión de @Thomas Verbeek para aquellos VCs sin tablas (probado bajo iOS 8.4):
extension UITabBarController {
/**
Shows or hides the tabbar
:param: hidden whether to show or hide the tabbar
:param: animationDuration the animation''s duration
*/
func setHidden(hidden:Bool, animationDuration:NSTimeInterval = 0.25) {
let screenRect = UIScreen.mainScreen().bounds
var fHeight = screenRect.size.height
if !hidden {
fHeight -= self.tabBar.frame.size.height
}
UIView.animateWithDuration(animationDuration, animations: {
for view in self.view.subviews as! [UIView] {
if view is UITabBar {
view.frame = CGRectMake(
view.frame.origin.x,
fHeight,
view.frame.size.width,
view.frame.size.height)
}
}
})
}
}
Y aquí el puerto más directo (no probado):
extension UITabBarController {
/**
Shows or hides the tabbar
:param: hidden whether to show or hide the tabbar
:param: animationDuration the animation''s duration
*/
func setHidden(hidden:Bool, animationDuration:NSTimeInterval = 0.25) {
let screenRect = UIScreen.mainScreen().bounds
var fHeight = screenRect.size.height
if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
fHeight = screenRect.size.width
}
if !hidden {
fHeight -= self.tabBar.frame.size.height
}
UIView.animateWithDuration(animationDuration, animations: {
for view in self.view.subviews as! [UIView] {
if view is UITabBar {
view.frame = CGRectMake(
view.frame.origin.x,
fHeight,
view.frame.size.width,
view.frame.size.height)
}
else if hidden {
view.frame = CGRectMake(
view.frame.origin.x,
view.frame.origin.y,
view.frame.size.width,
fHeight)
}
}
}, completion: { finished in
if !hidden {
UIView.animateWithDuration(animationDuration, animations: {
for view in self.view.subviews as! [UIView] {
if !(view is UITabBar) {
view.frame = CGRectMake(
view.frame.origin.x,
view.frame.origin.y,
view.frame.size.width,
fHeight)
}
}
})
}
})
}
}
Desde IOS 7.1, soluciones "Swift" :
self.tabBarController?.tabBar.hidden = true // hide tabbar
self.tabBarController?.tabBar.hidden = false // show tabbar
Espero que esto pueda ayudar!
En tu método de acción para el botón:
[self.tabBarController.tabBar setHidden:YES];
Esta es la respuesta de karlbecker_com, portada a MonoTouch (Xamarin.iOS). La única diferencia es que implementé los métodos en una clase que hereda de UITabBarController, por lo que las referencias a " tabbarcontroller
" fueron reemplazadas por " this
".
public void HideTabBar()
{
var screenRect = UIScreen.MainScreen.Bounds;
float fHeight = screenRect.Height;
if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
|| UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
{
fHeight = screenRect.Width;
}
UIView.BeginAnimations(null);
UIView.SetAnimationDuration(0.4);
foreach(UIView view in this.View.Subviews)
{
if(view is UITabBar)
{
view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
}
else
{
view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
view.BackgroundColor = UIColor.Black;
}
}
UIView.CommitAnimations();
}
public void ShowTabBar()
{
var screenRect = UIScreen.MainScreen.Bounds;
float fHeight = screenRect.Height - 49f;
if(UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
|| UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
{
fHeight = screenRect.Width - 49f;
}
UIView.BeginAnimations(null);
UIView.SetAnimationDuration(0.4);
foreach(UIView view in this.View.Subviews)
{
if(view is UITabBar)
{
view.Frame = new RectangleF(view.Frame.X, fHeight, view.Frame.Width, view.Frame.Height);
}
else
{
view.Frame = new RectangleF(view.Frame.X, view.Frame.Y, view.Frame.Width, fHeight);
}
}
UIView.CommitAnimations();
}
Estoy pegando esto desde mi código de trabajo ... puede llamar a estos métodos para ocultar y mostrar el tabbarcontroller ... simplemente pase la instancia de tabbarcontroller a estas funciones ...
// Method call
[self hideTabBar:self.tabBarController];
// Method implementations
- (void)hideTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
}
}
[UIView commitAnimations];
}
- (void)showTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
NSLog(@"%@", view);
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
}
}
[UIView commitAnimations];
}
Intenté casi todas estas respuestas pero ninguna de ellas funcionó para mí. Mi aplicación tiene un UITabBarController como vista raíz, y cada pestaña tiene un UINavigationController. Uno de los UINavigationControllers tiene un UICollectionViewController como el controlador de vista superior. Cuando el usuario selecciona un elemento en UICollectionView, quería que el controlador de la vista detallada se insertara en la pila de navegación. Mi vista de detalles tenía una barra de herramientas en la parte inferior. No quería que la barra de herramientas apareciera en la parte superior de la barra de pestañas, ya que eso parece ridículo, y el cambio de contextos de pestañas no será necesario desde esta vista. Probablemente podría haberlo resuelto colocando manualmente UIToolbars y UITabbars y sin usar UITabbarController y la UIToolbar incorporada, pero eso parecía demasiado refactorizado y un tanto poco elegante.
Al final, mi solución fue bastante simple: ampliar los límites del UITabBarController de la parte inferior de la pantalla. Agregué esto a mi controlador de vista detallada:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Extend the UITabBarController to shift the tab bar off screen
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect tabBarControllerFrame = self.tabBarController.view.frame;
if (animated) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
tabBarControllerFrame.size.height = screenRect.size.height +
self.tabBarController.tabBar.frame.size.height;
[self.tabBarController.view setFrame:tabBarControllerFrame];
[UIView commitAnimations];
}
else {
tabBarControllerFrame.size.height = screenRect.size.height +
self.tabBarController.tabBar.frame.size.height;
[self.tabBarController.view setFrame:tabBarControllerFrame];
}
// Now show the toolbar
[self.navigationController setToolbarHidden:NO animated:animated];
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// Ensure the UITabBarController remains extended when subviews are laid out
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect tabBarControllerFrame = self.tabBarController.view.frame;
tabBarControllerFrame.size.height = screenRect.size.height +
self.tabBarController.tabBar.frame.size.height;
[self.tabBarController.view setFrame:tabBarControllerFrame];
}
Luego, para volver a mostrar la barra de pestañas cuando el usuario aparece en la parte superior de mi UINavigationController, agregué esto a mi controlador de vista superior:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Hide toolbar
[self.navigationController setToolbarHidden:YES animated:animated];
// Tab bar back on to screen
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect tabBarControllerFrame = self.tabBarController.view.frame;
if (tabBarControllerFrame.size.height != screenRect.size.height) {
if (animated) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
tabBarControllerFrame.size.height = screenRect.size.height;
[self.tabBarController.view setFrame:tabBarControllerFrame];
[UIView commitAnimations];
}
else {
tabBarControllerFrame.size.height = screenRect.size.height;
[self.tabBarController.view setFrame:tabBarControllerFrame];
}
}
}
La respuesta anterior de Saurabh puede ampliarse para que también funcione en orientación horizontal:
+ (void) hideTabBar:(UITabBarController *) tabbarcontroller {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
//Support for landscape views
int orientation = [[UIDevice currentDevice] orientation];
int x_pos = 480;
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
x_pos = 320;
}
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, x_pos, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, x_pos)];
}
}
[UIView commitAnimations];
}
`
Los números x_pos correspondientes para showTabBar () son 431
y 271
.
La respuesta modificada de Setomidor para trabajar tanto en paisaje, retrato y iPad (los valores 320 y 480 solo funcionan en iPhone).
- (void) hideTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width;
}
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
view.backgroundColor = [UIColor blackColor];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height - tabbarcontroller.tabBar.frame.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width - tabbarcontroller.tabBar.frame.size.height;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
[UIView commitAnimations];
}
También modifiqué el código para manejar los cambios introducidos en iOS 6 con el cambio de orientación de UIDevice y me aseguro de que funcione correctamente incluso cuando el dispositivo esté boca arriba.
La solución a continuación funciona bien para mí exactamente en el mismo caso de uso en el que tengo que pasar al modo de pantalla completa con la animación TabBar.
Básicamente, la idea es
para hacer una instantánea de UITabBar ;
agrega el UIImage de la instantánea a UIImageView que tiene el mismo marco que UITabBar ;
cambiar el tamaño de la vista subyacente y colocarla en self.tabBarController.view ;
establecer el alfa de UITabBar como 0.0;
coloque el UIImageView con la instantánea de UITabBar en la vista self.tabBarController.view ;
Una vez que se logra lo anterior, realice cualquier tipo de animación
#import "QuartzCore/CALayer.h" @implementation FTBFirstViewController { BOOL hidden; UIImageView *fakeTabBarImageView; UIView *viewToResize; } - (void)viewDidLoad { [super viewDidLoad]; ////////////////////////////// // Create your viewToResize ////////////////////////////// [self.view addSubview:viewToResize]; hidden = NO; } - (void)hideTabBar:(id)sender { if (!hidden) { // // to create the fake UITabBar fakeTabBarImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; UIImage *fakeTabBarImage = [self imageScreenshotFromView:self.tabBarController.tabBar]; fakeTabBarImageView.image = fakeTabBarImage; fakeTabBarImageView.frame = self.tabBarController.tabBar.frame; // // to resize underlying UIView viewToResize.frame = (CGRect){viewToResize.frame.origin.x, viewToResize.frame.origin.y + 20.f, viewToResize.frame.size.width, viewToResize.frame.size.height + fakeTabBarImageView.frame.size.height}; // // to hide real UITabBar self.tabBarController.tabBar.alpha = 0.0; // // to add views in exactly this order [self.tabBarController.view addSubview:viewToResize]; [self.tabBarController.view addSubview:fakeTabBarImageView]; // // do any sort of animation [UIView animateWithDuration:0.8 animations:^{ fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y + fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size}; }]; hidden = YES; } else { [UIView animateWithDuration:0.8 animations:^{ fakeTabBarImageView.frame = (CGRect){fakeTabBarImageView.frame.origin.x, fakeTabBarImageView.frame.origin.y - fakeTabBarImageView.frame.size.height, fakeTabBarImageView.frame.size}; } completion:^(BOOL complete){ self.tabBarController.tabBar.alpha = 1.0; [fakeTabBarImageView removeFromSuperview]; fakeTabBarImageView = nil; viewToResize.frame = self.view.frame; [self.view addSubview:viewToResize]; [fakeTabBarImageView removeFromSuperview]; }]; hidden = NO; } } - (UIImage *)imageScreenshotFromView:(UIView *)aView { UIImage *viewImage; UIGraphicsBeginImageContextWithOptions(aView.bounds.size, aView.opaque, [[UIScreen mainScreen] scale]); [aView.layer renderInContext:UIGraphicsGetCurrentContext()]; viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return viewImage; }
Las soluciones de Saurahb y karlbecker_com son geniales, aunque pueden causar un efecto de estallido obvio cuando la vista contiene una vista de tabla mientras la barra de pestañas hace una copia de respaldo. Hice algunas modificaciones y las combiné en una sola función (como una categoría en UITabBarController). No es completamente perfecto (animación de corrección retrasada) pero da buenos resultados con las tablas.
Si te gustan los bloques y categorías de animación, pruébalo. Orientación y dispositivo amigable.
UITabBarController + ShowHideBar.m:
#import "UITabBarController+ShowHideBar.h"
@implementation UITabBarController (ShowHideBar)
- (void) setHidden:(BOOL)hidden{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) ){
fHeight = screenRect.size.width;
}
if(!hidden) fHeight -= self.tabBar.frame.size.height;
[UIView animateWithDuration:0.25 animations:^{
for(UIView *view in self.view.subviews){
if([view isKindOfClass:[UITabBar class]]){
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}else{
if(hidden) [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
}completion:^(BOOL finished){
if(!hidden){
[UIView animateWithDuration:0.25 animations:^{
for(UIView *view in self.view.subviews)
{
if(![view isKindOfClass:[UITabBar class]])
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}];
}
}];
}
@end
UITabBarController + ShowHideBar.h:
#import <UIKit/UIKit.h>
@interface UITabBarController (ShowHideBar)
- (void) setHidden:(BOOL)hidden;
@end
Uso:
[self.tabBarController setHidden:YES];
[self.tabBarController setHidden:NO];
Ocultar la barra de pestañas no es una solución adecuada, no ajustará la altura de vista de los controladores de vista actuales.
En su lugar, simplemente puede transformar la barra de pestañas, ya sea por su altura (para ocultar) o una transformación de identidad para restablecer a visible.
extension UITabBarController {
func setBarHiddenAnimated(_ hidden:Bool) {
UIView.animate(withDuration: 0.3, animations: {
if hidden {
self.tabBar.transform = CGAffineTransform(translationX: 0, y: self.tabBar.frame.size.height)
} else {
self.tabBar.transform = CGAffineTransform.identity
}
})
}
}
Tenga en cuenta que es posible que deba configurar su controlador de vista para que ''se extienda por debajo de las barras inferiores'' y ''se extienda por debajo de las barras opacas'' para eliminar el fondo negro durante la animación.
Versión rápida y modificada del código @Saurabh
Método
func setTabBarHidden (bool:Bool){
for view in tabBarController!.view.subviews {
if (view.isKindOfClass(UITabBar)){
let tabBar = view as! UITabBar
UIView.animateWithDuration(0.3, animations: { () -> Void in
var offset = CGFloat(50)
if (bool == false){
offset = -50;
}
tabBar.frame = CGRect(origin: CGPointMake(tabBar.frame.origin.x, tabBar.frame.origin.y + offset), size: tabBar.frame.size)
})
}
}
}
Mostrar
override func viewDidLoad() {
setTabBarHidden(true)
}
Esconder
override func viewWillDisappear(animated: Bool) {
setTabBarHidden(false)
}
en iOS8 es suficiente con establecer la propiedad hidden
de tabBar
Al igual que en Swift puedes
rootTabVC = UITabBarController()
rootTabVC?.tabBar.hidden = true
Hago esto en mi didFinishLaunchingWithOptions
en el appdelegate
y funciona bien, creo que si recuerdo correctamente en las versiones anteriores de iOS también necesitabas establecer el frame
de tabBar
fuera de la pantalla; de lo contrario, la tabbar
no se mostraría, pero lo hará todavía ocupa el espacio.
puedes presionar un controlador de vista modal
[self presentModalViewController:myFullscreenViewController animated:YES];
esto creará una vista completa de pantalla completa sobre la actual.
descartar ist con dismissModalViewController:animated: