簡體   English   中英

當UIViewController推送時顯示UITabBar

[英]Show UITabBar when UIViewController pushed

這是我的情況:
我在UITabBarController有一個UINavigationController 當我向下鑽取導航控制器時,在某些時候我必須隱藏UITabBar因為我希望視圖具有盡可能多的空間。
我通過在推送的UIViewController使用self.hidesBottomBarWhenPushed = YES來做到這一點,並且它運行得很好。
但是,我想在以下推送的控制器中顯示UITabBar 我試圖在其他控制器中放置self.hidesBottomBarWhenPushed = NO ,但是UITabBar不會回來。

文檔說明似乎是正常的:

hidesBottomBarWhenPushed

If YES, the bar at the bottom of the screen is hidden; otherwise, NO. If YES, the bottom bar remains hidden until the view controller is popped from the stack.

實際上,當彈出具有此屬性設置為yes的控制器時,tabbar會返回。

一旦控制器被按下,是否有任何正確的方法來顯示UITabBar

提前致謝

不推薦使用hidesBottomBarWhenPushed。 我發現使用以下方法實現隱藏和顯示UITabBar非常簡單:

self.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
self.hidesBottomBarWhenPushed = NO;

因此,在推送detailViewConroller之后,您應該將hide屬性重置為NO。 這樣,當細節視圖彈出時,它將再次出現。 在viewWillApear / disapear等中無需任何其他更改。享受。

好的,我們還有很長的路要走。

當您從文檔中讀取時,默認行為是明確的:一旦視圖控制器的hides...屬性為YES,標簽欄將被隱藏,直到彈出視圖控制器。 你想要的是什么直接與此相矛盾,並且出於各種原因,我首先建議不要采用這種方法。

但是,這並不意味着無法實施。


  • 設置hides...屬性回到NO

您無法修改默認行為。 要顯示選項卡欄,堆棧中的所有視圖控制器必須將其hides...屬性設置為NO。 因此,從隱藏標簽欄的視圖中,如果要在按下新視圖時再次顯示該欄,則必須將先前視圖控制器的hides...屬性再次設置為NO

在推送新視圖控制器之前,將屬性設置回NO。

// ... prepare viewControllerToPush

self.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
[viewControllerToPush release];

通過這樣做,您將再次擁有標簽欄。 但是,您將識別從左側推入標簽欄,而從右側推入新視圖。 這顯然是不可取的,所以我們需要解決這個問題。


  • 覆蓋選項卡欄的圖層操作

問題是,標簽欄再次出現時使用的默認圖層操作(動畫)是左側的推送過渡動畫。 UITabBar實現- (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key方法,告訴我使用左邊的動畫作為案例。 我們需要覆蓋此方法,以便從右側返回動畫。

為了顯示標簽欄,Cocoa修改了它的圖層的position屬性。 因此,我們的新方法應該從右側為鍵position返回一個動畫,對於所有其他鍵,它應該使用默認實現。 請注意,Apple未記錄使用標簽欄的position ,因此在以下版本中如有更改,恕不另行通知。 無論如何,我們正在實施一些與蘋果規范直接相悖的東西,因此不能抱怨太多。

但是,您不能只使用子類來覆蓋該方法。 因為即使您有UITabBar的自定義子類,也無法修改UITabBarController類以使用它而不是默認的UITabBar。

所以,它變得有點復雜。 為了將自己的邏輯植入UITabBar類,您必須“交換”消息actionForLayer: forKey:

首先,使用category為UITabBar類添加一個新方法。

@interface UITabBar(customAction)
@end

@implementation UITabBar(customAction)

- (id < CAAction >)customActionForLayer:(CALayer *)layer forKey:(NSString *)key {
    if ([key isEqualToString:@"position"]) {
        CATransition *pushFromRight = [[CATransition alloc] init];
        pushFromRight.duration = 0.25; 
        pushFromRight.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 
        pushFromRight.type = kCATransitionPush; 
        pushFromRight.subtype = kCATransitionFromRight;
        return [pushFromRight autorelease];
    } 
return [self defaultActionForLayer:layer forKey:key];
}
@end

並在標簽欄控制器的viewDidAppear方法中,插入以下代碼。

Method original = class_getInstanceMethod([UITabBar class], @selector(actionForLayer:forKey:));
Method custom = class_getInstanceMethod([UITabBar class], @selector(customActionForLayer:forKey:));

class_replaceMethod([UITabBar class], @selector(actionForLayer:forKey:), method_getImplementation(custom), method_getTypeEncoding(custom));
class_addMethod([UITabBar class], @selector(defaultActionForLayer:forKey:), method_getImplementation(original), method_getTypeEncoding(original));

您希望在viewDidAppear而不是viewDidLoad執行此操作,否則標簽欄將在應用程序第一次顯示時從右側滑入。

現在,當UITabBar實例獲取消息actionsForLayer forKey: ,將調用自定義方法customActionForLayer forKey: . 它攔截關鍵position ,並從右側返回動畫。 如果它是另一個鍵,它會調用消息的原始實現,現在它連接到消息defaultActionsForLayer forKey: .


好的,我們有。 請記住,當彈出視圖時,您可能必須將hides...屬性設置回YES,因為在推送新視圖時將其設置為NO(並執行一些類似的技巧來正確設置動畫)。

我花了一些時間在這上面但具有諷刺意味的是,我不得不說*不要再使用它了,因為它使用了Cocoa類的未記錄信息(標簽欄動畫的“位置”鍵),與記錄的行為相矛盾,並且反對Apple的人機界面指南。 您可能會發現您的應用程序與以下SDK版本不同,用戶無法輕松采用該界面,甚至Apple拒絕您在App Store上的應用程序。

那我的答案到底是什么? 好吧,我猜想一個關於iOS開發的一些有趣話題的例子(以及證明我今天非常無效的證據:P)。

這是我在iOS 5中使用Storyboard時的方法:

在執行push segue之前,將hidesBottomBarWhenPushed屬性設置為NO

- (void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
   if( [segue.identifier isEqualToString:@"PushDetailView"] )
   {
      self.hidesBottomBarWhenPushed = NO;
   }

   [super prepareForSegue:segue sender:sender];
}

segue標識符顯然取決於您的名字。

當視圖控制器的視圖消失時立即將其設置回YES

- (void)viewWillDisappear:(BOOL)animated
{
   self.hidesBottomBarWhenPushed = YES;

   [super viewWillDisappear:animated];
}

就像魅力(在iOS 5.1上測試)一樣,使用UITabBar所有正確動畫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM