9

Edit: Ich habe John die Prämie zugesprochen, da er viel Mühe in seine Antwort gesteckt hat, und würde es sowieso bekommen, aber es gibt immer noch keine funktionierende Lösung. Ich suche immer noch nach einer Antwort, wenn jemand weiß, wie man das macht, würde es sehr geschätzt werden.Hide UINavBar und UITabBar gleichzeitig mit Animation

Ich möchte eine "Maximieren" -Schaltfläche zu meiner App hinzufügen, die die Navigations- und Tab-Leiste versteckt. Die Navigationsleiste und die Tableiste sollten gleichmäßig ein- und ausgefahren werden, und die innere/Inhaltsansicht sollte mit derselben Geschwindigkeit wie die Navigationsleiste und die Tableiste erweitert und verkleinert werden.

Ich verwendete [self.navigationController setNavigationBarHidden: YES/NO animated: YES]; für die Navigationsleiste und fand diesen Thread How to hide uitabbarcontroller zum Ausblenden der Tableiste.

UITabBar Klassenerweiterung:

- (void) setTabBarHidden:(BOOL)hidden animated:(BOOL)animated { 
    CGRect screenRect = [[UIScreen mainScreen] bounds]; 

    float screenHeight = screenRect.size.height; 
    if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) { 
     screenHeight = screenRect.size.width; 
    } 
    if (!hidden) { 
     screenHeight -= self.tabBar.frame.size.height; 
    } 
    [UIView animateWithDuration: (animated ? UINavigationControllerHideShowBarDuration : 0) animations: ^{ 
     for (UIView* each in self.view.subviews) { 
      if (each == self.tabBar) { 
       [each setFrame: CGRectMake(each.frame.origin.x, screenHeight, each.frame.size.width, each.frame.size.height)]; 
      } else { 
       [each setFrame: CGRectMake(each.frame.origin.x, each.frame.origin.y, each.frame.size.width, screenHeight)]; 
      } 
     } 
    } completion: ^(BOOL finished) { 
     NSLog(@"Animation finished %d", finished); 
    }]; 
} 

Das Problem ist, wenn ich die beiden zugleich (Aus-/Einblenden der nav und Tab-Leiste) verwenden, ist es nicht sauber ist. Wenn die Navigationsleiste zuerst kommt, springt alles, was an der Unterseite verankert ist (siehe Beispiel unten), und wenn die Navigationsleiste zuerst kommt, springt die Spitze.

Beispiel: positioniere ich die UIButton in der rechten unteren Ecke und legen Sie den automatischen Größen

resizeButton.frame = CGRectMake(self.view.bounds.size.width - 50, self.view.bounds.size.height - 100, 32, 32); // hardcoded just for testing purposes 
resizeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin; 

Maske Aber wenn die navbar und Tabbar minimiert die UIButton springt zwischen den beiden Zuständen (nicht gleitet zusammen mit der Registerkarte Bar). Wenn ich es jedoch so ändere, dass es oben rechts angebracht wird, gleitet es perfekt mit der Navigationsleiste.

Weiß jemand, wie man das löst?


bearbeiten: Dies ist der Schrank und eleganteste Lösung, die ich bisher haben (nur ein Arbeitskonzept zu erhalten versuchen):

[UIView animateWithDuration: UINavigationControllerHideShowBarDuration animations: ^{ 
    if (self.isMaximized) { 
     self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height + 49 - 20); 
     [self.navigationController setNavigationBarHidden:YES animated:YES]; 
    } else { 
     self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height - 20); 
     [self.navigationController setNavigationBarHidden:NO animated:YES]; 
    } 
} completion: ^(BOOL finished) { 
    NSLog(@"Frame done: %@", NSStringFromCGRect(self.view.frame)); 
    return; 
}]; 

auf die Maximierung:

  • Verschiebt die Navigationsleiste nach oben und gleichzeitig die Tableiste nach unten.
  • Die Oberseite der inneren/co ntent Blick gleitet nach oben, und der Boden dieser Ansicht springt

auf der Minimierung:

  • Slides die navbar nach unten und schiebt den Tabbar auf, zugleich
  • Die Spitze der Innen-/Seiten gleitet richtig nach unten, aber der Boden springt auf den Endwert, Leerzeichen zurückbleibt, die dann durch das Gleiten Tabbar bedeckt ist

