2015-09-25 17 views
28

Sto provando a creare il foglio delle azioni come mostrato nell'app dei messaggi su iOS quando proviamo ad allegare un'immagine come nell'immagine.UIAlertController - aggiungi visualizzazioni personalizzate all'agenda

Ho realizzato in UIAlertController nuovo, non possiamo adattare alcuna vista personalizzata. Qualunque modo posso fare esattamente questo?

Il mio codice sembra piuttosto standard.

let alertController = UIAlertController(title: "My AlertController", message: "tryna show some images here man", preferredStyle: UIAlertControllerStyle.ActionSheet) 

     let okAction = UIAlertAction(title: "oks", style: .Default) { (action: UIAlertAction) -> Void in 
     alertController.dismissViewControllerAnimated(true, completion: nil) 
    } 
    let cancelAction = UIAlertAction(title: "Screw it!", style: .Cancel) { (action: UIAlertAction) -> Void in 
     alertController.dismissViewControllerAnimated(true, completion: nil) 
    } 

    alertController.addAction(okAction) 
    alertController.addAction(cancelAction) 

    self.presentViewController(alertController, animated: true, completion: nil) 

enter image description here

risposta

68

UIAlertController estende UIViewController, che ha una proprietà della vista. Puoi aggiungere sottoview a quella vista secondo il desiderio del tuo cuore. L'unico problema è dimensionare correttamente il controller degli avvisi. Potresti fare qualcosa di simile, ma questo potrebbe facilmente rompersi la volta successiva che Apple aggiusta il design di UIAlertController.

Swift 3

let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet) 

    let margin:CGFloat = 10.0 
    let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120) 
    let customView = UIView(frame: rect) 

    customView.backgroundColor = .green 
    alertController.view.addSubview(customView) 

    let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")}) 

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")}) 

    alertController.addAction(somethingAction) 
    alertController.addAction(cancelAction) 

    DispatchQueue.main.async { 
     self.present(alertController, animated: true, completion:{}) 
    } 

Swift

let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet) 

let margin:CGFloat = 10.0 
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120) 
let customView = UIView(frame: rect) 

customView.backgroundColor = .green 
alertController.view.addSubview(customView) 

let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")}) 

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")}) 

alertController.addAction(somethingAction) 
alertController.addAction(cancelAction) 

self.present(alertController, animated: true, completion:{}) 

Objective-C

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"\n\n\n\n\n\n" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; 

    CGFloat margin = 8.0F; 
    UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(margin, margin, alertController.view.bounds.size.width - margin * 4.0F, 100.0F)]; 
    customView.backgroundColor = [UIColor greenColor]; 
    [alertController.view addSubview:customView]; 

    UIAlertAction *somethingAction = [UIAlertAction actionWithTitle:@"Something" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {}]; 
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {}]; 
    [alertController addAction:somethingAction]; 
    [alertController addAction:cancelAction]; 
    [self presentViewController:alertController animated:YES completion:^{}]; 

Detto, molto meno approccio hacky sarebbe quello di rendere la propria sottoclasse vista che funziona in modo simile al layout UIAlertActionStyle di UIAlertController. Infatti, lo stesso codice appare leggermente diverso in iOS 8 e 9. IOS

IOS 8 enter image description here

IOS 9 enter image description here

IOS 10 enter image description here

+0

Quello è impressionante e molto disponibile ho ancora ottenere una linea dietro la vista verde a margine. Immagino che metterò una vista del contenitore attorno alla vista verde per quello. con 0 margini. – CalZone

+0

Grazie, amico. È stato fantastico Ho appena apportato una leggera regolazione alla larghezza della vista personalizzata ma tutto bene! Saluti. – Felipe

+0

Ciao a tutti Qualcuno può darmi un progetto di esempio per il primo screenshot ??? –

4

Per i più pigri, Swift 3.0 e iOS> = 9 sono ottimizzati n @ di risposta di Keller:

let alertController = UIAlertController(title: "\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet) 

let margin:CGFloat = 10.0 
let rect = CGRect(x: margin, y: margin, width: alertController.view.bounds.size.width - margin * 4.0, height: 120) 
let customView = UIView(frame: rect) 

customView.backgroundColor = .green 
alertController.view.addSubview(customView) 

let somethingAction = UIAlertAction(title: "Something", style: .default, handler: {(alert: UIAlertAction!) in print("something")}) 

let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert: UIAlertAction!) in print("cancel")}) 

