Невозможно установить цвет текста кнопок "Отправить" и "Отмена" в почтовом композиторе, если он представлен в UIActivityViewController в iOS7

Я использую UIActivityViewController для обмена элементами в iOS7. Когда я нажимаю кнопку "Почта", он выдает почтовый композитор, но кнопки "Отмена" и "Отправить" на панели навигации и самой панели навигации являются синими, что делает его очень трудным для чтения, поэтому я хочу изменить их цвет. Он работает в iOS6, но не в iOS7.

Я пробовал

[[UIBarButtonItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor], UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, nil] forState:UIControlStateNormal];

который работает в iOS6, и я попробовал

[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]];
[[UINavigationBar appearance] setBarTintColor:[UIColor redColor]];

который заставляет цвет мигать красным при первом запуске приложения, прежде чем сразу переключиться обратно на синий цвет.

Ответ 1

Удалось изменить цвет текста кнопок Отправить и Отмена, которые находятся на UINavigationBar в MFMailComposerViewController (оба Отправить и Отмена) и MFMessageComposeViewController (только Отмена), если они представлены из UIActivityViewController.

Используя UIActivityViewController, нажмите на Message или Mail:

Using an UIActivityViewController

Вы заметите, что цвет текста по умолчанию для кнопок Отправить и Отмена синий:

Default blue colors

Чтобы изменить это, в классе AppDelegate.m в методе didFinishLaunchingWithOptions вставьте следующую строку:

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTintColor:[UIColor whiteColor]];

Это приводит к:

Changed to white

Вы также можете использовать другие цвета, например:

[UIColor purpleColor];

Change to purple

[UIColor greenColor];

Changed to green

Как я это проверил? Я заметил, что это решение работает для следующего:

  • с Xcode 5.1 в iOS 7.1-симуляторе, создавая в качестве базового iOS SDK 7.1 (можно выбрать из выбора файла проекта → Настройки сборки → Базовый SDK. Также выбрано из Общего → Цель развертывания → 7.1)
  • с Xcode 5.1 на iPhone 4, создавая в качестве базового iOS SDK 7.0 (может быть выбран из выбора файла проекта → Настройки сборки → Базовый SDK. Также выбрано из Общего → Цель развертывания → 7.0)
  • с Xcode 5.1 на iPhone 4, создавая в качестве базового IOS SDK 7.1 (может быть выбран из выбора файла проекта → Настройки сборки → Базовый SDK. Также выбран из Общего → Цель развертывания → 7.1)

Это не сработало при тестировании с помощью

  • с Xcode 5.1 в симуляторе iOS 7.0, создавая в качестве базового iOS SDK 7.0 (может быть выбран из выбора файла проекта → Настройки сборки → Базовый SDK. Также выбран из Общего → Цель развертывания → 7.0)

Поэтому это должно быть безопасно использовать, поскольку я считаю, что поведение на самом устройстве больше, чем поведение в симуляторе iOS. Если кто-нибудь знает, почему он не работает в симуляторе iOS 7.0, я бы хотел знать.:)

Ответ 2

Цвет оттенка штриха и цвет строки состояния в UIActivityViewController. Решение Swift 3:

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
    }
}

Ответ 3

Вот что работает на iOS 7.1 на сегодняшний день.

Подкласс UIActivityViewController и переопределить следующий метод:

- (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();
        }
    }];
}

Это приведет к белым кнопкам и белой строке состояния.

Ответ 4

Для Swift:

self.navigationController?.presentViewController(activityViewController, animated: true, completion: { () in
   UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
   UINavigationBar.appearance().barTintColor = UIColor.whiteColor() // optional to change bar backgroundColor           
}

Это изменит цвет кнопки "Отправить" и "Отмена" на белый (проверено на iOS 7,8), но я до сих пор не могу сделать цвет текста в строке состояния белым (хотя я не пробовал решение подкласса UIActivityViewController для изменения текста строки состояния цвет)

Ответ 5

Это, похоже, ошибка с iOS 7. Я видел другие отчеты об этом в Интернете. Он также не исправляется в iOS 7.1.

Чтобы быть конкретным, независимо от того, что вы делаете, вы не можете устанавливать цвета оттенков на панели навигации для диалогов, показанных с помощью UIActivityViewController.

Ответ 6

У меня была та же проблема с моим приложением, где свойство tintColor UINavigationBar является белым везде благодаря прокси-серверу внешнего вида. В результате получилось, что UIBarButtonItem из контроллера просмотра композитора композитора не были видны (белые кнопки на белой панели навигации).

У меня есть этот вызов в моем методе application:didFinishLaunchingWithOptions::

[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];

Как невозможно (на данный момент?) получить доступ к UINavigationBar контроллера представления композитора почты в UIActivityViewController, я сделал следующее обходное решение, которое вдохновлено ответом 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: этот код предназначен для iOS 7, но вы можете использовать [[UIBarButtonItem appearance] setTintColor:] в iOS 6 (cf Kevin van Mierlo)

Ответ 7

Я исправил свою проблему путем подкласса UIActivityViewController, как это.   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
        }
    }

Ответ 8

