Change navigation button color in MFMailComposerVi

2019-02-08 03:48发布

I'm trying to change the text color for navigation buttons in a MFMailComposerViewController but it doesn't work like on iOS 6. In iOS 6 it worked with UIAppearance like this:

// Navigation button
UIBarButtonItem *barButton = [UIBarButtonItem appearance];
NSDictionary *barButtonTitleTextAttributes = @{UITextAttributeTextColor: [UIColor redColor]};
NSDictionary *disabledBarButtonTitleTextAttributes = @{UITextAttributeTextColor: [UIColor grayColor]};

[barButton setTitleTextAttributes:barButtonTitleTextAttributes forState:UIControlStateNormal];
[barButton setTitleTextAttributes:disabledBarButtonTitleTextAttributes forState:UIControlStateDisabled];
[barButton setBackgroundImage:[[UIImage imageNamed:@"btn_appearance"] stretchableImageWithLeftCapWidth:6 topCapHeight:0] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

But this doesn't work on iOS 7 and looks always like this: enter image description here

I also tried to set the tintColor attribute on the navigationBar but this has no effect either:

navigationBar.tintColor = [UIColor redColor];

Is there anyway to change the navigation button text color in a MFMailComposeViewController on iOS 7?

6条回答
戒情不戒烟
2楼-- · 2019-02-08 03:48

As has been pointed out a few times, setting the tint on the MFMailComposeViewController navigation bar does not work. If you have other appearance changes set for the whole app, the tint colour is only one aspect of the issue, in our app we have changed the bar colour and UIBarButton text size so in the MFMailComposeViewController we see this: Navigation bar style in MFMailComposeViewController

The appearance in our app is set in a StyleGuide class with a function configureAppearanceModifiers called from the AppDelegate.

Taking the example from @timosdk I have added a second method:

- (void)neutraliseAppearanceModifiers {

    [[UINavigationBar appearance] setTranslucent:NO];
    [[UINavigationBar appearance] setTintColor:nil];
    [[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
    [[UINavigationBar appearance] setBackIndicatorImage:nil];
    [[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:nil];
    [[UINavigationBar appearance] setBackgroundImage:nil
                                  forBarPosition:UIBarPositionAny
                                      barMetrics:UIBarMetricsDefault];
    [[UIBarButtonItem appearance] setTitleTextAttributes:nil forState:UIControlStateNormal];
    [[UIBarButtonItem appearance] setTitleTextAttributes:nil forState:UIControlStateHighlighted];
    [[UIBarButtonItem appearance] setTitleTextAttributes:nil forState:UIControlStateDisabled];
    [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:nil forState:UIControlStateNormal];
    [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:nil forState:UIControlStateHighlighted];
    [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:nil forState:UIControlStateDisabled];

}

I call this before initialising the MFMailComposeViewController and then call configureAppearanceModifiers again in the didFinishWithResult delegate before dismissing the ViewController, this works perfectly.

查看更多
放荡不羁爱自由
3楼-- · 2019-02-08 03:49

If you ever inspect the view hierarchy created by showing a MFMailComposeViewController you'll see that it's contained within an instance of _UITextEffectsRemoteView. You have zero programmatic access to any subviews of that, which I'm guessing is because they're probably owned by a separate process. Those subviews will inherit anything set on the various UIAppearance proxies (e.g., bar background, titleTextAttributes, etc) but nothing more.

The UIAppearance protocol does not mention this in the documentation, but it does have this in the comments of the header file:

Note for iOS7: On iOS7 the tintColor property has moved to UIView, and now has special inherited behavior described in UIView.h.
This inherited behavior can conflict with the appearance proxy, and therefore tintColor is now disallowed with the appearance proxy.

So the end result is that while you can control most aspects of the appearance of MFMailComposeViewController you will always get the system default blue tint color.

Bug report: http://openradar.appspot.com/radar?id=6166546539872256

查看更多
Root(大扎)
4楼-- · 2019-02-08 03:53

Like OemerA says - there is no way to change the colors. My problem was that in UIAppearance I set the background color of the bar to blue so then the "buttons" are no longer visible. Since the email is actually not part of your app it makes more sense to reset the nag bar appearance prior to creating the mail composer. This is how I do it:

// set to normal white
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor blackColor], NSForegroundColorAttributeName, nil]];

MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];

// set to back to blue with white text
[[UINavigationBar appearance] setBarTintColor:[UIColor blueColor]];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, nil]];
查看更多
在下西门庆
5楼-- · 2019-02-08 03:53

Swift 3.0

func sendEmail() {
    if MFMailComposeViewController.canSendMail() {
        let mail = MFMailComposeViewController()
        mail.navigationBar.tintColor = UIColor.red
        mail.mailComposeDelegate = self
        mail.setToRecipients(["abc@abc.com"])
        mail.setMessageBody("<p>You're so awesome!</p>", isHTML: true)

        present(mail, animated: true)
    } else {
        // show failure alert
    }
}

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    controller.dismiss(animated: true)
}
查看更多
等我变得足够好
6楼-- · 2019-02-08 04:10

If you set the tintColor on UIWindow it works perfectly fine, the first time presenting the MFMailComposerViewController. It seems like it loses the tintColor information for the subsequent calls.

Note: this changes the tint of every element of your window.

查看更多
▲ chillily
7楼-- · 2019-02-08 04:14

I used this and works perfect in iOS7+

MFMailComposeViewController* mailViewController = [[MFMailComposeViewController alloc] init];        
mailViewController.mailComposeDelegate = self;
[mailViewController setToRecipients:@[@"email@apple.com"]];

[mailViewController.navigationBar setTintColor:[UIColor orangeColor]];

[self presentViewController:mailViewController animated:YES completion:nil]; 
查看更多
登录 后发表回答