Wenn ich die Reihenfolge der Minimierungs-Animationen (so der navbar animatino rearange wird zuerst) genannt wird, dann springt die oben in der Innen/content Ansicht

Antwort

-2

Try this

Sie Tabbar contrller und Navigationsleiste Animation wie verstecken kann: -

-(IBAction)hide:(id)sender 
{ 
[self hideShowBars]; 
} 
- (void) hideShowBars 
{ 
    CGRect rect = self.navigationController.navigationBar.frame; 
    CGRect rect1 = self.tabBarController.tabBar.frame; 

    if(self.navigationController.navigationBar.isHidden) 
    { 
     [self.navigationController.navigationBar setHidden:NO]; 
     rect.origin.y=self.view.frame.origin.y; 
    } 
    else 
    { 
     rect.origin.y=self.view.frame.origin.y-rect.size.height; 
    } 

    if(self.tabBarController.tabBar.isHidden) 
    { 
     [self.tabBarController.tabBar setHidden:NO]; 
     rect1.origin.y=self.view.frame.size.height-rect1.size.height-rect1.size.height; 
    } 
    else 
    { 
     rect1.origin.y=self.view.frame.size.height; 
    } 
[UIView beginAnimations:nil context:NULL]; 
[UIView setAnimationDuration:0.50]; 
[UIView setAnimationDelegate:self]; 
[UIView setAnimationDidStopSelector:@selector(hideShowBarsAnimationStopped)]; 

self.navigationController.navigationBar.frame=rect; 
self.tabBarController.tabBar.frame = rect1; 
[UIView commitAnimations]; 
} 
- (void) hideShowBarsAnimationStopped 
{ 
if(self.navigationController.navigationBar.frame.origin.y==self.view.frame.origin.y) 
    return; 

if(!self.navigationController.navigationBar.isHidden) 
{ 
    [self.navigationController.navigationBar setHidden:YES]; 
} 

if(!self.tabBarController.tabBar.isHidden) 
{ 
    [self.tabBarController.tabBar setHidden:YES]; 
} 
} 
+0

'beginAnimations' \' commitAnimations'? Diese Art der Animation von Ansichten ist seit langem nicht mehr zugunsten blockbasierter Animationen. – Abizern

+0

Die Größe der inneren/Inhaltsansicht wird nicht geändert. – Raekye

+0

nur ich probierte die Navigationsleiste und die Tableiste nur, wenn Sie die innere/inhaltliche Ansicht ändern möchten. Diesen Code auf die gleiche Weise versuchen. Wenn Sie Zweifel haben, werde ich Ihnen helfen – Ravindhiran

6

die Lösung i Verwendung sollte das Sprungproblem beseitigen, das Sie sehen.

Diese Lösung ist abgeleitet von einer Objective-C-Kategorie gefunden Carlos Oliva's github page, und während das Urheberrecht in diesem Code "alle Rechte vorbehalten" ist, schrieb ich ihm und er gab die Erlaubnis zur Verwendung.

Mein Kategoriecode unterscheidet sich nur geringfügig von seinem Code. Außerdem finden Sie unterhalb des Kategoriencodes den Aufrufcode, den ich in meiner App verwende.

von UITabBarController + HideTabBar.m

// the self.view.frame.size.height can't be used directly in isTabBarHidden or 
// in setTabBarHidden:animated: because the value may be the rect with a transform. 
// 
// further, an attempt to use CGSizeApplyAffineTransform() doesn't work because the 
// value can produce a negative height. 
// cf. http://lists.apple.com/archives/quartz-dev/2007/Aug/msg00047.html 
// 
// the crux is that CGRects are normalized, CGSizes are not. 

- (BOOL)isTabBarHidden { 
    CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform); 
    CGRect tabBarFrame = self.tabBar.frame; 
    return tabBarFrame.origin.y >= viewFrame.size.height; 
} 


- (void)setTabBarHidden:(BOOL)hidden { 
    [self setTabBarHidden:hidden animated:NO]; 
} 


- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated { 
    BOOL isHidden = self.tabBarHidden; 
    if (hidden == isHidden) 
     return; 
    UIView* transitionView = [self.view.subviews objectAtIndex:0]; 

    if (!transitionView) 
    { 
#if DEBUG 
    NSLog(@"could not get the container view!"); 
#endif 
     return; 
    } 

    CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform); 
    CGRect tabBarFrame = self.tabBar.frame; 
    CGRect containerFrame = transitionView.frame; 
    tabBarFrame.origin.y = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height); 
    containerFrame.size.height = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height); 
    [UIView animateWithDuration:kAnimationDuration 
        animations:^{ 
         self.tabBar.frame = tabBarFrame; 
         transitionView.frame = containerFrame; 
        } 
    ]; 
} 

