How to use UITextView in UIAlertController

空扰寡人 提交于 2019-11-27 22:20:31

问题


I created a popup alert using alert controller and added two alert actions(ok and cancel) as below.

UIAlertController * alert=   [UIAlertController
                              alertControllerWithTitle:@"Cycling"
                              message:@"Please enter title and description"
                              preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* ok = [UIAlertAction
                     actionWithTitle:@"OK"
                     style:UIAlertActionStyleDefault
                     handler:^(UIAlertAction * action)
                     {
                         [alert dismissViewControllerAnimated:YES completion:nil];

                     }];
UIAlertAction* cancel = [UIAlertAction
                         actionWithTitle:@"Cancel"
                         style:UIAlertActionStyleDefault
                         handler:^(UIAlertAction * action)
                         {
                             [alert dismissViewControllerAnimated:YES completion:nil];

                         }];

[alert addAction:ok];
[alert addAction:cancel];

[self presentViewController:alert animated:YES completion:nil];

Now, i want add UITextView. Because I have two text field like title and description. For description i want to use UITextView for adding no.of lines. I tried i am not getting how to add it.

Please advice.


回答1:


Adding UITextView to UIAlertController:

https://gist.github.com/bennagar/c0cd618bcd23c4c2dadf

func showAlert() {

    let saveAction = UIAlertAction(title: "OK", style: .Default, handler: nil)

    saveAction.enabled = false

    let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)

    alertController.view.addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions.New, context: nil)

    NSNotificationCenter.defaultCenter().addObserverForName(UITextViewTextDidChangeNotification, object: textView, queue: NSOperationQueue.mainQueue()) { (notification) in
        saveAction.enabled = self.textView.text != ""
    }

    textView.backgroundColor = UIColor.greenColor()
    alertController.view.addSubview(self.textView)

    alertController.addAction(saveAction)
    alertController.addAction(cancelAction)

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

}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == "bounds"{
        if let rect = (change?[NSKeyValueChangeNewKey] as? NSValue)?.CGRectValue(){
            let margin:CGFloat = 8.0
            textView.frame = CGRectMake(rect.origin.x + margin, rect.origin.y + margin, CGRectGetWidth(rect) - 2*margin, CGRectGetHeight(rect) / 2)
            textView.bounds = CGRectMake(rect.origin.x + margin, rect.origin.y + margin, CGRectGetWidth(rect) - 2*margin, CGRectGetHeight(rect) / 2)
        }
    }
}

<script src="https://gist.github.com/bennagar/c0cd618bcd23c4c2dadf.js"></script>

Still locking for way to get the height of the marked view, when I have it I can just replace the /2 with the correct height.




回答2:


With the above solutions my textview was not positioned correctly. This is how I got it to work:

   // The \n is required so that the alertcontroller keeps space for the message. Add as many \n as you like your textview height to be
   self.alertController = [UIAlertController alertControllerWithTitle:@"Some title"
                                                              message:@"\n\n\n\n\n\n\n\n"
                                                        preferredStyle:UIAlertControllerStyleAlert];

   self.alertController.view.autoresizesSubviews = YES;
   UITextView *textView = [[UITextView alloc] initWithFrame:CGRectZero];
   textView.translatesAutoresizingMaskIntoConstraints = NO;
   textView.editable = NO;
   textView.dataDetectorTypes = UIDataDetectorTypeAll;
   textView.text = @"Some really long text here";
   textView.userInteractionEnabled = YES;
   textView.backgroundColor = [UIColor clearColor];
   // This will make the scroll view scrollable if the text is too long
   textView.scrollEnabled = YES;
   NSLayoutConstraint *leadConstraint = [NSLayoutConstraint constraintWithItem:self.alertController.view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:textView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:-8.0];
       NSLayoutConstraint *trailConstraint = [NSLayoutConstraint constraintWithItem:self.alertController.view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:textView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:8.0];

   NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.alertController.view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:textView attribute:NSLayoutAttributeTop multiplier:1.0 constant:-64.0];
   NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.alertController.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:textView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:64.0];
   [self.retailerHelpAlertController.view addSubview:textView];
   [NSLayoutConstraint activateConstraints:@[leadConstraint, trailConstraint, topConstraint, bottomConstraint]];