alertController.addAction(somethingAction) 
alertController.addAction(cancelAction) 

self.present(alertController, animated: true, completion:{}) 
3

ho scritto un'estensione per UIAlertController (a Swift 4), che risolve i problemi di layout con layout automatico. C'è anche una stringa di messaggi di riserva nel caso in cui qualcosa non funzioni (a causa di cambiamenti futuri nel layout di UIAlertController).

import Foundation 

extension UIAlertController { 

    /// Creates a `UIAlertController` with a custom `UIView` instead the message text. 
    /// - Note: In case anything goes wrong during replacing the message string with the custom view, a fallback message will 
    /// be used as normal message string. 
    /// 
    /// - Parameters: 
    /// - title: The title text of the alert controller 
    /// - customView: A `UIView` which will be displayed in place of the message string. 
    /// - fallbackMessage: An optional fallback message string, which will be displayed in case something went wrong with inserting the custom view. 
    /// - preferredStyle: The preferred style of the `UIAlertController`. 
    convenience init(title: String?, customView: UIView, fallbackMessage: String?, preferredStyle: UIAlertControllerStyle) { 

     let marker = "__CUSTOM_CONTENT_MARKER__" 
     self.init(title: title, message: marker, preferredStyle: preferredStyle) 

     // Try to find the message label in the alert controller's view hierarchie 
     if let customContentPlaceholder = self.view.findLabel(withText: marker), 
      let customContainer = customContentPlaceholder.superview { 

      // The message label was found. Add the custom view over it and fix the autolayout... 
      customContainer.addSubview(customView) 

      customView.translatesAutoresizingMaskIntoConstraints = false 
      customContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[customView]-|", options: [], metrics: nil, views: ["customView": customView])) 
      customContainer.addConstraint(NSLayoutConstraint(item: customContentPlaceholder, 
                  attribute: .top, 
                  relatedBy: .equal, 
                  toItem: customView, 
                  attribute: .top, 
                  multiplier: 1, 
                  constant: 0)) 
      customContainer.addConstraint(NSLayoutConstraint(item: customContentPlaceholder, 
                  attribute: .height, 
                  relatedBy: .equal, 
                  toItem: customView, 
                  attribute: .height, 
                  multiplier: 1, 
                  constant: 0)) 
      customContentPlaceholder.text = "" 
     } else { // In case something fishy is going on, fall back to the standard behaviour and display a fallback message string 
      self.message = fallbackMessage 
     } 
    } 
} 

private extension UIView { 

    /// Searches a `UILabel` with the given text in the view's subviews hierarchy. 
    /// 
    /// - Parameter text: The label text to search 
    /// - Returns: A `UILabel` in the view's subview hierarchy, containing the searched text or `nil` if no `UILabel` was found. 
    func findLabel(withText text: String) -> UILabel? { 
     if let label = self as? UILabel, label.text == text { 
      return label 
     } 

     for subview in self.subviews { 
      if let found = subview.findLabel(withText: text) { 
       return found 
      } 
     } 

     return nil 
    } 
} 

Ed ecco un esempio di utilizzo:

// Create a custom view for testing... 
let customView = UIView() 
customView.translatesAutoresizingMaskIntoConstraints = false 
customView.backgroundColor = .red 

// Set the custom view to a fixed height. In a real world application, you could use autolayouted content for height constraints 
customView.addConstraint(NSLayoutConstraint(item: customView, 
              attribute: .height, 
              relatedBy: .equal, 
              toItem: nil, 
              attribute: .notAnAttribute, 
              multiplier: 1, 
              constant: 100)) 

// Create the alert and show it 
let alert = UIAlertController(title: "Alert Title", 
           customView: customView, 
           fallbackMessage: "This should be a red rectangle", 
           preferredStyle: .actionSheet) 

alert.addAction(UIAlertAction(title: "Yay!", style: .default, handler: nil)) 
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) 

self.present(alert, animated: true, completion: nil) 

che vi mostrerà qualcosa di simile: enter image description here

+0

Funziona bene. Mi chiedo solo se questo sarà respinto nel processo di revisione, qualche idea? – Knolraap

+2

Non sono coinvolte API private, quindi non saprei perché Apple dovrebbe rifiutarlo. – Zaggo

Problemi correlati