我猜你正在尋找一個上傳進度條或類似的東西,顯示在導航欄下方,並與你保持關係,無論你去哪個視圖。幾周前我剛剛實現了這個功能,並提出了額外的警告 - 我們使用IIViewDeck,因此我們必須能夠處理整個UINavigationController的更改。
我所做的是我添加的視圖導航欄的子視圖。我的導航欄和導航控制器都是分類的(並且應用程序已經無需事先提交到App Store)。起初,我這樣做是因爲我需要在沒有UIAppearance
的幫助下自定義導航欄,但現在它似乎是繼續給予的禮物,因爲它給了我相當多的靈活性來完成這樣的任務。
- 創建自定義的UINavigationController和UINavigationBar的
- 如果你需要處理的觸摸,你將不得不實行
hitTest:withEvent
- 以下附上太多的代碼。
- 如果你有改變
UINavigationController
視圖(如標籤欄的應用程序,或用側面菜單,讓你改變UINavigationController
這是在中心)的應用程序,我實現了志願監控中心視圖控制器,這樣的進展觀點可以'追隨'它周圍。代碼也在下面。
這是我如何創建一個自定義的UINavigationController和UINavigationBar的:
+ (ZNavigationController *)customizedNavigationController
{
//This is just a regular UINavigationBar subclass - doesn't have to have any code but I personally override the pop/push methods to call my own flavor of viewWill/Did/Appear/Disappear methods - iOS has always been a bit finicky about what gets called when
ZNavigationController *navController = [[ZNavigationController alloc] initWithNibName:nil bundle:nil];
// Ensure the UINavigationBar is created so that it can be archived. If we do not access the
// navigation bar then it will not be allocated, and thus, it will not be archived by the
// NSKeyedArchvier.
[navController navigationBar];
// Archive the navigation controller.
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:navController forKey:@"root"];
[archiver finishEncoding];
// Unarchive the navigation controller and ensure that our UINavigationBar subclass is used.
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[unarchiver setClass:[ZNavigationBar class] forClassName:@"UINavigationBar"];
ZNavigationController *customizedNavController = [unarchiver decodeObjectForKey:@"root"];
[unarchiver finishDecoding];
// Modify the navigation bar to have a background image.
ZNavigationBar *navBar = (ZNavigationBar *)[customizedNavController navigationBar];
[navBar setTintColor:kZodioColorBlue];
[navBar setBackgroundImage:[UIImage imageNamed:@"Home_TopBar_RoundCorner_withLogo"] forBarMetrics:UIBarMetricsDefault];
return customizedNavController;
}
現在,你有你自己的自定義ZNavigationBar
(這些都是從我的代碼的實際名稱 - 是一個痛苦的經歷和變化所有這些)你實現觸摸操作 - 變量名是相當自我解釋 - 我要檢測一個「左附件視圖」接觸,「主要區域」,或該進度條的「右附件視圖」:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
DDLogVerbose(@"Got a touch at point X: %f Y: %f", point.x, point.y);
//First check if the progress view is visible and touch is within that frame
if ([[JGUploadManager sharedManager] progressViewVisible] &&
CGRectContainsPoint([[JGUploadManager sharedManager] uploadProgressView].frame, point))
{
//Modified frame - have to compensate for actual position of buttons in the view from the standpoint of the UINavigationBar. Can probably use another/smarter method to do this.
CGRect modifiedCancelButtonFrame = [[JGUploadManager sharedManager] uploadProgressView].leftAccessoryFrame;
modifiedCancelButtonFrame.origin.y += [[JGUploadManager sharedManager] uploadProgressView].leftAccessoryView.superview.frame.origin.y;
//Do the same thing for the right view
CGRect modifiedRetryButtonFrame = [[JGUploadManager sharedManager] uploadProgressView].rightAccessoryFrame;
modifiedRetryButtonFrame.origin.y += [[JGUploadManager sharedManager] uploadProgressView].rightAccessoryView.superview.frame.origin.y;
//Touch is on the left button
if ([[JGUploadManager sharedManager] progressViewVisible] &&
[[JGUploadManager sharedManager] uploadProgressView].leftAccessoryView &&
CGRectContainsPoint(modifiedCancelButtonFrame, point))
{
return [[JGUploadManager sharedManager] uploadProgressView].leftAccessoryView;
}
//Touch is on the right button
else if ([[JGUploadManager sharedManager] progressViewVisible] &&
[[JGUploadManager sharedManager] uploadProgressView].rightAccessoryView &&
CGRectContainsPoint(modifiedRetryButtonFrame, point))
{
return [[JGUploadManager sharedManager] uploadProgressView].rightAccessoryView;
}
//Touch is in the main/center area
else
{
return [[JGUploadManager sharedManager] uploadProgressView];
}
}
//Touch is not in the progress view, pass to super
else
{
return [super hitTest:point withEvent:event];
}
}
現在,「跟隨」導航控制器的KVO部分。實行志願的地方 - 我用一個單「上傳管理器」類,我把它放在類的初始化,但是這取決於你的應用程序的設計:
ZRootViewController *rootViewController = ((JGAppDelegate*)[UIApplication sharedApplication].delegate).rootViewDeckController;
[rootViewController addObserver:sharedManager
forKeyPath:@"centerController"
options:NSKeyValueObservingOptionNew
context:nil];
然後,當然實現這一點:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
DDLogVerbose(@"KVO shows something changed: %@", keyPath);
if ([keyPath isEqualToString:@"centerController"])
{
DDLogVerbose(@"Center controller changed to: %@", object);
[self centerViewControllerChanged];
}
}
最後的centerViewControllerChanged
功能:
- (void)centerViewControllerChanged
{
ZRootViewController *rootViewController = ((JGAppDelegate*)[UIApplication sharedApplication].delegate).rootViewDeckController;
ZNavigationController *centerController = (ZNavigationController *)rootViewController.centerController;
//Check if the upload progress view is visible and/or active
if (self.uploadProgressView.frame.origin.y > 0 && self.uploadProgressView.activityIndicatorView.isAnimating)
{
[centerController.navigationBar addSubview:self.uploadProgressView];
}
//Keep weak pointer to center controller for other stuff
DDLogVerbose(@"Setting center view controller: %@", centerController);
self.centerViewController = centerController;
}
如果我誤解了你的問題,然後我剛鍵入的最長的SO回答世界,白白笑。我希望這有助於並讓我知道是否有任何部分需要澄清!
以下是更改導航欄的方法。您可能可以調整其大小並添加您的視圖。 http://sebastiancelis.com/2012/03/05/subclassing-hard-to-reach-classes/ – 2013-03-27 00:40:55