2015-09-25 31 views
28

Tôi đang cố tạo bảng tác vụ như hiển thị trong ứng dụng tin nhắn trên iOS khi chúng tôi cố đính kèm hình ảnh như trong ảnh chụp màn hình.UIAlertController - thêm chế độ xem tùy chỉnh vào actionheet

Tôi đã nhận ra trong UIAlertController mới, chúng tôi không thể phù hợp với bất kỳ chế độ xem tùy chỉnh nào. Bất kỳ cách nào tôi có thể thực hiện chính xác điều này?

Mã của tôi trông khá chuẩn.

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

Trả lời

68

UIAlertController kéo dài UIViewController, trong đó có một thuộc tính view. Bạn có thể thêm các bản xem trước vào chế độ xem đó theo mong muốn của trái tim bạn. Vấn đề duy nhất là định kích thước bộ điều khiển cảnh báo đúng cách. Bạn có thể làm một cái gì đó như thế này, nhưng điều này có thể dễ dàng phá vỡ trong thời gian tới Apple điều chỉnh thiết kế của 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:^{}]; 

Điều đó đang được nói, một ít hơn nhiều cách tiếp cận hacky sẽ là làm cho lớp con xem của riêng bạn hoạt động tương tự như bố cục UIAlertActionStyle của UIAlertController. Trong thực tế, cùng mã trông hơi khác nhau trong iOS 8 và iOS 9.

iOS 8 enter image description here

iOS 9 enter image description here

iOS 10 enter image description here

+0

Thats tuyệt vời và thực sự hữu ích tôi vẫn nhận được một dòng đằng sau tầm nhìn xanh mát bên lề. Tôi đoán tôi sẽ đặt một cái nhìn container xung quanh xem màu xanh lá cây cho điều đó. với 0 lề. – CalZone

+0

Cảm ơn, bạn đời. Điều này thật tuyệt vời. Chỉ cần thực hiện điều chỉnh nhẹ để chiều rộng để xem tùy chỉnh nhưng tất cả đều tốt! Chúc mừng. – Felipe

+0

Xin chào tất cả Bất cứ ai có thể cho tôi dự án mẫu cho ảnh chụp màn hình đầu tiên ??? –

4

Đối với những người lười, Swift 3.0 và iOS> = 9 tối ưu hóa versio n của câu trả lời @ 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

Tôi đã viết phần mở rộng cho UIAlertController (trong Swift 4), giải quyết các vấn đề về bố cục với tính năng tự động hoàn thành. Thậm chí có một chuỗi thông báo dự phòng trong trường hợp một cái gì đó không hoạt động (do những thay đổi trong tương lai trong bố cục 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 
    } 
} 

Và đây là một ví dụ sử dụng:

// 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) 

nào sẽ hiển thị một cái gì đó như thế này: enter image description here

+0

Điều này hoạt động tốt. Chỉ cần tự hỏi nếu điều này sẽ bị từ chối trong quá trình xem xét, bất kỳ ý tưởng? – Knolraap

+2

Không có API riêng tư nào có liên quan, vì vậy tôi sẽ không biết tại sao Apple nên từ chối nó. – Zaggo

Các vấn đề liên quan