J'utilise UIActivityViewController pour partager des éléments dans iOS7. Lorsque je tape sur l'option Courrier, le compositeur de messages apparaît, mais les boutons Annuler et Envoyer de la barre de navigation et de la barre de navigation elle-même sont bleus, ce qui rend la lecture très difficile, je souhaite donc changer leur couleur. Cela fonctionne dans iOS6 mais pas dans iOS7.
J'ai essayé
[[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil] forState:UIControlStateNormal];
qui fonctionne dans iOS6, et j'ai essayé
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
ce qui fait que la couleur clignote en rouge la première fois que l'application est exécutée avant de revenir immédiatement à la couleur bleue.
Géré pour changer la couleur du texte des boutons Envoyer et Annuler, qui se trouvent sur les UINavigationBar
dans les MFMailComposerViewController
(les deux Envoyer et Annuler) et MFMessageComposeViewController
(uniquement Annuler), lorsqu'ils sont présentés à partir de UIActivityViewController
.
À l'aide d'un UIActivityViewController, appuyez sur Message
ou Mail
:
Vous remarquerez que la couleur de texte par défaut des boutons Envoyer et Annuler est bleue:
Pour changer cela, dans le AppDelegate.m
classe, dans la méthode didFinishLaunchingWithOptions
, insérez la ligne suivante:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:[UIColor whiteColor]];
Il en résulte:
Vous pouvez également utiliser d'autres couleurs, par exemple:
[UIColor purpleColor];
[UIColor greenColor];
Comment ai-je testé cela? J'ai remarqué que cette solution fonctionne pour les éléments suivants:
Cela n'a pas fonctionné lors des tests avec:
Par conséquent, il devrait être sûr à utiliser, car je pense que le comportement sur l'appareil réel importe plus que le comportement dans le simulateur iOS. Si quelqu'un sait pourquoi cela ne fonctionne pas dans le simulateur iOS 7.0, je voudrais savoir. :)
Couleur de teinte de la barre et couleur de la barre d'état dans UIActivityViewController. Swift 3 solution:
extension MFMailComposeViewController {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIApplication.shared.statusBarStyle = UIStatusBarStyle.lightContent
}
open override func viewDidLoad() {
super.viewDidLoad()
navigationBar.isTranslucent = false
navigationBar.isOpaque = false
navigationBar.barTintColor = UIColor.white
navigationBar.tintColor = UIColor.white
}
}
Voici ce qui fonctionne sur iOS 7.1 à partir d'aujourd'hui.
Sous-classe UIActivityViewController et remplacez la méthode suivante:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
viewControllerToPresent.view.tintColor = [UIColor whiteColor];
[super presentViewController:viewControllerToPresent animated:flag completion:^{
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
if (completion) {
completion();
}
}];
}
Cela rendra les boutons blancs et la barre d'état blanche.
Pour Swift:
self.navigationController?.presentViewController(activityViewController, animated: true, completion: { () in
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = UIColor.whiteColor() // optional to change bar backgroundColor
}
Cela changera Envoyer & Annuler la couleur du bouton en Blanc (testé sur iOS 7,8) mais je ne parviens toujours pas à rendre la couleur du texte de la barre d'état blanche (bien que je n'ai pas essayé cette solution de sous-classe UIActivityViewController
pour changer la couleur du texte de la barre d'état)
J'ai eu le même problème avec mon application où la propriété tintColor
de UINavigationBar
est partout blanche grâce au proxy d'apparence. L'effet résultant est que UIBarButtonItem
du courrier composer view controller navigationBar n'était pas visible (boutons blancs sur une barre de navigation blanche).
J'ai cet appel dans mon application:didFinishLaunchingWithOptions:
méthode:
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
Comme il est impossible (pour l'instant?) D'accéder au UINavigationBar
du mail composer contrôleur de vue dans le UIActivityViewController
, j'ai fait la solution de contournement suivante qui est inspirée de la réponse d'Alex:
UIColor *normalColor = [[UINavigationBar appearance] tintColor];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// back to normal color
[[UINavigationBar appearance] setTintColor:normalColor];
}];
[self presentViewController:activityViewController animated:YES completion:^{
// change color temporary
[[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:232.0f/255.0f green:51.0f/255.0f blue:72.0f/255.0f alpha:1.0f]];
}];
PS: ce code est destiné à iOS 7, mais vous pouvez utiliser [[UIBarButtonItem appearance] setTintColor:]
dans iOS 6 (cf. la réponse de Kevin van Mierlo)
Cela semble être un bug avec iOS 7. J'ai vu d'autres rapports à ce sujet en ligne. Il ne semble pas non plus être corrigé dans iOS 7.1.
Pour être précis, peu importe ce que vous faites, vous ne pouvez pas définir de couleurs de teinte dans les barres de navigation pour les boîtes de dialogue affichées à partir de UIActivityViewController.
J'ai résolu mon problème en sous-classant UIActivityViewController comme ceci. ViewWillAppear viewWilldisapper
extension UIActivityViewController {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UINavigationBar.appearance().barTintColor = .white
}
open override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.isOpaque = false
navigationController?.navigationBar.barTintColor = UIColor(red: (247/255), green: (247/255), blue: (247/255), alpha: 1)
//navigationBar.tintColor = UIColor.white
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
UINavigationBar.appearance().barTintColor = mycustomColor
}
}
Cela a fonctionné pour moi: dans AppDelegate.m dans la fonction:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
J'ai entré le code suivant:
//mail composer
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBarTintColor:myBackgroundColor];
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setTintColor:myBarItemsColor];
Cela fonctionne très bien sur iOS7 + iOS8, n'a pas essayé sur les versions plus récentes
Si vous souhaitez définir la couleur des boutons d'annulation et d'envoi dans iOS 7, vous devez utiliser ceci:
// Change the colours of the buttons in iOS 7
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];
Dans iOS 6, ce sont en effet ceux-ci et vous devez également laisser cela dans votre code:
// Change the colours of the buttons in iOS 6
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
// Change the color of the the navigation bar in iOS 6 and 7
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];
Eh bien, il y a des raisons pour lesquelles nous ne pouvons pas changer la façon dont l'interface utilisateur dans le code d'Apple est la même. Principalement parce que c'est Apple. Ils ne vous permettent pas de modifier l'apparence de l'interface utilisateur dans MFMailComposerViewController. S'il y a un moyen, alors je n'en ai aucune idée, mais je n'ai jamais vu de moyen de le faire. MFMailComposeViewController ne prend pas en charge l'attribut d'apparence tel qu'il a été créé dans iOS 3.0, et l'apparence n'est devenue rien avant iOS 5.0
Voici un lien vers le MFMailComposeViewController Apple: MFMailComposeViewController
J'espère que cela t'aides!
Essayez ce code car il vous aidera
[[mailComposer navigationBar] setTintColor:[UIColor blackColor]];
Je n'ai pas réussi à faire fonctionner la solution d'Alex, mais j'ai réussi à obtenir une variation de la réponse de Paillou au travail même si j'ai dû définir à la fois le barTintColor et le titleTextAttributes dans ma situation:
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
activityViewController.excludedActivityTypes = @[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAddToReadingList, UIActivityTypePostToVimeo, UIActivityTypePostToFlickr, UIActivityTypeAirDrop];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// back to normal color
[[UINavigationBar appearance] setBarTintColor:AAColorInputBorder];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"Avenir-Medium" size:18], NSFontAttributeName,
[UIColor whiteColor], NSForegroundColorAttributeName,
nil]];
}];
[self presentViewController:activityViewController animated:YES completion:^{
// change color temporary
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"Avenir-Medium" size:18], NSFontAttributeName,
AAColorInputBorder, NSForegroundColorAttributeName,
nil]];
Merci Paillou!
Vous pouvez définir votre appearance
avant de présenter UIActivityViewController
. Ajoutez la réinitialisation de l'apparence à completionWithItemsHandler
de votre activity VC
:
setNavBarAppearance()
activityVC.completionWithItemsHandler = { [weak self] _, _, _, _ in
self?.resetNavBarAppearance()
}
present(activityVC, animated: true, completion: nil)
Le seul problème, c'est que si l'activité est comme l'envoi de courrier, elle est en plein écran. Votre apparence ne sera pas appliquée aux vues visibles actuelles. Un peu de hacks pour le résoudre:
setNavBarAppearance()
activityVC.completionWithItemsHandler = { [weak self] _, _, _, _ in
self?.resetNavBarAppearance()
// Hacks(choose one of them):
// 1)
self?.navigationController?.isNavigationBarHidden = true
self?.navigationController?.isNavigationBarHidden = false
// 2)
let redrawTriggerVC = UIViewController()
redrawTriggerVC.modalPresentationStyle = .popover
self.present(redrawTriggerVC, animated: false, completion: nil)
redrawTriggerVC.dismiss(animated: false, completion: nil)
}
present(activityVC, animated: true, completion: nil)
J'ai essayé de nombreuses méthodes différentes dans iOS 9 et 10, mais c'est la seule qui a fonctionné. Notez que j'ai également une image d'arrière-plan derrière la barre de navigation:
[UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
NSDictionary *attribs = @{NSForegroundColorAttributeName:UIColor.whiteColor};
UINavigationBar.appearance.titleTextAttributes = attribs;
UINavigationBar.appearance.tintColor = UIColor.whiteColor;
[UINavigationBar.appearance setBackgroundImage:[UIImage imageNamed:@"IOSNavigationBar"] forBarMetrics:UIBarMetricsDefault];
UIBarButtonItem.appearance.tintColor = UIColor.whiteColor;
Je n'ai pas trouvé de mécanisme que j'aimais, alors pour ce que ça vaut, voici le mien. Une partie du problème est que les versions ultérieures d'iOS ajoutent la possibilité pour les applications d'ajouter des extensions de partage et d'action à l'échelle du système. Ces éléments tiers semblent être codés de toutes sortes de façons. Certains héritent du style de barre de navigation de l'application, certains utilisent le leur et certains semblent supposer une barre de navigation blanche (mais héritent en fait de l'application).
Ceci est testé sur iOS 12.2.
Je crée un UIActivityItemSource
, auquel j'ai:
- (nullable id)activityViewController:(nonnull UIActivityViewController *)activityViewController itemForActivityType:(nullable UIActivityType)activityType {
if (activityType == UIActivityTypePrint || [activityType.lowercaseString containsString:@"extension"] || [activityType containsString:@"AssignToContact"]) {
//What a hack, but the best I can do. Seems some extensions inherit nav style from parent, others don't.
//ActionExtension is bottom row; all those I tested need this. The string comparison catches most non-OS extensions (the type is set by developer).
[[UINavigationBar appearance] setBarTintColor:[UIColor kNavigationBarBackgroundColor]]; //kNavigationBarBackgroundColor is my app's custom nav bar background color
} else {
[[UINavigationBar appearance] setBarTintColor:[UIColor whiteColor]];
}
return self.pdfData; //In my case I'm sharing a PDF as NSData - modify as needed for your shared item
}
Puis dans mon UIActivityViewController
completionWithItemsHandler
j'inclus:
[[UINavigationBar appearance] setBarTintColor:[UIColor kNavigationBarBackgroundColor]]; //Again, this is my app's custom nav bar background color
Sans rapport avec le problème spécifique, mais si vous ne disposez pas actuellement d'un UIActivityItemSource
, vous devez faire quelque chose comme ceci:
NSArray *activities=@[self]; //And set self to be a UIActivityItemSource
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil];
Je suis sûr que ce n'est pas fiable à 100%, mais a fonctionné avec toutes les extensions que j'ai essayées.
Pour ios7, je pense que vous devriez passer par ce code
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];
Si cela ne fonctionne pas non plus, essayez Mail Compose View Controller Apple disponible sur Internet.
Dans Swift j'ai fait une extension pour UIViewController
:
extension UIViewController {
func presentActivityViewController(viewControllerToPresent: UIViewController) {
self.presentViewController(viewControllerToPresent, animated: true) { _ in
UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = Config.primaryColor
}
}
}
Lorsque je dois présenter un UIActivityViewController, j'appelle:
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: [])
presentActivityViewController(activityViewController)
J'ai eu d'énormes problèmes avec cela, surtout lorsque MFMailComposeViewController
/MFMessageViewController
sont eux-mêmes affichés par UIActivityViewController
.
J'ai recouru à l'utilisation de la méthode swizzling sur viewDidAppear
/viewDidDisappear
pour annuler puis refaire la personnalisation des couleurs et des polices de mon application, avec l'aide de https://github.com/rentzsch/jrswizzle :
SwizzledComposeViewControllers.h
#import <MessageUI/MessageUI.h>
@interface MFMailComposeViewController (GMSwizzling)
@end
@interface MFMessageComposeViewController (GMSwizzling)
@end
SwizzledComposeViewControllers.m
#import "SwizzledComposeViewControllers.h"
#import "AppDelegate.h"
#import "JRSwizzle.h"
@implementation MFMailComposeViewController (GMSwizzling)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self jr_swizzleMethod:@selector(init) withMethod:@selector(gmswizzled_init) error:nil];
[self jr_swizzleMethod:@selector(viewWillAppear:) withMethod:@selector(gmswizzled_viewWillAppear:) error:nil];
[self jr_swizzleMethod:@selector(viewWillDisappear:) withMethod:@selector(gmswizzled_viewWillDisappear:) error:nil];
});
}
- (instancetype)gmswizzled_init {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
return [self gmswizzled_init];
}
- (void)gmswizzled_viewWillAppear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
[self gmswizzled_viewWillAppear:animated];
}
- (void)gmswizzled_viewWillDisappear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate customiseAppearance];
[self gmswizzled_viewWillDisappear:animated];
}
@end
@implementation MFMessageComposeViewController (GMSwizzling)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self jr_swizzleMethod:@selector(init) withMethod:@selector(gmswizzled_init) error:nil];
[self jr_swizzleMethod:@selector(viewWillAppear:) withMethod:@selector(gmswizzled_viewWillAppear:) error:nil];
[self jr_swizzleMethod:@selector(viewWillDisappear:) withMethod:@selector(gmswizzled_viewWillDisappear:) error:nil];
});
}
- (instancetype)gmswizzled_init {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
return [self gmswizzled_init];
}
- (void)gmswizzled_viewWillAppear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate uncustomiseAppearance];
[self gmswizzled_viewWillAppear:animated];
}
- (void)gmswizzled_viewWillDisappear:(BOOL)animated {
[(AppDelegate*)UIApplication.sharedApplication.delegate customiseAppearance];
[self gmswizzled_viewWillDisappear:animated];
}
@end
(Je dois admettre que je ne me souviens pas pourquoi j'ai des apparences non personnalisées à la fois dans init
et viewWillAppear
, mais je suis assez sûr qu'il y avait une raison ...).
Dans Swift, le iOS9, réglage
UINavigationBar.appearance().barTintColor = UIColor.greenColor() // eg
UINavigationBar.appearance().translucent = false
avant de présenter le contrôleur de vue d'activité a fait l'affaire pour moi.
Avant de présenter le mail composer insérez cette ligne comme ceci:
[mailComposer.navigationBar setTintColor:[UIColor whiteColor]];
[self presentViewController:mailComposer animated:YES completion:nil];
Même si j'ai défini le style de la barre d'état dans l'application, j'ai terminé le lancement, je devais également le définir à nouveau dans le bloc d'achèvement comme ceci:
[self presentViewController:mailComposer animated:YES completion:^{[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];}];