von meinem ScrollableDetailImageViewController.m

- (void)setBarsHidden:(BOOL)hidden animated:(BOOL)animated 
{ 
    [self setTabBarHidden:hidden animated:animated]; 
    [self setStatusBarHidden:hidden animated:animated]; 

    // must be performed after hiding/showing of statusBar 
    [self.navigationController setNavigationBarHidden:hidden animated:animated]; 
} 

- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated 
{ 
    id parent = self.navigationController.parentViewController; 
    if ([parent respondsToSelector:@selector(isTabBarHidden)] 
     && hidden != [parent isTabBarHidden] 
     && [parent respondsToSelector:@selector(setTabBarHidden:animated:)]) 
     [parent setTabBarHidden:hidden animated:animated]; 
} 
+0

Danke, ich werde das ausprobieren. Ist 'kAnimationDuration' einfach irgendein Wert für die Dauer? Und was nutzt 'CGRectApplyAffineTransform'? Ich fand Dokumentation hier https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGAffineTransform/Reference/reference.html, aber wenn ich NSLog den ursprünglichen Rahmen mit dem affine'd Rahmen, bekomme ich den selbe CGRect – Raekye

+0

Ich habe es gerade versucht, und ich bekomme das gleiche Ergebnis. Wenn die Navigationsleiste zuerst kommt, ist die Spitze nervös. Wenn die Tableiste zuerst kommt (wie Sie sagen), ist der Boden immer noch nervös. Auch wenn ich den regulären View-Frame im Gegensatz zum affinen View-Frame NSBeimnehme (ich ändere nicht den Code), bekomme ich zuerst die gleichen Werte – Raekye

+0

, 'kAnimationDuration' sollte keine Rolle spielen, aber für meinen Code ist es hartcodiert .2'. Zweitens sollte die 'CGRectApplyAffineTransform' auch keine Rolle spielen, außer die view.transform ist etwas anderes als Identität. Schließlich bin ich neugierig, ob Ihre Ansicht Aufrufe von 'viewDidLayoutSubviews' enthält oder ob es eine Ansichtshierarchie gibt, die bewirkt, dass die äußere Ansicht bei ausgeblendetem Tab-Fenster skaliert wird, aber die innere Ansicht nicht gleichzeitig vergrößert wird . –

-1

Versuchen Sie einfach diesen Code, wenn es funktioniert. Ich habe diesen Code ein Jahr zuvor geschrieben. Aber es funktioniert immer noch gut für mich.

Ich habe die blockbasierten Animationen nicht verwendet. Weil es geschrieben wurde, als ich neu in iOS bin. Versuchen Sie einfach, sich selbst zu optimieren, wie Sie es wollten.

- (void) hideTabBar:(UITabBarController *) tabbarcontroller { 

    [self.navigationController setNavigationBarHidden:YES animated:YES]; 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.1]; 
    for(UIView *view in tabbarcontroller.view.subviews) 
    { 
     if ([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
      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)]; 
      }    
     }else if([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 
      if([view isKindOfClass:[UITabBar class]]) 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, 1024, view.frame.size.width, view.frame.size.height)]; 
      } 
      else 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 1024)]; 
      } 
     } 
    } 
    [UIView commitAnimations]; 
} 

// Method shows the bottom and top bars 

- (void) showTabBar:(UITabBarController *) tabbarcontroller { 

    [self.navigationController setNavigationBarHidden:NO animated:YES]; 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.1]; 
    for(UIView *view in tabbarcontroller.view.subviews) 
    { 
     if ([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
      if([view isKindOfClass:[UITabBar class]]) 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, 430, view.frame.size.width, view.frame.size.height)]; 
      } 
      else 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 436)]; 
      }    
     }else if([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 
      if([view isKindOfClass:[UITabBar class]]) 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, 975, view.frame.size.width, view.frame.size.height)]; 
      } 
      else 
      { 
       [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 980)]; 
      } 
     } 
    } 
    [UIView commitAnimations]; 
} 
+0

Leider funktioniert es bei mir nicht:/Trotzdem danke – Raekye