ios objective-c uiactionsheet uialertcontroller

ios - ¿Cómo cambiar el color de fondo del UIAlertController?



objective-c uiactionsheet (9)

Debido al extraño comportamiento de UIActionSheet en iOS 8, he implementado UIAlertController con UIAction como botones en él. Me gustaría cambiar todo el fondo de UIAlertController. Pero no puedo encontrar ninguna manera de hacerlo.

Probado incluso con,

actionController.view.backgroundColor = [UIColor blackColor];

Pero no me ayudó. Cualquier aportación a este respecto será apreciable.

Gracias por adelantado.


Swift3

Paso en una capa más comparar con swift2

let subview1 = alert.view.subviews.first! as UIView let subview2 = subview1.subviews.first! as UIView let view = subview2.subviews.first! as UIView subview.backgroundColor = backgroundColor view.backgroundColor = backgroundColor view.layer.cornerRadius = 10.0 // set color to UILabel font setSubviewLabelsToTextColor(textColor, view: view) // set font to alert via KVC, otherwise it''ll get overwritten let titleAttributed = NSMutableAttributedString( string: alert.title!, attributes: [NSFontAttributeName:UIFont.boldSystemFont(ofSize: 17)]) alert.setValue(titleAttributed, forKey: "attributedTitle") let messageAttributed = NSMutableAttributedString( string: alert.message!, attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 13)]) alert.setValue(messageAttributed, forKey: "attributedMessage") // set the buttons to non-blue, if we have buttons if let buttonColor = buttonColor { alert.view.tintColor = buttonColor }


Aquí hay una extensión de UIAlertController que funciona tanto en iPad como en iPhone. El botón Cancelar cambiará de un color oscuro a blanco automáticamente dependiendo de qué estilo de desenfoque esté seleccionado:

