Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 420 Vote(s) - 3.44 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do I scroll the UIScrollView when the keyboard appears?

#11
Apple's recommendation recoded in **Swift** + Using UIScrollView with Auto Layout in iOS (basing on these following links: [link 1][1], [link 2][2], [link 3][3]):



import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

@IBOutlet var t1: UITextField!
@IBOutlet var t2: UITextField!
@IBOutlet var t3: UITextField!
@IBOutlet var t4: UITextField!

@IBOutlet var srcScrollView: UIScrollView!

@IBOutlet var contentView: UIView!

var contentViewCoordinates: CGPoint!

override func viewDidLoad() {

super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

/* Constraints on content view */
let leftConstraint = NSLayoutConstraint(item:self.contentView,
attribute:NSLayoutAttribute.Leading,
relatedBy:NSLayoutRelation.Equal,
toItem:self.view,
attribute:NSLayoutAttribute.Left,
multiplier:1.0,
constant:0)
self.view.addConstraint(leftConstraint)

let rightConstraint = NSLayoutConstraint(item:self.contentView,
attribute:NSLayoutAttribute.Trailing,
relatedBy:NSLayoutRelation.Equal,
toItem:self.view,
attribute:NSLayoutAttribute.Right,
multiplier:1.0,
constant:0)
self.view.addConstraint(rightConstraint)

/* Tap gesture */
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = false
srcScrollView.addGestureRecognizer(tapGesture)

/* Save content view coordinates */
contentViewCoordinates = contentView.frame.origin
}

func hideKeyboard() {
t1.resignFirstResponder()
t2.resignFirstResponder()
t3.resignFirstResponder()
t4.resignFirstResponder()
}

var activeField: UITextField?

func textFieldDidBeginEditing(textField: UITextField) {
activeField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
activeField = nil
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let center = NSNotificationCenter.defaultCenter()
center.addObserver(self, selector: "keyboardOnScreen:", name: UIKeyboardDidShowNotification, object: nil)
center.addObserver(self, selector: "keyboardOffScreen:", name: UIKeyboardDidHideNotification, object: nil)
}

func keyboardOnScreen(notification: NSNotification){
// Retrieve the size and top margin (inset is the fancy word used by Apple)
// of the keyboard displayed.
let info: NSDictionary = notification.userInfo!
let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize!.height, 0.0)

srcScrollView.contentInset = contentInsets
srcScrollView.scrollIndicatorInsets = contentInsets

var aRect: CGRect = self.view.frame
aRect.size.height -= kbSize!.height
//you may not need to scroll, see if the active field is already visible
if (CGRectContainsPoint(aRect, activeField!.frame.origin) == false) {
let scrollPoint:CGPoint = CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height)
srcScrollView.setContentOffset(scrollPoint, animated: true)
}
}

// func keyboardOnScreen(aNotification: NSNotification) {
// let info: NSDictionary = aNotification.userInfo!
// let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
//
// var bkgndRect: CGRect! = activeField?.superview?.frame
//
// bkgndRect.size.height += kbSize!.height
//
// activeField?.superview?.frame = bkgndRect
//
// srcScrollView.setContentOffset(CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height), animated: true)
// }

func keyboardOffScreen(notification: NSNotification){
let contentInsets:UIEdgeInsets = UIEdgeInsetsZero

srcScrollView.contentInset = contentInsets
srcScrollView.scrollIndicatorInsets = contentInsets

self.srcScrollView.setContentOffset(CGPointMake(0, -self.view.frame.origin.y/2), animated: true)
}

}


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:
Reply

#12
Use following extension if you don't want to calculate too much:

func scrollSubviewToBeVisible(subview: UIView, animated: Bool) {
let visibleFrame = UIEdgeInsetsInsetRect(self.bounds, self.contentInset)
let subviewFrame = subview.convertRect(subview.bounds, toView: self)
if (!CGRectContainsRect(visibleFrame, subviewFrame)) {
self.scrollRectToVisible(subviewFrame, animated: animated)
}
}

And maybe you want keep your UITextField always visible:

func textViewDidChange(textView: UITextView) {
self.scrollView?.scrollSubviewToBeVisible(textView, animated: false)
}
Reply

#13
I used this answer supplied by Sudheer Palchuri

[To see links please register here]

[To see links please register here]


In ViewDidLoad, register the notifications:

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

Add below observer methods which does the automatic scrolling when keyboard appears.

func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}

func keyboardWillShow(notification:NSNotification){

var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)

var contentInset:UIEdgeInsets = self.scrollView.contentInset
contentInset.bottom = keyboardFrame.size.height
self.scrollView.contentInset = contentInset
}

func keyboardWillHide(notification:NSNotification){

var contentInset:UIEdgeInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInset
}
Reply

#14
This is the final code with improvements in **Swift**

//MARK: UITextFieldDelegate
func textFieldDidBeginEditing(textField: UITextField!) { //delegate method
self.textField = textField
}

func textFieldShouldReturn(textField: UITextField!) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}

//MARK: Keyboard handling
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
unregisterKeyboardNotifications()
}

func registerKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}

func unregisterKeyboardNotifications() {
NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardDidShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo!
let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size
let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets

var viewRect = self.view.frame
viewRect.size.height -= keyboardSize.height
let relativeFieldFrame: CGRect = textField.convertRect(textField.frame, toView: self.view)
if CGRectContainsPoint(viewRect, relativeFieldFrame.origin) {
let scrollPoint = CGPointMake(0, relativeFieldFrame.origin.y - keyboardSize.height)
scrollView.setContentOffset(scrollPoint, animated: true)
}

}

