5

enter image description here

I need to move a UITextView up out of the way of the keyboard when some input is required. I am using the following code and it works perfectly with a UITextField but not at all with a UITextView.

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self,
                                                     selector: #selector(DailyNotesViewController.keyboardWillShow(_:)),
                                                     name: UIKeyboardWillShowNotification,
                                                     object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self,
                                                     selector: #selector(DailyNotesViewController.keyboardWillHide(_:)),
                                                     name: UIKeyboardWillHideNotification,
                                                     object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func adjustInsetForKeyboardShow(show: Bool, notification: NSNotification) {
    let userInfo = notification.userInfo ?? [:]
    let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
    let adjustmentHeight = (CGRectGetHeight(keyboardFrame) + 20) * (show ? 1 : -1)
    scrollView.contentInset.bottom += adjustmentHeight
    scrollView.scrollIndicatorInsets.bottom += adjustmentHeight
}

func keyboardWillShow(notification: NSNotification) {
    adjustInsetForKeyboardShow(true, notification: notification)
}

func keyboardWillHide(notification: NSNotification) {
    adjustInsetForKeyboardShow(false, notification: notification)
}

Kindly suggest what I am missing?

Adil Soomro
  • 37,609
  • 9
  • 103
  • 153
Wayne
  • 283
  • 1
  • 3
  • 21
  • By "it works perfectly with a UITextField but not at all with a UITextView" what do you mean, what is "working perfectly" and what is happening with the textview that means its not working... what IS happening with it? – Scriptable Sep 08 '16 at 11:47
  • The UITextfield moves up so it is not covered or obscured by the keyboard but the UITextView does not move and does get covered by the keyboard. – Wayne Sep 08 '16 at 11:54
  • Could you screenshot the layout of the screen with and without the keyboard showing. if the view is moving up and everything else with it but the textview is not, it sounds like its likely an issue with the positioning/constraints of the textview. How is the textview connected to the view hierarchy? – Scriptable Sep 08 '16 at 11:57
  • Use Keyboard notification to manage its dynmatic height along with device – Shobhakar Tiwari Sep 08 '16 at 11:59
  • Check: http://stackoverflow.com/questions/28813339/move-a-view-up-only-when-the-keyboard-covers-an-input-field – KNV Sep 08 '16 at 12:05
  • There are lot of similar questions available already. Should check http://stackoverflow.com/questions/26070242/move-view-with-keyboard-using-swift – Santosh Sep 08 '16 at 13:11
  • @Santosh - I have tried to search but all I find relates to a UITextField which I have covered and works beautifully with the code in my post. I just don't understand why it does not work if the bottom input field is a textView. Thanks. – Wayne Sep 08 '16 at 13:14
  • How about this one? http://stackoverflow.com/questions/18224161/how-to-make-a-uitextview-move-up-when-keyboard-is-present – Santosh Sep 08 '16 at 13:16

3 Answers3

5

The actual solution turned out to be very simple.

On the UITextView, set scrollingEnabled to False.

Thanks for all the assistance.

Wayne
  • 283
  • 1
  • 3
  • 21
0
func animateTextView(textView: UITextView, up: Bool)
{
    let movementDistance:CGFloat = -170
    let movementDuration: Double = 0.3

    var movement:CGFloat = 0
    if up
    {
        movement = movementDistance
    }
    else
    {
        movement = -movementDistance
    }
    UIView.beginAnimations("animateTextView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)
    self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
    UIView.commitAnimations()
}


func textViewDidBeginEditing(_ textView: UITextView)
{
    if (textView.tag == 1) { // remarks textview
        self.animateTextView(textView: textView, up:true)
    }
}

func textViewDidEndEditing(_ textView: UITextView)
{
    if (textView.tag == 1) { // remarks textview
        self.animateTextView(textView: textView, up:false)
    }
}
auspicious99
  • 3,902
  • 1
  • 44
  • 58
-1

first you set this fraction

var animatedDistance: CGFloat = 0.0
let KEYBOARD_ANIMATION_DURATION: CGFloat = 0.3
let MINIMUM_SCROLL_FRACTION: CGFloat = 0.2
let MAXIMUM_SCROLL_FRACTION: CGFloat = 0.8
let PORTRAIT_KEYBOARD_HEIGHT: CGFloat = 120
let LANDSCAPE_KEYBOARD_HEIGHT: CGFloat = 140

After call the textviewdelegate

 func textViewDidBeginEditing(textView: UITextView) {
 var textFieldRect = self.view.window.convertRect(textView.bounds, fromView: textView)
 var viewRect = self.view.window.convertRect(self.view.bounds, fromView: self.view)
 var midline: CGFloat = textFieldRect.origin.y + 0.5 * textFieldRect.size.height
 var numerator: CGFloat = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height
var denominator: CGFloat = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height
var heightFraction: CGFloat = numerator / denominator
if heightFraction < 0.0 {
   heightFraction = 0.0
}
else if heightFraction > 1.0 {
   heightFraction = 1.0
}

var orientation = UIApplication.sharedApplication().statusBarOrientation
if orientation == .Portrait || orientation == .PortraitUpsideDown {
   animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction)

its worked fine at my end please check. its may be helpfull for you.

Pooja Srivastava
  • 721
  • 1
  • 6
  • 19