簡體   English   中英

UIAlertController 更改操作表的取消按鈕的背景顏色

[英]UIAlertController change background color of Cancel button for action sheet

我正在嘗試使用操作表樣式創建 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];

這給了我以下結果:鏈接

我已經訪問了如何更改 UIAlertController 的背景顏色? 但沒有一個解決方案具有用於取消按鈕背景的自定義顏色。

任何幫助將不勝感激!

有一個非常非常臟的解決方案,但它有效。 為此,我們將使用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 }
        }
    }
}

每次我們設置subiewsBackgroundColor值時,UIView 都會迭代它的子視圖並為每個子視圖設置一個新的背景顏色。

正如您在下面的答案中看到的,在 UIAlertController 的層次結構中有一個名為_UIAlertControlleriOSActionSheetCancelBackgroundView的特殊 UIView,它包含一個白色的子視圖(用於取消按鈕)

讓我們嘗試獲取它的外觀並使用我們的屬性來更改它的子視圖顏色。 我想這是一種私人api。

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

將此代碼放在 AppDelegate 的 didFinishLaunching 或專用類中。 就是這樣。 現在您可以看到紅色背景上的取消按鈕。 在 iOS 11 上測試。

您無法更改默認取消按鈕樣式的顏色。 您需要為取消按鈕創建自定義視圖控制器,並將其設置為取消警報操作的內容視圖控制器。 這種方式可以單獨保留取消按鈕

在此處輸入圖片說明

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)

在此處輸入圖片說明

如果你想要一個單獨的取消按鈕(UIAlertActionStyleCancel),你不能改變取消按鈕的背景顏色。 如果這是您的優先事項,那么您必須制作自己的自定義視圖。 或者,您可以簡單地添加標題為“取消”的默認操作。

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

(但它不會給你一個單獨的按鈕)。

我已經調試了視圖層次結構並找到了這個。 在此處輸入圖片說明

我在我的混合 Objective-C / Swift 項目中使用了mbryzinski答案,並且能夠像這樣從 Objective-C 修改取消按鈕的背景顏色:

((UIView *)[NSClassFromString(@"_UIAlertControlleriOSActionSheetCancelBackgroundView")
 appearance]).subviewsBackgroundColor = [UIColor yourBackgroundColor];

我將 UIView 擴展作為 .swift 文件包含在項目中,我不得不刪除fileprivate關鍵字:

extension UIView {
    private struct AssociatedKey {
        static var subviewsBackgroundColor = "subviewsBackgroundColor"
    }
    @objc dynamic var subviewsBackgroundColor: UIColor? {
    ...

此外,需要在使用擴展名的文件中導入橋接頭:

#import "{Your Project's name}-Swift.h"

修改 UIAlertController 的背景和文本顏色是實現深色主題的一種快速(而且老實說很臟)的方法。 圓角周圍有一些輕微的瑕疵,背景顏色越深,這些瑕疵越明顯。 尤其是在 iPad 上,偽影非常明顯。

正確的解決方案可能是使用自定義警報控制器。 (還沒有找到一個看起來最像股票的。)

我現在得到了解決方案。 我創建了示例項目並解決了您的問題,我明白了。

視圖控制器.h

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

視圖控制器.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    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 *subView = alert.view.subviews.lastObject; //firstObject
    UIView *alertContentView = subView.subviews.lastObject; //firstObject
    [alertContentView setBackgroundColor:[UIColor darkGrayColor]];
    alertContentView.layer.cornerRadius = 5;
    [self presentViewController:alert animated:YES completion:nil];
    alert.view.tintColor = [UIColor darkGrayColor];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

查看輸出

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM