Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

ios - UIAlertController change background color of Cancel button for action sheet

I am trying to create a UIAlertController with the action sheet style but I want to change the background color to a gray color. I have been able to find a way to change the background color of the UIAlertController, but not the Cancel button. The Cancel button, which is separate, remains white.

This is the code that I have right now:

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

And this gives me the following result: Link

I have visited How to change the background color of the UIAlertController? but none of the solutions have a custom color for the background of the Cancel button.

Any help would be appreciated!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There is a very very dirty solution but it works. We are going to use UIAppearance for this purpose.

First of all we need to prepare a special private extension for UIView to be able to change it's subviews background color.

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

Each time we set subiewsBackgroundColor value UIView will iterate it's subviews and set a new background color for each.

As you can see in the answer below there is a special UIView called _UIAlertControlleriOSActionSheetCancelBackgroundView in UIAlertController's hierarchy which contains a subview with white color (for the cancel button)

Let's try to get it's appearance and use our property to change it's subview color. I guess it's kind of a private api.

if let cancelBackgroundViewType = NSClassFromString("_UIAlertControlleriOSActionSheetCancelBackgroundView") as? UIView.Type {
    cancelBackgroundViewType.appearance().subviewsBackgroundColor = .red
}

Place this code in the AppDelegate's didFinishLaunching or a dedicated class. That's it. Now you can see the cancel button on a red background. Tested on iOS 11.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...