【问题标题】:How to use UITextView in UIAlertController如何在 UIAlertController 中使用 UITextView
【发布时间】:2015-02-19 09:44:51
【问题描述】:

我使用警报控制器创建了一个弹出警报,并添加了两个警报操作(确定和取消),如下所示。

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];

现在,我想添加 UITextView。因为我有两个文本字段,如标题和描述。对于描述,我想使用 UITextView 添加行数。我试过了,我不知道如何添加它。

请指教。

【问题讨论】:

  • 不要,使用自定义视图,或者以模态方式呈现的视图控制器。
  • @vikingosegundo 好吧...抱歉。谢谢

标签: ios objective-c uialertcontroller


【解决方案1】:

Johno2110 的解决方案对我来说效果最好,只需进行一些清理和调整。在此处发布代码和结果的屏幕截图,以防它帮助其他人。

确认使用 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)
        }
    }
}

【讨论】:

  • 这些按钮在较小的设备上隐藏在键盘后面。将警报移动到屏幕上方一点的任何方法,或者可能会减小 textview 的大小
【解决方案2】:

将 UITextView 添加到 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)
        }
    }
}

&lt;script src="https://gist.github.com/bennagar/c0cd618bcd23c4c2dadf.js"&gt;&lt;/script&gt;

仍然锁定获取标记视图高度的方法,当我拥有它时,我可以将 /2 替换为正确的高度。

【讨论】:

  • 在 Swift3 中,即使在修改其他变量后也抛出错误:An -observeValueForKeyPath:ofObject:change:context: message was received but not handling.
【解决方案3】:

使用上述解决方案,我的 textview 没有正确定位。这就是我让它工作的方式:

   // 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]];

【讨论】:

  • 非常感谢 aloooot!这应该是公认的答案。
【解决方案4】:

斯威夫特 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】:

    上述出色的解决方案。有些需要一些操作才能为 Swift 4.2 工作,这里是转换。我还在 TextView 中添加了一些填充,使其在运动上更令人愉悦。

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

    【讨论】:

    • 这很好用而且看起来很棒。您可以使用警报字段的消息字段来指导用户输入内容(因为标题字段被文本视图隐藏)。
    • 这没有按预期工作,这里我没有在弹出窗口中获取文本视图,它仅带有标题和按钮
    • 弹窗居中,键盘与按键重叠,无法关闭!
    【解决方案6】:

    试试我从这里得到的代码: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"); 
    }];
    

    然后显示它。

    【讨论】:

    • 如何添加多行。
    • 我要么添加多个 UITextView,要么创建我自己的 UIView 子类,其中包含一个 UITextView。
    • 多个UITextView。
    • 我假设您只是重复 [alertController addTextFieldWith...] 行和下面的两个(除非您不想自定义它)并且新的文本视图将添加到第一个下面.
    • 我认为他想要一个不同于 UITextFIELD 的 UITextVIEW...FIELD 是一行编辑,用于标题,而 VIEW 有多行,用于描述
    猜你喜欢
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2015-02-22
    • 2018-10-19
    • 1970-01-01
    相关资源
    最近更新 更多