Я предполагаю, что вы хотите установить индикатор выполнения загрузки или что-то подобное, что отображается под панелью навигации и остается с вами независимо от того, к какому виду вы идете. Я только что реализовал это пару недель назад с дополнительным предостережением - мы используем IIViewDeck, чтобы мы могли обрабатывать изменения всего UINavigationController.
Что я сделал, так я добавил представление в качестве подсмотра навигационной панели. Моя панель навигации и контроллер навигации оба подкласса (и приложения были отправлены в App Store без инцидентов). Сначала я сделал это, потому что мне нужно было настроить навигационную панель без помощи UIAppearance
, но теперь это, кажется, подарок, который продолжает давать, поскольку это дает мне довольно гибкую задачу для таких задач.
- Создание пользовательских UINavigationController и UINavigationBar
- Если вам нужно обрабатывать штрихи, вам придется реализовать
hitTest:withEvent
- Я включил этот код ниже тоже.
- Если у вас есть приложение с изменениями
UINavigationController
(например, приложение панели вкладок или с боковым меню, которое позволяет вам изменить UINavigationController
, который находится в центре), я внедрил KVO для контроля контроллера центра, чтобы прогресс вид может «следовать» вокруг. Код также ниже.
Это, как я создал обычай 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/ –