iOS 8 UIActivityViewController和UIAlertController按钮文本颜色使用窗口的tintColor

32
在iOS 8中,似乎UIAlertController(特别是操作表类型)上的按钮以及UIActivityViewController上的按钮都从主窗口的tintColor获取它们的颜色。

我该如何更改按钮文本的颜色?我尝试使用外观代理像这样:

[[UIButton appearanceWhenContainedIn:[UIActivityViewController class], nil] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

但它没有效果。我的窗口的tintColor是白色,所以UIActivityViewController按钮上的文本也是白色,无法看到。更改窗口的tintColor可以解决此问题,但会破坏应用程序的其余部分。

请参见我的UIActivityViewController截图,其中包含白色取消按钮和底部的白色文本:

UIActivityViewController with white Cancel button text

相同的情况适用于UIActionSheet(是的,我知道它已被弃用)和具有actionSheet类型的UIAlertController。

如何在不更改整个应用程序的tintColor的情况下使这些窗口上的文本可读?谢谢!


为什么不直接将您的窗口色调从白色更改呢?我猜我对窗口色调了解得不够,不知道它能做什么。 - beebcon
6个回答

30

除了为您的应用程序定义全局色调颜色之外,每个视图控制器都允许您覆盖仅适用于该控制器的色调颜色。 在这种情况下,您最好在初始化后但在显示之前设置UIActivityViewController上的tintColor。

UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:activities];

//Set the tint color on just the activity controller as needed here before presenting
[activityController.view setTintColor:[UIColor blueColor]];

[self presentViewController:activityController animated:YES completion:nil];

如果您在应用程序中经常这样做,可以使用子类或类别来避免代码重复。


2
+1 & 谢谢 -- 我只是在这里添加一些神奇的关键词,可能会帮助其他遇到和我一样问题的人...我一直在搜索“不可见取消”、“空白取消”或“白色取消”。花了相当长时间才找到这个非常有用的问答。 - Michael Dautermann
当我尝试更改视图的tintColor时,UIActivityViewController中出现透明背景,这在iOS 7上效果不佳。 - Halpo

21

我在使用UIAlertController时,这个方法对我很有用。

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor blackColor]];

3
由于更改UIAlertController内每个视图的色彩,可能会产生意外的副作用。如果将来更改了视图层次结构,这肯定会导致错误。 - DiscDev
这个对我有用(iOS 8.4):[[UIView appearanceWhenContainedIn: [UIActivityViewController class], nil] setTintColor: [UIColor blackColor]]]; 这更好地针对了活动控制器。 - Leslie Godwin
6
这应该是被接受的答案,因为它实现了您想要做的事情:仅将某些视图控制器(例如警报控制器或活动控制器)的色调颜色设置为与主色调不同的颜色。如果在iOS 9中不起作用,则我们应该报告一个漏洞。这就是外观代理设计的目的所在。 - Cory Imdieke
1
因为在iOS 9中这种方法不起作用,所以这里提供了一种解决方案来设置UIAlertController按钮的tintColor: https://dev59.com/Yl8d5IYBdhLWcg3wxUjC#32636878 - peacetype
被接受的答案在iOS 9中运行良好 - 这个答案很脆弱/不可靠,而且似乎有许多意想不到的副作用,特别是因为它会给UIAlertController中包含的所有UIView着色。请自行决定是否使用此解决方案。 - DiscDev

4

iOS 11

        let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
        activityVC.popoverPresentationController?.sourceView = self.view

        //Set your activity view controller's appearance
        UIButton.appearance().tintColor = .blue

        //Set back to default UIButton appearance
        self.present(activityVC, animated: true, completion: {
            DispatchQueue.main.async {
                UIButton.appearance().tintColor = nil
            }
        })

这导致我应用中使用自定义色调的其他按钮出现了问题。 - kmell96
你应该设置颜色而不是空值。 - belebeich
并非所有的按钮都使用相同的色调颜色,因此我单独设置了每个按钮的色调颜色;您的代码是我设置 UIButton.appearance().tintColor 的唯一位置。我将所有的色调颜色设置从初始化器中移动到 viewWillAppear 中,然后您的解决方案就起作用了。超级 hacky 但有效。 - kmell96

2
在iOS 9中,我能通过对呈现UIActivityViewController的视图进行着色来解决这个问题。不幸的是,在iOS 10 / Xcode 8中,这个方法对我不再起作用。我试图给分享面板着色,以使取消按钮不再显示白色看不见的文本。
在iOS 10中,我发现唯一有效的方法是UIButton.appearance().tintColor = UIColor.red。您可以在应用程序委托中全局设置它(但是这也会影响到导航栏按钮等,所以您需要手动将它们着色为另一种颜色)。您还可以在视图中局部设置它,但是由于它实际上是应用于所有Button类型的全局主题,因此如果您不希望下一个视图选择它,则必须在之后将其设置回另一种颜色。
因此,我通过在初始化UIActivityViewController之后但在呈现它之前添加具有我的着色颜色的行来以“hackish”的方式将其作为着色方式仅适用于我的ActivityController按钮,并在ActivityController呈现函数的完成处理程序中将着色设置回我的首选颜色(白色)。
例如: // image to share let image = UIImage(named: "Image")
    // set up activity view controller
    let imageToShare = [ image! ]
    let activityViewController = UIActivityViewController(activityItems: imageToShare, applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view 
    UIButton.appearance().tintColor = UIColor.red

    // present the view controller
    self.present(activityViewController, animated: true, completion: {
        DispatchQueue.main.async {
            UIButton.appearance().tintColor = UIColor.white
        }
    })

1

对我有用 - 先备份当前的tint


//COLCSocialManager.showShareActivityViewController(fromVC: aViewController)
    class func showShareActivityViewController(fromVC vc: UIViewController){


        let textToShare = "TAXI. New iOS app for tourists and cabbies. Check it out its free."
        let linkToShare = "http://buff.ly/dddd"

        //on FB the link is converted
        let activityItems: [Any] = [ textToShare, linkToShare ]

        let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = vc.view // so that iPads won't crash

        // exclude some activity types from the list (optional)
        //activityViewController.excludedActivityTypes = [ UIActivityType.airDrop, UIActivityType.postToFacebook ]

        let buttonTintBackup = UIButton.appearance().tintColor

        UIButton.appearance().tintColor = UIColor.red

        // present the view controller
        vc.present(activityViewController, animated: true) {
            UIButton.appearance().tintColor = buttonTintBackup
        }

    }

仅在所有使用自定义色调颜色的按钮通过 UIButton.appearance() 设置色调,而不是视图本身的色调时才起作用。否则,备份该外观无法解决问题。 - kmell96

0
使用完成处理程序的优雅解决方案,适用于UIActivityController
    let barTintColor = UINavigationBar.appearance().barTintColor
    let bTintColour = UINavigationBar.appearance().tintColor

    UINavigationBar.appearance().barTintColor = UIColor.white
    UINavigationBar.appearance().tintColor = UIColor.darkGray

    activityViewController.completionWithItemsHandler = {(activityType: UIActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) in
        UINavigationBar.appearance().barTintColor = barTintColor
        UINavigationBar.appearance().tintColor =  bTintColour
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接