iOS Swift - 动态增加 UITextView 和父 UIView 的高度

Posted

技术标签:

【中文标题】iOS Swift - 动态增加 UITextView 和父 UIView 的高度【英文标题】:iOS Swift - Dynamically increase height of UITextView and parent UIView 【发布时间】:2015-01-25 22:37:37 【问题描述】:

我几乎让整个 UITextView 在键盘上方移动,根据文本量增加/减少其高度,然后将其返回到原始位置。但是,我无法让父 UIView 与 UITextView 一起增长。

如果我取消注释 updateParentView() 方法的最后一行以将父 UIView 更新为其更新后的大小,则不会更改大小,包括 UITextView。

class ViewController: UIViewController, UITextViewDelegate 

    var kPreferredTextViewToKeyboardOffset: CGFloat = 0.0
    var keyboardFrame: CGRect = CGRect.nullRect
    var keyboardIsShowing: Bool = false

    @IBOutlet weak var commentView: UIView!
    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var sendButton: UIButton!

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)

        // Make it look like UITextField
        self.textView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
        self.textView.sizeToFit()
        let lightestGrayColor: UIColor = UIColor( red: 224.0/255.0, green: 224.0/255.0, blue:224.0/255.0, alpha: 1.0 )
        self.textView.layer.borderColor = lightestGrayColor.CGColor
        self.textView.layer.borderWidth = 0.6
        self.textView.layer.cornerRadius = 6.0
        self.textView.clipsToBounds = true
        self.textView.layer.masksToBounds = true
    

    override func viewWillDisappear(animated: Bool) 
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self)
    

    func keyboardWillShow(notification: NSNotification)
    
        self.keyboardIsShowing = true

        if let info = notification.userInfo 
            self.keyboardFrame = (info[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
            self.arrangeViewOffsetFromKeyboard()
        

    

    func keyboardWillHide(notification: NSNotification)
    
        self.keyboardIsShowing = false

        self.returnViewToInitialFrame()
    

    func arrangeViewOffsetFromKeyboard()
    
        var theApp: UIApplication = UIApplication.sharedApplication()
        var windowView: UIView? = theApp.delegate!.window!

        var textFieldLowerPoint: CGPoint = CGPointMake(self.commentView!.frame.origin.x, self.commentView!.frame.origin.y + self.commentView!.frame.size.height)

        var convertedTextViewLowerPoint: CGPoint = self.view.convertPoint(textFieldLowerPoint, toView: windowView)

        var targetTextViewLowerPoint: CGPoint = CGPointMake(self.commentView!.frame.origin.x, self.keyboardFrame.origin.y - kPreferredTextViewToKeyboardOffset)

        var targetPointOffset: CGFloat = targetTextViewLowerPoint.y - convertedTextViewLowerPoint.y
        var adjustedViewFrameCenter: CGPoint = CGPointMake(self.view.center.x, self.view.center.y + targetPointOffset)

        UIView.animateWithDuration(0.2, animations:  
            self.view.center = adjustedViewFrameCenter
        )
    

    func returnViewToInitialFrame()
    
        var initialViewRect: CGRect = CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height)

        if (!CGRectEqualToRect(initialViewRect, self.view.frame))
        
            UIView.animateWithDuration(0.2, animations: 
                self.view.frame = initialViewRect
            );
        
    

    func textViewDidBeginEditing(textView: UITextView) 
        //
        print("text view did begin editing\n")
        //
        if(self.keyboardIsShowing)
        
            self.arrangeViewOffsetFromKeyboard()
        
    

    func textViewDidChange(textView: UITextView) 
        print("text view did change\n")
        let textViewFixedWidth: CGFloat = self.textView.frame.size.width
        let newSize: CGSize = self.textView.sizeThatFits(CGSizeMake(textViewFixedWidth, CGFloat(MAXFLOAT)))
        var newFrame: CGRect = self.textView.frame
        //
        var textViewYPosition = self.textView.frame.origin.y
        var heightDifference = self.textView.frame.height - newSize.height
        //
        if (abs(heightDifference) > 5) 
            newFrame.size = CGSizeMake(fmax(newSize.width, textViewFixedWidth), newSize.height)
            newFrame.offset(dx: 0.0, dy: heightDifference)
            //
            updateParentView(heightDifference: heightDifference)
        
        self.textView.frame = newFrame
    

    func updateParentView(#heightDifference: CGFloat) 
        //
        var newContainerViewFrame: CGRect = self.commentView.frame
        //
        var containerViewHeight = self.commentView.frame.size.height
        print("container view height: \(containerViewHeight)\n")
        //
        var newContainerViewHeight = containerViewHeight - heightDifference
        print("new container view height: \(newContainerViewHeight)\n")
        //
        var containerViewHeightDifference = containerViewHeight - newContainerViewHeight
        print("container view height difference: \(containerViewHeightDifference)\n")
        //
        newContainerViewFrame.size = CGSizeMake(self.commentView.frame.size.width, newContainerViewHeight)
        //
        newContainerViewFrame.offset(dx: 0.0, dy: containerViewHeightDifference)
        //
        // self.commentView.frame = newContainerViewFrame
    

    func textViewDidEndEditing(textView: UITextView) 
        //
        print("text view did end editing\n")
        //
        textView.resignFirstResponder()
    


【问题讨论】:

我有点困惑。 newContainterViewHeight 应该是 containerViewHeight + heightDifference 而不是 - 【参考方案1】:

我有一个非常简单的答案,希望对您有所帮助。我所拥有的非常简单,并且不涉及代码。我做了所有的限制。这里有一对图像可以帮助我解释:

这就是我所拥有的

这才是真正的样子

TextView 在属性检查器中未选中此属性至关重要:

然后,您只需为每个视图设置顶部、前导、尾随和底部,并将 no height 设置为其中任何一个。打字时一切都会随着它的父视图一起增长! :)

【讨论】:

【参考方案2】:

这对我有用。就我而言,我在表格视图下方有文本视图。因此,随着文本视图的高度增加,父视图实际上并不是需要更改的——文本视图上方的视图是需要调整大小的(对我来说是表格视图)。所以,这就是我在updateParentView 函数中实现的。

func updateParentView(heightDifference: CGFloat) 
    //
    var newContainerViewFrame: CGRect = self.commentTableView.frame
    //
    let containerViewHeight = self.commentTableView.frame.size.height
    print("container view height: \(containerViewHeight)\n")
    //
    let newContainerViewHeight = containerViewHeight + heightDifference
    print("new container view height: \(newContainerViewHeight)\n")
    //
    let containerViewHeightDifference = containerViewHeight - newContainerViewHeight
    print("container view height difference: \(containerViewHeightDifference)\n")
    //
    newContainerViewFrame.size = CGSizeMake(self.commentTableView.frame.size.width, newContainerViewHeight)
    //
    newContainerViewFrame.origin.y - containerViewHeightDifference
    //
    self.commentTableView.frame = newContainerViewFrame

现在,随着文本视图的高度增加,表格视图按照newContainerViewFrame.origin.y - containerViewHeightDifference“向上滑动”。看看下面的截图。

【讨论】:

以上是关于iOS Swift - 动态增加 UITextView 和父 UIView 的高度的主要内容,如果未能解决你的问题,请参考以下文章

如何根据swift 3中的集合视图高度动态增加表格视图高度?

在 Swift 中的 UITextView 上放置阴影

Swift 4 - 如何使用按钮启用/禁用键盘

iOS:在 Swift 中动态设置 UITableView 高度

Firebase.google.com iOS 中的 Firebase 动态链接(Swift)

Swift URL 编码返回 Optional("String")