UIAlertController更改操作表的"取消"按钮的背景颜色

Pib*_*omb 1 objective-c ios uialertcontroller

我正在尝试使用动作表样式创建UIAlertController,但我想将背景颜色更改为灰色.我已经能够找到一种方法来改变UIAlertController的背景颜色,但不能找到取消按钮."取消"按钮是独立的,保持白色.

这是我现在的代码:

UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];

[alert addAction:[UIAlertAction actionWithTitle:@"Option 1" style:UIAlertActionStyleDefault handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:@"Option 2" style:UIAlertActionStyleDefault handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:@"Option 3" style:UIAlertActionStyleDefault handler:nil]];
[alert addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:nil]];

[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];

UIView *firstSubview = alert.view.subviews.firstObject;
UIView *alertContentView = firstSubview.subviews.firstObject;

for (UIView *subSubView in alertContentView.subviews) {
    subSubView.backgroundColor = [UIColor darkGrayColor]; // Here you change background
}

alert.view.tintColor = [UIColor whiteColor];

[self.controller presentViewController:alert animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

这给了我以下结果: 链接

我已经访问过如何更改UIAlertController的背景颜色? 但是没有一个解决方案具有"取消"按钮背景的自定义颜色.

任何帮助,将不胜感激!

Sou*_*men 6

如果您需要单独的取消按钮(UIAlertActionStyleCancel),则无法更改取消按钮的背景颜色.如果这是您的首要任务,那么您必须制作自己的自定义视图.或者,您只需添加标题为"取消"的默认操作即可.

[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil]]

(但它不会给你一个单独的按钮).

我调试了视图层次结构并找到了这个. 在此输入图像描述


小智 6

有一个非常非常肮脏的解决方案,但是它可以工作。我们将为此目的使用UIAppearance

首先,我们需要为UIView准备一个特殊的私有扩展,以便能够更改其子视图的背景颜色。

fileprivate extension UIView {
    private struct AssociatedKey {
        static var subviewsBackgroundColor = "subviewsBackgroundColor"
    }

    @objc dynamic var subviewsBackgroundColor: UIColor? {
        get { 
          return objc_getAssociatedObject(self, &AssociatedKey.subviewsBackgroundColor) as? UIColor 
        }

        set {
          objc_setAssociatedObject(self,
                                   &AssociatedKey.subviewsBackgroundColor,
                                   newValue,
                                   .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
          subviews.forEach { $0.backgroundColor = newValue }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每次我们设置subiewsBackgroundColor值时,UIView都会迭代其子视图并为每个子视图设置新的背景色。

正如您在下面的答案中看到的那样,UIAlertController的层次结构中有一个名为_UIAlertControlleriOSActionSheetCancelBackgroundView的特殊UIView ,其中包含带有白色的子视图(用于“取消”按钮)

让我们尝试获得它的外观,并使用我们的属性更改其子视图颜色。我猜这有点像私人API。

if let cancelBackgroundViewType = NSClassFromString("_UIAlertControlleriOSActionSheetCancelBackgroundView") as? UIView.Type {
    cancelBackgroundViewType.appearance().subviewsBackgroundColor = .red
}
Run Code Online (Sandbox Code Playgroud)

将此代码放在AppDelegate的didFinishLaunching或专用类中。而已。现在,您可以在红色背景上看到“取消”按钮。在iOS 11上测试。


小智 5

您不能更改默认取消样式按钮的颜色。您需要为“取消”按钮创建一个自定义视图控制器,并将其设置为“取消警报”操作的内容视图控制器。这种方式使取消按钮分开保持

在此处输入图片说明

let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

alertController.addAction(UIAlertAction(title: "Option 1", style: .default, handler: nil))
alertController.addAction(UIAlertAction(title: "Option 2", style: .default, handler: nil))
alertController.addAction(UIAlertAction(title: "Option 3", style: .default, handler: nil))

alertController.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: nil))

if let firstSubview = alertController.view.subviews.first, let alertContentView = firstSubview.subviews.first {
    for view in alertContentView.subviews {
        view.backgroundColor = .darkGray
    }
}

alertController.view.tintColor = .white

let cancelButtonViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CancelButtonViewController")
let cancelAction = UIAlertAction(title: "", style: .cancel, handler: nil)
cancelAction.setValue(cancelButtonViewController, forKey: "contentViewController")

alertController.addAction(cancelAction)

present(alertController, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 控制器约束被打破。如果您有10个以上的项目,则“取消”按钮与最后一个项目重叠 (2认同)