func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = UIEdgeInsetsZero
scrollView.scrollIndicatorInsets = UIEdgeInsetsZero
}
Reply

#15
I've found the above answers have been outdated. Also not perfect when scroll.

Here's a swift version.

It will scroll right below the textField, no spare space. And It will restore to the way it was like its first appear.

//add observer
override func viewDidLoad() {
super.viewDidLoad()

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
}

func keyboardDidShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo!
let keyboardSize = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)!.CGRectValue.size
let difference = keyboardSize.height - (self.view.frame.height - inputTextField.frame.origin.y - inputTextField.frame.size.height)
if difference > 0 {
var contentInset:UIEdgeInsets = self.scrollView.contentInset
contentInset.bottom = difference
self.scrollView.contentInset = contentInset

let scrollPoint = CGPointMake(0, difference)
self.scrollView.setContentOffset(scrollPoint, animated: true)
}

}

func keyboardDidHide(notification: NSNotification) {
let contentInset:UIEdgeInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInset
}

//remove observer
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
Reply

#16
Here is a **Swift 3** compatible answer, that will also work with view controllers within a navigation controller - as they will change the scroll views `contentInset.top` property.

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)

self.registerKeyboardNotifications()
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

self.unregisterKeyboardNotifications()
}

func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardDidShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func unregisterKeyboardNotifications() {
NotificationCenter.default.removeObserver(self)
}


func keyboardDidShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
let keyboardSize = keyboardInfo.cgRectValue.size

// Get the existing contentInset for the scrollView and set the bottom property to be the height of the keyboard
var contentInset = self.scrollView.contentInset
contentInset.bottom = keyboardSize.height

self.scrollView.contentInset = contentInset
self.scrollView.scrollIndicatorInsets = contentInset
}

func keyboardWillHide(notification: NSNotification) {
var contentInset = self.scrollView.contentInset
contentInset.bottom = 0

self.scrollView.contentInset = contentInset
self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero
}
Reply

#17
My solution has 4 step:<br/>
- Step 1: the function listens when the keyboard appears

- (void)keyboardWasShown:(NSNotification *)notification {
// Get the size of the keyboard.
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
//top: 64 for navigation bar, 0 for without navigation
UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, keyboardSize.height, 0);
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
}
- Step 2: the function listens when the keyboard disappears

- (void)keyboardWillHide:(NSNotification *)notification {
//top: 64 for navigatiob bar
UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, 0, 0);
[_editScrollView setContentInset: contentInsets];
[_editScrollView setScrollIndicatorInsets: contentInsets];
}
- Step 3: add these functions to the notification center:

- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- Step 4: remove listen when view controller disappers

- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}


Reply

#18
I just implemented this with Swift 2.0 for iOS9 on Xcode 7 (beta 6), works fine here.

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}

func registerKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}

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

func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo!
let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size
let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets

var viewRect = view.frame
viewRect.size.height -= keyboardSize.height
if CGRectContainsPoint(viewRect, textField.frame.origin) {
let scrollPoint = CGPointMake(0, textField.frame.origin.y - keyboardSize.height)
scrollView.setContentOffset(scrollPoint, animated: true)
}
}

func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = UIEdgeInsetsZero
scrollView.scrollIndicatorInsets = UIEdgeInsetsZero
}

**Edited for Swift 3**

Seems like you only need to set the `contentInset` and `scrollIndicatorInset` with Swift 3, the scrolling/contentOffset is done automatically..

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}

func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(notification:)),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(notification:)),
name: NSNotification.Name.UIKeyboardWillHide,
object: nil)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
let keyboardSize = keyboardInfo.cgRectValue.size
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}

func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}

Reply

#19
Try this code in Swift 3:


override func viewDidAppear(_ animated: Bool) {
setupViewResizerOnKeyboardShown()
}

func setupViewResizerOnKeyboardShown() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardWillShowForResizing),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardWillHideForResizing),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}

func keyboardWillShowForResizing(notification: Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let window = self.view.window?.frame {
// We're not just minusing the kb height from the view height because
// the view could already have been resized for the keyboard before
self.view.frame = CGRect(x: self.view.frame.origin.x,
y: self.view.frame.origin.y,
width: self.view.frame.width,
height: window.origin.y + window.height - keyboardSize.height)

} else {
debugPrint("We're showing the keyboard and either the keyboard size or window is nil: panic widely.")
}
}

func keyboardWillHideForResizing(notification: Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let viewHeight = self.view.frame.height
self.view.frame = CGRect(x: self.view.frame.origin.x,
y: self.view.frame.origin.y,
width: self.view.frame.width,
height: viewHeight) //viewHeight + keyboardSize.height

} else {
debugPrint("We're about to hide the keyboard and the keyboard size is nil. Now is the rapture.")
}
}

deinit {
NotificationCenter.default.removeObserver(self)
}
Reply

#20
**Swift 4.2** solution that takes possible heights of UIToolbar and UITabBar into account.

private func setupKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIControl.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIControl.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWillShow(_ notification: Notification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size

let tabbarHeight = tabBarController?.tabBar.frame.size.height ?? 0
let toolbarHeight = navigationController?.toolbar.frame.size.height ?? 0
let bottomInset = keyboardSize.height - tabbarHeight - toolbarHeight

scrollView.contentInset.bottom = bottomInset
scrollView.scrollIndicatorInsets.bottom = bottomInset
}

@objc func keyboardWillHide(_ notification: Notification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}


And, if you're targeting < iOS 9, you have to unregister the observer at some point (thanks [Joe][1])


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through