Ну, есть причины, почему мы не можем изменить способ, которым пользовательский интерфейс в коде яблока является таким, каким он есть. В основном потому, что это яблоко. Они не позволяют редактировать способ отображения пользовательского интерфейса в MFMailComposerViewController. Если есть способ, то я понятия не имею, но я никогда не видел никакого способа сделать это. MFMailComposeViewController не поддерживает атрибут внешнего вида, поскольку он был создан в iOS 3.0, и внешний вид не стал чем-то, пока iOS 5.0

Вот ссылка на документацию Apple MFMailComposeViewController: MFMailComposeViewController

Надеюсь, это поможет!

Ответ 9

Если вы хотите установить цвет кнопок отмены и отправки в iOS 7, вы должны использовать это:

// Change the colours of the buttons in iOS 7
[[UINavigationBar appearance] setTintColor:[UIColor redColor]];

В iOS 6 это действительно так, и вы также должны оставить это в своем коде:

// 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]];

Ответ 10

Попробуйте этот код, возможно, это поможет вам

[[mailComposer navigationBar] setTintColor:[UIColor blackColor]];

Ответ 11

Я не смог заставить решение Alex работать, однако мне удалось получить вариацию ответа Paillou на работу, хотя мне пришлось установить в моей ситуации как barTintColor, так и titleTextAttributes:

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]];

Спасибо Paillou!

Ответ 12

Это сработало для меня: в AppDelegate.m в функции:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

Я ввел следующий код:

//mail composer
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBarTintColor:myBackgroundColor];
[[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setTintColor:myBarItemsColor];

Он отлично работает на iOS7 + iOS8, не пробовал более новые версии

Ответ 13

Вы можете настроить свой appearance перед представлением UIActivityViewController. Добавьте сброс внешнего вида в completionWithItemsHandler вашей activity VC:

setNavBarAppearance()

activityVC.completionWithItemsHandler = { [weak self] _, _, _, _ in
    self?.resetNavBarAppearance()
}

present(activityVC, animated: true, completion: nil)

Единственная проблема в том, что если активность похожа на отправку почты, то это полноэкранный режим. Ваш внешний вид не будет применен к текущим видимым представлениям. Немного взломать, чтобы решить это:

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)

Ответ 14

Для ios7 я думаю, что вы должны пройти этот код

[[UINavigationBar appearance] setTintColor:[UIColor redColor]];

Если он также не работает, попробуйте загрузить документацию Apple Mail Compose View Controller в Интернете.

Ответ 15

Перед представлением почтового композитора вставьте эту строку следующим образом:

[mailComposer.navigationBar setTintColor:[UIColor whiteColor]];
[self presentViewController:mailComposer animated:YES completion:nil];

Несмотря на то, что я установил стиль строки в приложении, завершил запуск, мне также нужно было установить его снова в блоке завершения следующим образом:

[self presentViewController:mailComposer animated:YES completion:^{[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];}];

Ответ 16

У меня были огромные проблемы с этим, особенно когда MFMailComposeViewController/MFMessageViewController сами отображаются UIActivityViewController.

Я применил метод swizzling на viewDidAppear/viewDidDisappear, чтобы отменить, а затем повторить настройку цветов и шрифтов моего приложения с помощью 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

(Должен признать, я не могу вспомнить, почему я нестандартно выглядел как в init, так и viewWillAppear, но я уверен, что была причина...).

Ответ 17

В Swift я сделал расширение для UIViewController:

extension UIViewController {

    func presentActivityViewController(viewControllerToPresent: UIViewController) {
        self.presentViewController(viewControllerToPresent, animated: true) { _ in
            UIBarButtonItem.appearance().tintColor = UIColor.whiteColor()
            UINavigationBar.appearance().barTintColor = Config.primaryColor
        }
    }
}

Когда мне нужно представить UIActivityViewController, я вызываю:

    let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: [])
    presentActivityViewController(activityViewController)

Ответ 18

В Swift, на iOS9, установите

UINavigationBar.appearance().barTintColor = UIColor.greenColor() // eg
UINavigationBar.appearance().translucent = false

перед представлением контроллера вида активности помогло.

Ответ 19

Я пробовал много разных методов в iOS 9 и 10, но это единственное, что сработало. Обратите внимание, что у меня есть фоновое изображение за навигационной панелью:

[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;

Ответ 20

Я не нашел механизм, который мне понравился, поэтому за то, что он стоит здесь, мой. Частично проблема заключается в том, что в более поздних версиях iOS добавлена возможность добавления в приложения общесистемных расширений для общего доступа и действий. Эти сторонние предметы, похоже, закодированы всевозможными способами. Некоторые наследуют стиль навигационной панели приложения, некоторые используют свой собственный, а некоторые, кажется, предполагают белую навигационную панель (но на самом деле наследуют от приложения).

Это проверено на iOS 12.2.

Я создаю UIActivityItemSource, к которому у меня есть:

- (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 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
}

Затем в моем UIActivityViewController completionWithItemsHandler я включаю:

[[UINavigationBar appearance] setBarTintColor:[UIColor kNavigationBarBackgroundColor]]; //Again, this is my app custom nav bar background color

Не имеет отношения к конкретной проблеме, но если у вас нет UIActivityItemSource вам нужно сделать что-то вроде этого:

NSArray *[email protected][self]; //And set self to be a UIActivityItemSource
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil];

Я уверен, что это не на 100% надежно, но работало со всеми расширениями, которые я пробовал.