回答3:


Fantastic solutions above. Some needed some manipulation to work for Swift 4.2, here is the conversion for that. I've also added some padding in the TextView to make it athletically more pleasing.

let textView = UITextView(frame: CGRect.zero)

@IBAction func alert(_ sender: Any) {

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

    textView.textContainerInset = UIEdgeInsets.init(top: 8, left: 5, bottom: 8, right: 5)

    let saveAction = UIAlertAction(title: "OK", style: .default) { (action) in
        self.label.text = self.textView.text
        alertController.view.removeObserver(self, forKeyPath: "bounds")
    }

    saveAction.isEnabled = false

    let cancelAction = UIAlertAction.init(title: "Cancel", style: .default) { (action) in
        alertController.view.removeObserver(self, forKeyPath: "bounds")
    }

    alertController.view.addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions.new, context: nil)

    NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: textView, queue: OperationQueue.main) { (notification) in
        saveAction.isEnabled = self.textView.text != ""
    }

    textView.backgroundColor = UIColor.white
    alertController.view.addSubview(self.textView)

    alertController.addAction(saveAction)
    alertController.addAction(cancelAction)

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


}


override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "bounds"{
        if let rect = (change?[NSKeyValueChangeKey.newKey] as? NSValue)?.cgRectValue {
            let margin:CGFloat = 8.0
            textView.frame = CGRect.init(x: rect.origin.x + margin, y: rect.origin.y + margin, width: rect.width - 2*margin, height: rect.height / 2)
            textView.bounds = CGRect.init(x: rect.origin.x + margin, y: rect.origin.y + margin, width: rect.width - 2*margin, height: rect.height / 2)
        }
    }
}



回答4:


Swift 3

 let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
 let textView = UITextView()
 textView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

 let controller = UIViewController()

 textView.frame = controller.view.frame
 controller.view.addSubview(textView)

 alert.setValue(controller, forKey: "contentViewController")

 let height: NSLayoutConstraint = NSLayoutConstraint(item: alert.view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: view.frame.height * 0.8)
 alert.view.addConstraint(height)

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



回答5:


Johno2110's solution worked best for me with a little cleanup and tweaking. Posting the code and a screenshot of the result here in case it helps anybody else out.

Confirmed working with Swift 5.

let textView = UITextView(frame: CGRect.zero)

@IBAction func sendFeedback(_ sender: Any) {
    let alertController = UIAlertController(title: "Feedback \n\n\n\n\n", message: nil, preferredStyle: .alert)

    let cancelAction = UIAlertAction.init(title: "Cancel", style: .default) { (action) in
        alertController.view.removeObserver(self, forKeyPath: "bounds")
    }
    alertController.addAction(cancelAction)

    let saveAction = UIAlertAction(title: "Submit", style: .default) { (action) in
        let enteredText = self.textView.text
        alertController.view.removeObserver(self, forKeyPath: "bounds")
    }
    alertController.addAction(saveAction)

    alertController.view.addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions.new, context: nil)
    textView.backgroundColor = UIColor.white
    textView.textContainerInset = UIEdgeInsets.init(top: 8, left: 5, bottom: 8, right: 5)
    alertController.view.addSubview(self.textView)

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

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "bounds"{
        if let rect = (change?[NSKeyValueChangeKey.newKey] as? NSValue)?.cgRectValue {
            let margin: CGFloat = 8
            let xPos = rect.origin.x + margin
            let yPos = rect.origin.y + 54
            let width = rect.width - 2 * margin
            let height: CGFloat = 90

            textView.frame = CGRect.init(x: xPos, y: yPos, width: width, height: height)
        }
    }
}




回答6:


Try this code I got from here: http://useyourloaf.com/blog/2014/09/05/uialertcontroller-changes-in-ios-8.html

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title", message:@"Message", preferredStyle:UIAlertControllerStyleAlert];

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
    textField.placeholder = NSLocalizedString(@"LoginPlaceholder", @"Login"); 
}];

Then show it.



来源:https://stackoverflow.com/questions/28603060/how-to-use-uitextview-in-uialertcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!