I almost have the whole moving a UITextView above the keyboard, increasing/decreasing its height based on the amount of text and then returning it to its original position. However, I'm having trouble getting the parent UIView to grow along with the UITextView.
If I uncomment the last line of the updateParentView() method to update the parent UIView to its updated size, nothing changes size, including the 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()
}
}
I have a really simple answer, I hope it can help. What I have is pretty simple and doesn't invlove code. I did all by constraints. Here there are a pair of images to help me expain:
This is what I have
This is how it really looks like
It's crucial that the TextView
has this property unchecked in property inspector:
Then you simple set the top, leading, trailing and bottom for each view and set no height to any of them. Everything will grow when typing along with it's parent views! :)
This is what worked for me. In my case, I have the text view below a table view. So, as the text view grows in height, the parent view isn't actually what needs to change - the view above the text view is what needs to resize (for me it was the table view). So, here is what I implemented in the updateParentView
function.
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
}
Now, as the text view increases in height, the table view "slides up" per newContainerViewFrame.origin.y - containerViewHeightDifference
. Check out the screenshot below.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With