extension UIAlertController { private struct AssociatedKeys { static var blurStyleKey = "UIAlertController.blurStyleKey" } public var blurStyle: UIBlurEffectStyle { get { return objc_getAssociatedObject(self, &AssociatedKeys.blurStyleKey) as? UIBlurEffectStyle ?? .extraLight } set (style) { objc_setAssociatedObject(self, &AssociatedKeys.blurStyleKey, style, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) view.setNeedsLayout() view.layoutIfNeeded() } } public var cancelButtonColor: UIColor? { return blurStyle == .dark ? UIColor(red: 28.0/255.0, green: 28.0/255.0, blue: 28.0/255.0, alpha: 1.0) : nil } private var visualEffectView: UIVisualEffectView? { if let presentationController = presentationController, presentationController.responds(to: Selector(("popoverView"))), let view = presentationController.value(forKey: "popoverView") as? UIView // We''re on an iPad and visual effect view is in a different place. { return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first } return view.recursiveSubviews.flatMap({$0 as? UIVisualEffectView}).first } private var cancelActionView: UIView? { return view.recursiveSubviews.flatMap({ $0 as? UILabel} ).first(where: { $0.text == actions.first(where: { $0.style == .cancel })?.title })?.superview?.superview } public convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, blurStyle: UIBlurEffectStyle) { self.init(title: title, message: message, preferredStyle: preferredStyle) self.blurStyle = blurStyle } open override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() visualEffectView?.effect = UIBlurEffect(style: blurStyle) cancelActionView?.backgroundColor = cancelButtonColor } }

También se necesita la siguiente extensión UIView :

extension UIView { var recursiveSubviews: [UIView] { var subviews = self.subviews.flatMap({$0}) subviews.forEach { subviews.append(contentsOf: $0.recursiveSubviews) } return subviews } }

Ejemplo:

let controller = UIAlertController(title: "Dark Alert Controller", message: nil, preferredStyle: .actionSheet, blurStyle: .dark) // Setup controller actions etc... present(controller, animated: true, completion: nil)

iPhone:

iPad:


He encontrado una manera pirata de hacerlo. Primero necesita una extensión que le permita buscar UIVisualEffectView dentro del UIAlertController :

extension UIView { func searchVisualEffectsSubview() -> UIVisualEffectView? { if let visualEffectView = self as? UIVisualEffectView { return visualEffectView } else { for subview in subviews { if let found = subview.searchVisualEffectsSubview() { return found } } } return nil } }

Importante : presentViewController llamar a esta función después de llamar a presentViewController , porque solo después de cargar el controlador de vista, la vista de efectos visuales se inserta en su lugar. Luego puedes cambiar el efecto asociado a él a un efecto de desenfoque oscuro:

self.presentViewController(actionController, animated: true, completion: nil) if let visualEffectView = actionController.view.searchVisualEffectsSubview() { visualEffectView.effect = UIBlurEffect(style: .Dark) }

Y este es el resultado final:

Sinceramente, me sorprendo de lo bien que funciona. Creo que esto es probablemente algo que Apple olvidó agregar. Además, todavía no he aprobado una aplicación mediante la aprobación con este "hack" (no es un hack porque solo usamos APIs públicas), pero estoy seguro de que no habrá ningún problema.


Para el objetivo - El código C puede ser similar.

UIAlertController * alert=[UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert]; UIView *firstSubview = alert.view.subviews.firstObject; UIView *alertContentView = firstSubview.subviews.firstObject; for (UIView *subSubView in alertContentView.subviews) { subSubView.backgroundColor = [UIColor colorWithRed:255/255.0f green:255/255.0f blue:255/255.0f alpha:1.0f]; } UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){ //Close Action }]; [alert addAction:cancelAction]; [self presentViewController:alert animated:YES completion:nil];


Puedes usar el proxy de apariencia.

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

Esto parece aplicarse a todos, excepto a la acción de cancelación cuando se presenta como una hoja de acción.


Tienes que profundizar algunos puntos de vista:

let subview = actionController.view.subviews.first! as UIView let alertContentView = subview.subviews.first! as UIView alertContentView.backgroundColor = UIColor.blackColor()

Y tal vez quieras mantener el radio de la esquina original:

alertContentView.layer.cornerRadius = 5;

Lo siento por el "Swifting" pero no estoy familiarizado con Objective-C. Espero que sea similar.

Por supuesto, también es importante cambiar el color del título de las acciones. Lamentablemente no sé cómo configurar el color de las acciones por separado. Pero esto es, cómo cambia todos los colores de texto de los botones:

actionController.view.tintColor = UIColor.whiteColor();

EDITAR:

¡El radio de la esquina del UIAlertController ha cambiado desde que esta respuesta ha sido publicada! Reemplace esto:

alertContentView.layer.cornerRadius = 5;

a esto:

actionContentView.layer.cornerRadius = 15


para Swift 3 / Swift 4

let subview =(alert.view.subviews.first?.subviews.first?.subviews.first!)! as UIView subview.backgroundColor = UIColor(red: (145/255.0), green: (200/255.0), blue: (0/255.0), alpha: 1.0) alert.view.tintColor = UIColor.black

.


tal vez te guste el uso del efecto de desenfoque en el modo oscuro. Aquí hay una manera muy fácil de obtener esto:

UIVisualEffectView.appearance(whenContainedInInstancesOf: [UIAlertController.classForCoder() as! UIAppearanceContainer.Type]).effect = UIBlurEffect(style: .dark)


func Alert(View: ViewController, Title: String, TitleColor: UIColor, Message: String, MessageColor: UIColor, BackgroundColor: UIColor, BorderColor: UIColor, ButtonColor: UIColor) { let TitleString = NSAttributedString(string: Title, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : TitleColor]) let MessageString = NSAttributedString(string: Message, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(15), NSForegroundColorAttributeName : MessageColor]) let alertController = UIAlertController(title: Title, message: Message, preferredStyle: .Alert) alertController.setValue(TitleString, forKey: "attributedTitle") alertController.setValue(MessageString, forKey: "attributedMessage") let okAction = UIAlertAction(title: "OK", style: .Default) { (action) in } let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil) alertController.addAction(okAction) alertController.addAction(cancelAction) let subview = alertController.view.subviews.first! as UIView let alertContentView = subview.subviews.first! as UIView alertContentView.backgroundColor = BackgroundColor alertContentView.layer.cornerRadius = 10 alertContentView.alpha = 1 alertContentView.layer.borderWidth = 1 alertContentView.layer.borderColor = BorderColor.CGColor //alertContentView.tintColor = UIColor.whiteColor() alertController.view.tintColor = ButtonColor View.presentViewController(alertController, animated: true) { // ... } }