光标在UITextView

时间:2016-10-03 21:38:07

标签: ios swift uitextview nslayoutconstraint

我在我的UITextView应用中从头开始编写swift。 我在textView上添加view,如下所示:

enter image description here

它就在键盘的正上方。

textView附加了约viewleadingbottomtoptrailing,所有等于= {{1 }}

4具有以下限制:

viewtrailingleadingbottomtop

height是我代码中的一个出口。我正在检查Height中有多少行,并根据我修改textView

height

以上行数由此扩展程序计算:

func textViewDidChange(textView: UITextView) { //Handle the text changes here
    switch(textView.numberOfLines()) {
    case 1:
        heightConstraint.constant = 38
        break
    case 2:
        heightConstraint.constant = 50
        break
    case 3:
        heightConstraint.constant = 70
        break
    case 4:
        heightConstraint.constant = 90
        break
    default:
        heightConstraint.constant = 90
        break
    }
}

extension UITextView{ func numberOfLines() -> Int{ if let fontUnwrapped = self.font{ return Int(self.contentSize.height / fontUnwrapped.lineHeight) } return 0 } } 的初始高度为textView38中的初始字体大小为textView

现在,当用户开始键入新行时,它工作得很好,但15未设置在视图的完整范围内。我的意思是这样的事实,它看起来像这样:

enter image description here

它应该是这样的:

enter image description here

为什么会添加这个额外的空白区域,如何摆脱它?

目前,当新行显示在此空白区域时,但当用户滚动textView以使文本居中并摆脱空白区域时 - 它永远消失,用户无法滚动它又一次,所以白线就在那里。所以对我来说,看起来像刷新内容有些问题,但也许你知道的更好 - 你能给我一些提示吗?

2 个答案:

答案 0 :(得分:3)

我正在开发的其中一个应用程序的评论部分中使用了一些不同的方法。这与Facebook Messenger iOS应用程序的输入字段非常相似。更改了插座名称以与您问题中的插座名称相匹配。

//Height constraint outlet of view which contains textView.
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
@IBOutlet weak var textView: UITextView!

//Maximum number of lines to grow textView before enabling scrolling.
let maxTextViewLines = 5
//Minimum height for textViewContainer (when there is no text etc.)
let minTextViewContainerHeight = 40

func textViewDidChange(textView: UITextView) {
    let textViewVerticalInset = textView.textContainerInset.bottom + textView.textContainerInset.top
    let maxHeight = ((textView.font?.lineHeight)! * maxTextViewLines) + textViewVerticalInset
    let sizeThatFits = textView.sizeThatFits(CGSizeMake(textView.frame.size.width, CGFloat.max))

    if sizeThatFits.height < minTextViewContainerHeight {
        heightConstraint.constant = minTextViewContainerHeight
        textView.scrollEnabled = false
    } else if sizeThatFits.height < maxHeight {
        heightConstraint.constant = sizeThatFits.height
        textView.scrollEnabled = false
    } else {
        heightConstraint.constant = maxHeight
        textView.scrollEnabled = true
    }
}

func textViewDidEndEditing(textView: UITextView) {
    textView.text = ""
    heightConstraint.constant = minTextViewContainerHeight
    textView.scrollEnabled = false
}

答案 1 :(得分:-1)

我正在使用ASTextInputAccessoryView。它为您处理一切,并且非常容易设置:

enter image description here

import ASTextInputAccessoryView

class ViewController: UIViewController {

    var iaView: ASResizeableInputAccessoryView!    
    var messageView = ASTextComponentView()

