How to use UITextView in UIAlertController

后端 未结 6 1349
悲哀的现实
悲哀的现实 2020-12-16 18:48

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

UIAlertController * alert=   [UIAlertController
                  


        
相关标签:
6条回答
  • 2020-12-16 18:58

    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]];
    
    0 讨论(0)
  • 2020-12-16 18:58

    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)
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 19:05

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

    0 讨论(0)
  • 2020-12-16 19:06

    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.

    0 讨论(0)
  • 2020-12-16 19:07

    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.

    0 讨论(0)
  • 2020-12-16 19:14

    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)
    
    0 讨论(0)
提交回复
热议问题