问题
When I push a CNContactViewController
on to the stack of UITableViewController
subclass which is within a UINavigationController
, the top navigation bar is almost entirely hidden. But with the brightness all the way up, you make out the back arrow followed by the word "Detail", and the system status bar. When I tap that corner of the screen, the CNContactViewController is indeed dismissed.
Of course this is not good, since a user would probably not even see the text of the navigation bar and now to press any buttons to dismiss.
Is there any way to make the navigation bar tint of the CNContactViewController be the same as the view controller that showed it (the rest of my app)?
CNContactViewController *controller = [CNContactViewController viewControllerForUnknownContact:person];
controller.contactStore = [[CNContactStore alloc] init];
controller.delegate = self;
controller.allowsActions = NO;
[self.navigationController pushViewController:controller animated:YES];
I should note that I'm only experiencing this problem on iOS 10, and not versions below 10. I also do get the properly tinted navigation bar when I tap "Add to Existing Contact", but it breaks again when that view controller is dismissed.
So again, my question is: Is there any way to make the navigation bar tint of the CNContactViewController be the same as the view controller that showed it (the rest of my app)?
回答1:
Your second screen shot shows the reason for this problem: you have set the tint color for your bar (or bar button items in general) to be white. Hence, they are white in front of the transparent navigation bar and white background in the contact view controller.
You can't do anything directly about the bar tint color, but you can solve this in either of two ways:
One is to make your navigation bar nontranslucent. In that case, the contact view controller's navigation bar will be black, and your white bar button items will be visible.
Another approach is to change your navigation bar's tint color (not the bar tint color, but the tint color that it communicates down to its bar button items) as the contact view controller pushes, and change it back when it pops.
EDIT Okay, I see that there's a further problem because the New Contact view controller is a further view controller presented in front of yours. If you refuse to give up your white bar button item setting, you will have to use the appearance proxy to set the UIBarButtonItem tint color to something else when your push the contact view controller, and then reset it back to your white when your navigation controller delegate tells you that the user is popping back to your view controller.
回答2:
I spent hours wrestling with CNContactViewController trying to force it to fit into my UINavigation appearance settings, but it just won't. It has it's own look and feel. I had a look at iOS apps like Mail and Notes to see how they show the CNContactViewController and it seems to be shown as a popover, so I went that way too.
Even that isn't trivial. The CNContactViewController has to be wrapped in a UINavigationView so that the Create New Contact and other views can push. And if you have overridden the UINavigationBar appearance defaults, you need to set them back to standard before and after. Here's how it looks in the end:
@property (strong, nonatomic) CNContactViewController *contactViewController;
@property (assign, nonatomic) UIBarStyle saveAppearanceBarStyle;
@property (strong, nonatomic) UIColor *saveAppearanceBarTintColor;
@property (strong, nonatomic) UIColor *saveAppearanceTintColor;
@property (strong, nonatomic) UIColor *saveAppearanceBackgroundColor;
@property (strong, nonatomic) NSDictionary<NSAttributedStringKey, id> * saveAppearanceTitleTextAttributes;
@property (assign, nonatomic) BOOL saveAppearanceTranslucent;
- (IBAction)onAddToContactsButtonTapped:(id)sender
self.contactViewController = [CNContactViewController viewControllerForUnknownContact: ... ]; // as before
[self suspendNavBarAppearanceSettings];
UINavigationController *popNav = [[UINavigationController alloc] initWithRootViewController:self.contactViewController];
popNav.modalPresentationStyle = UIModalPresentationPopover;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(onAddToContactsDoneTapped:)];
self.contactViewController.navigationItem.leftBarButtonItem = doneButton;
[self presentViewController:popNav animated:YES completion:nil];
UIPopoverPresentationController *popoverController = newNav.popoverPresentationController;
popoverController.permittedArrowDirections = UIPopoverArrowDirectionAny;
popoverController.sourceRect = ...; // where you want it to point
popoverController.sourceView = ...; // where you want it to point
popoverController.delegate = self;
}
- (void) suspendNavBarAppearanceSettings
{
self.saveAppearanceBarStyle = [UINavigationBar appearance].barStyle;
self.saveAppearanceBarTintColor = [UINavigationBar appearance].barTintColor;
self.saveAppearanceTintColor = [UINavigationBar appearance].tintColor;
self.saveAppearanceBackgroundColor = [UINavigationBar appearance].backgroundColor;
self.saveAppearanceTitleTextAttributes = [UINavigationBar appearance].titleTextAttributes;
self.saveAppearanceTranslucent = [UINavigationBar appearance].translucent;
[UINavigationBar appearance].barStyle = UIBarStyleDefault;
[UINavigationBar appearance].barTintColor = nil;
[UINavigationBar appearance].tintColor = nil;
[UINavigationBar appearance].backgroundColor = nil;
[UINavigationBar appearance].titleTextAttributes = nil;
[UINavigationBar appearance].translucent = YES;
}
- (void) restoreNavBarAppearanceSettings
{
[UINavigationBar appearance].barStyle = self.saveAppearanceBarStyle;
[UINavigationBar appearance].barTintColor = self.saveAppearanceBarTintColor;
[UINavigationBar appearance].tintColor = self.saveAppearanceTintColor;
[UINavigationBar appearance].backgroundColor = self.saveAppearanceBackgroundColor;
[UINavigationBar appearance].titleTextAttributes = self.saveAppearanceTitleTextAttributes;
[UINavigationBar appearance].translucent = self.saveAppearanceTranslucent;
}
- (void)onAddToContactsDoneTapped:(id)sender
{
[self restoreNavBarAppearanceSettings];
[[self presentedViewController] dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - CNContactViewControllerDelegate
- (void)contactViewController:(CNContactViewController *)viewController
didCompleteWithContact:(nullable CNContact *)contact
{
[self restoreNavBarAppearanceSettings];
[[self presentedViewController] dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - UIPopoverPresentationControllerDelegate
- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
{
// This method is only called if we are presented in a popover, i.e. on iPad
// as opposed to full screen like on a phone.
// on iPad you just tap outside to finish, so remove the Done button
self.contactViewController.navigationItem.leftBarButtonItem = nil;
}
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
[self restoreNavBarAppearanceSettings];
}
来源:https://stackoverflow.com/questions/40600559/cncontactviewcontroller-hiding-navigation-bar