    override func viewDidLoad() {
        super.viewDidLoad()

        let photoComponent = UINib
            .init(nibName: "PhotosComponentView", bundle: nil)
            .instantiateWithOwner(self, options: nil)
            .first as! PhotosComponentView

        messageView = ASTextComponentView(frame: CGRect(x: 0, y: 0, width: screenSize.width , height: 44))
        messageView.backgroundColor = UIColor.uIColorFromHex(0x191919)
        messageView.defaultSendButton.addTarget(self, action: #selector(buttonAction), forControlEvents: .TouchUpInside)

        iaView = ASResizeableInputAccessoryView(components: [messageView, photoComponent])
        iaView.delegate = self        
    }
}

//MARK: Input Accessory View
extension ViewController {
    override var inputAccessoryView: UIView? {
        return iaView
    }

    // IMPORTANT Allows input view to stay visible
    override func canBecomeFirstResponder() -> Bool {
        return true
    }

    // Handle Rotation
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

        coordinator.animateAlongsideTransition({ (context) in
            self.messageView.textView.layoutIfNeeded()
        }) { (context) in
            self.iaView.reloadHeight()
        }
    }
}

// MARK: ASResizeableInputAccessoryViewDelegate
extension ViewController: ASResizeableInputAccessoryViewDelegate {

    func updateInsets(bottom: CGFloat) {
        var contentInset = tableView.contentInset
        contentInset.bottom = bottom
        tableView.contentInset = contentInset
        tableView.scrollIndicatorInsets = contentInset
    }

    func inputAccessoryViewWillAnimateToHeight(view: ASResizeableInputAccessoryView, height: CGFloat, keyboardHeight: CGFloat) -> (() -> Void)? {

        return { [weak self] in
            self?.updateInsets(keyboardHeight)
            self?.tableView.scrollToBottomContent(false)
        }
    }

    func inputAccessoryViewKeyboardWillPresent(view: ASResizeableInputAccessoryView, height: CGFloat) -> (() -> Void)? {
        return { [weak self] in
            self?.updateInsets(height)
            self?.tableView.scrollToBottomContent(false)
        }
    }

    func inputAccessoryViewKeyboardWillDismiss(view: ASResizeableInputAccessoryView, notification: NSNotification) -> (() -> Void)? {
        return { [weak self] in
            self?.updateInsets(view.frame.size.height)
        }
    }

    func inputAccessoryViewKeyboardDidChangeHeight(view: ASResizeableInputAccessoryView, height: CGFloat) {
        let shouldScroll = tableView.isScrolledToBottom
        updateInsets(height)
        if shouldScroll {
            self.tableView.scrollToBottomContent(false)
        }
    }
}

现在您只需要设置AccessoryView按钮的操作。

// MARK: Actions
extension ViewController {

    func buttonAction(sender: UIButton!) {

        // do whatever you like with the "send" button. for example post stuff to firebase or whatever
        // messageView.textView.text <- this is the String inside the textField

        messageView.textView.text = ""
    }

    @IBAction func dismissKeyboard(sender: AnyObject) {
        self.messageView.textView.resignFirstResponder()
    }

    func addCameraButton() {

        let cameraButton = UIButton(type: .Custom)
        let image = UIImage(named: "camera")?.imageWithRenderingMode(.AlwaysTemplate)
        cameraButton.setImage(image, forState: .Normal)
        cameraButton.tintColor = UIColor.grayColor()

        messageView.leftButton = cameraButton

        let width = NSLayoutConstraint(
            item: cameraButton,
            attribute: .Width,
            relatedBy: .Equal,
            toItem: nil,
            attribute: .NotAnAttribute,
            multiplier: 1,
            constant: 40
        )
        cameraButton.superview?.addConstraint(width)

        cameraButton.addTarget(self, action: #selector(self.showPictures), forControlEvents: .TouchUpInside)
    }

    func showPictures() {

        PHPhotoLibrary.requestAuthorization { (status) in
            NSOperationQueue.mainQueue().addOperationWithBlock({
                if let photoComponent = self.iaView.components[1] as? PhotosComponentView {
                    self.iaView.selectedComponent = photoComponent
                    photoComponent.getPhotoLibrary()
                }
            })
        }
    }
}