In view controller I have UIImageView and multiple uitextfields. I'm using the following code, based on Apple documentation, to move the scrollView up when a keyboard notification is called, to push up the hidden text fields. However the when the keyboard appears the view does move up.
Am I missing something here?
class NewViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var scrollView: UIScrollView!
var activeTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.contentSize.height = 1000
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func registerForKeyboardNotifications() {
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: "keyboardWillBeShown:", name: UIKeyboardWillShowNotification, object: nil)
notificationCenter.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillBeShown(sender: NSNotification) {
let info: NSDictionary = sender.userInfo!
let value: NSValue = info.valueForKey(UIKeyboardFrameBeginUserInfoKey) as! NSValue
let keyboardSize: CGSize = value.CGRectValue().size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0.0, keyboardSize.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
print(aRect)
let activeTextFieldRect: CGRect? = activeTextField?.frame
let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
}
}
func keyboardWillBeHidden(sender: NSNotification) {
let contentInsets: UIEdgeInsets = UIEdgeInsetsZero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
func textFieldDidBeginEditing(textField: UITextField) {
activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
activeTextField = nil
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.registerForKeyboardNotifications()
}
override func viewDidDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
Try this code and set "moveValue" for your situation.
Remember to extends UITextFieldDelegate
func textFieldDidBeginEditing(textField: UITextField)
{
self.animateViewMoving(true, moveValue: 85)
}
func textFieldDidEndEditing(textField: UITextField)
{
self.animateViewMoving(false, moveValue: 85)
}
func animateViewMoving (up:Bool, moveValue :CGFloat)
{
let durataMovimento:NSTimeInterval = 0.3
let movimento:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(durataMovimento )
self.view.frame = CGRectOffset(self.view.frame, 0, movimento)
UIView.commitAnimations()
}
Related
I am trying to create a view which slides up when the keyboard appears, and within this view is a text field functioning as a search bar and collection view to hold the results of the search. The View slides up fine right above the keyboard as it is supposed to however once I tap on one of the cells to scroll horrizontally the view just disappears. What could be causing this.
Code That I Think May Be Causing The Problem
var offsetY:CGFloat = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
#objc func keyboardFrameChangeNotification(notification: Notification) {
if let userInfo = notification.userInfo {
let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
let animationCurve = UIViewAnimationOptions(rawValue: Int(animationCurveRawValue))
if let _ = endFrame, endFrame!.intersects(self.myView.frame) {
self.offsetY = self.myView.frame.maxY - endFrame!.minY
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y - self.offsetY
}, completion: nil)
} else {
if self.offsetY != 0 {
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y + self.offsetY
self.offsetY = 0
}, completion: nil)
}
}
}
}
Code in its entirety
import UIKit
class SearchCollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UITextFieldDelegate, UICollectionViewDataSource {
#IBOutlet weak var searchBar: UITextField!
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var myView: UIView!
var genericArray:[String] = ["A","B","C","D","E","F","G","Ab","Abc"]
var currentGenericArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: (UIScreen.main.bounds.width-1)/2, height: (UIScreen.main.bounds.width-1)/2)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
layout.scrollDirection = .horizontal
self.collectionView.collectionViewLayout = layout
searchBar.delegate = self
currentGenericArray = genericArray
searchBar.addTarget(self, action: #selector(TableSearchViewController.textFieldDidChange), for: .editingChanged)
}
#objc func textFieldDidChange(){
guard(!(searchBar.text?.isEmpty)!) else{
currentGenericArray = genericArray
collectionView.reloadData()
return
}
currentGenericArray = genericArray.filter({letter -> Bool in
letter.lowercased().contains(searchBar.text!)
})
collectionView.reloadData()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return currentGenericArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionCell
cell.collectionLabel.text = currentGenericArray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
var offsetY:CGFloat = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
#objc func keyboardFrameChangeNotification(notification: Notification) {
if let userInfo = notification.userInfo {
let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
let animationCurve = UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue))
if let _ = endFrame, endFrame!.intersects(self.myView.frame) {
self.offsetY = self.myView.frame.maxY - endFrame!.minY
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y - self.offsetY
}, completion: nil)
} else {
if self.offsetY != 0 {
UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
self.myView.frame.origin.y = self.myView.frame.origin.y + self.offsetY
self.offsetY = 0
}, completion: nil)
}
}
}
}
}
class CollectionCell:UICollectionViewCell{
#IBOutlet weak var collectionLabel: UILabel!
override func awakeFromNib() {
collectionLabel.textAlignment = .center
}
}
Your code is a bit muddled but I don't see any textField functions except for didChange which you call from your searchBar. Try adding a shouldReturn and a didEndEditing, as well as update your slider. Here is an example of what I would do. Try it and see if it makes a difference.
Lifecycle
let keyboardSlider = KeyboardSlider()
override func viewDidLoad() {
super.viewDidLoad()
keyboardSlider.subscribeToKeyboardNotifications(view: view)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
keyboardSlider.unsubscribeFromKeyboardNotifications()
}
TextField
// MARK: TextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
// Add Done button for Keyboard Dismissal
let toolBar = UIToolbar()
toolBar.sizeToFit()
toolBar.barStyle = .default
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.didStopEditing))
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
toolBar.setItems([space, doneButton], animated: false)
textField.inputAccessoryView = toolBar
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
/// Helper to dismiss keyboard
#objc func didStopEditing() {
textFieldShouldReturn(phoneNumberTextField)
}
func textFieldDidEndEditing(_ textField: UITextField) {
UIView.setAnimationCurve(UIViewAnimationCurve.easeInOut)
UIView.animate(withDuration: 0.2) {
self.view.frame.origin.y = 0
}
}
Keyboard Slider
class KeyboardSlider: NSObject {
// variables to hold and process information from the view using this class
weak var view: UIView?
#objc func keyboardWillShow(notification: NSNotification) {
// method to move keyboard up
view?.frame.origin.y = 0 - getKeyboardHeight(notification as Notification)
}
func getKeyboardHeight(_ notification:Notification) -> CGFloat {
// get exact height of keyboard on all devices and convert to float value to return for use
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
return keyboardSize.cgRectValue.height
}
func subscribeToKeyboardNotifications(view: UIView) {
// assigning view to class' counterpart
self.view = view
// when UIKeyboardWillShow do keyboardWillShow function
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
}
}
This answer is mainly to clean up your code
I have a feeling that your problem is in your didChange method on keyboard dismissal. Cleaning up your code and stepping through breakpoints will help locate your issue.
I have recently started to develop my own app following the instructions on internet. I am just a beginner (with no knowledge of coding) and hence may be doing very stupid mistake that I am not able to catch.
In my app I am facing a situation where my email text field is hiding behind the keyboard whenever I try to type email address. I did some research (on stack overflow) and wrote a piece of code that suppose to move my text field up but it is not ... I believe overall structure of code is right (I may be wrong here though) but it may be just tiny mistake that making my code ineffective.
can anyone guide me on what I am doing wrong here?
below is the piece of code I wrote:
{
import UIKit
import WebKit
import CoreGraphics
import AVFoundation
import QuartzCore
import Foundation
class StudentSignUpViewController: UIViewController,UIScrollViewDelegate, UITextFieldDelegate {
#IBOutlet weak var yourEmail: UITextField!
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
//setting portrait
AppUtility.lockOrientation(.portrait)
//hide keyboard when click outside
self.hideKeyboardWhenTappedAround()
//hide keyboard when click on return
self.yourEmail.delegate = self
self.scrollView.delegate = self
//boarder line for yourEmail
yourEmail.frame.size.height = UIScreen.main.fixedCoordinateSpace.bounds.size.width * CGFloat(0.05)
yourEmail.font = UIFont.italicSystemFont(ofSize: UIScreen.main.fixedCoordinateSpace.bounds.size.width * CGFloat(0.04))
bottomBoader(BottomLine: "UrEmailTextBottomLine", length: 1.0, yourTextBox: yourEmail)
yourEmail.applyCustomClearButton(yourTextBox: yourEmail)
registerForKeyboardNotifications()
deregisterFromKeyboardNotifications()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
AppUtility.lockOrientation(.portrait)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
AppUtility.lockOrientation(.all)
}
// *************************************************** moving textfiles when keyborad present ***********************************************************
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.yourEmail {
if (!aRect.contains(activeField.frame.origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
#objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
//self.scrollView.contentInset = UIEdgeInsets.zero
}
func textFieldDidBeginEditing( textField: UITextField){
yourEmail = textField
}
func textFieldDidEndEditing(textField: UITextField){
yourEmail = nil
}
The problem is you are registerForKeyboardNotifications() and then immediately deregisterFromKeyboardNotifications() so you aren't getting keyboard notifications. You should move the deregister to the deinit:
deinit {
deregisterFromKeyboardNotifications()
}
Edit
As #matt pointed out you don't need to deregisterFromKeyboardNotifications so just delete that code (including my suggestion of deinit)
Embedding your controls in a UITableView with static cells on a Storyboard will let the system take care of the scrolling for you.
hey bro why are call both the functions in viewDidLoad
registerForKeyboardNotifications()
deregisterFromKeyboardNotifications()
In viewDidLoad call only registerForKeyboardNotifications() and in deinit call deregisterFromKeyboardNotifications()
final solution that is working fine, I have copied it from stack overflow and tweak it little bit for my purpose:
var activeField: UITextField?
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
if activeField.frame.maxY > (scrollView.frame.height - keyboardSize!.height){
self.scrollView.setContentOffset(CGPoint.init(x: 0, y: activeField.frame.maxY - (scrollView.frame.height - keyboardSize!.height) + 20), animated: true)
} else {
return
}
print(activeField.frame.maxY)
print(scrollView.frame.height)
print(keyboardSize!.height)
print(scrollView.frame.height - keyboardSize!.height)
print(activeField.frame.maxY - (scrollView.frame.height - keyboardSize!.height) + 20)
}
}
#objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
im posting my full code here. the problem is when initially loading the app and the viewcontroller. it fully works. tap on the two textfields and the scrollview pushes up and keyboard is below the current textfield. but then if tapping out of the text field.. moving the the view up and retaping on the textfield it doesnt do it anymore. Also, if going back via nav controller and then loading again this viewcontroller, it wont do anything. it doesnt scroll anymore..( doesnt push the textfield up and keyboard goes below it anymore ) ...
import UIKit
import Parse
import Alamofire
import SwiftyJSON
class VCreservacion: UIViewController,UITextFieldDelegate,UIScrollViewDelegate {
var SUCURSALID = 0
var EMP_NOMBRE = ""
var DIRECCION = ""
var PROVINCIA = ""
var RESTID = 20556
#IBOutlet var lbl_empresa: UILabel!
#IBOutlet var lbl_direccion: UILabel!
#IBOutlet var lbl_step: UILabel!
#IBOutlet var cantidadView: UIView!
#IBOutlet var datePicker: UIDatePicker!
#IBOutlet var btn_reservar: UIButton!
#IBOutlet var stackView: UIStackView!
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var txtComentario: UITextField!
#IBOutlet weak var txtCelular: UITextField!
var activeField: UITextField?
var steps = 2
// MARK: RESERVE ACTION
#IBAction func ReserveAction(_ sender: UIButton) {
print("Reservando...")
// For date formater
var dateformated = ""
var dateformated2 = ""
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
//formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone!
dateformated = formatter.string(from: datePicker.clampedDate)
dateformated2 = formatter.string(from: datePicker.date)
print(dateformated)
print(dateformated2)
let cart = Cart.sharedInstance
guard let user = PFUser.current() else {
cart.showAlertView("Login", message: "Debes estar logeado para poder reservar.")
return
}
Alamofire.request("URL String", parameters: ["qty": "\(steps)","sucursalid":"\(self.SUCURSALID)","restid":"\(RESTID)","comment":"\(txtComentario.text!)","phone":"\(txtCelular.text!)","datetime":"\(dateformated)","action":"request","userid":"\(user.objectId!)"]).authenticate(usingCredential: cart.credential).responseJSON() {
response in
if (response.error != nil ) {
print(response.error.debugDescription)
print(response.request)
cart.showAlertView("Error", message: "there was an error.")
}
if(response.result.value != nil) {
let json = JSON(response.result.value!);
print(json);
let success:Bool = json["success"].boolValue
let error: Bool = json["error"].boolValue
if(success) {
print("con exito")
let alert = UIAlertController(title: "Reserva Enviada", message: "Tu reserva ha sido enviada y serĂ¡ revisada por el establecimiento", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
// Get the previous Controller.
let targetController: UIViewController = (self.navigationController?.viewControllers[self.navigationController!.viewControllers.count - 3])!
// And go to that Controller
self.navigationController?.popToViewController(targetController, animated: true)
}
alert.addAction(okAction)
self.present(alert,animated:true)
}
}
}
}
#IBAction func stepperValue(_ sender: UIStepper) {
self.lbl_step.text = Int(sender.value).description
steps = Int(sender.value)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerForKeyboardNotifications()
self.scrollView.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
deregisterFromKeyboardNotifications()
self.scrollView.delegate = nil
}
// MARK: Viewdidload
override func viewDidLoad() {
super.viewDidLoad()
// enable scroll on scrollview
self.scrollView.isScrollEnabled = true
// step label initial value 2
self.lbl_step.text = "2"
// Get celular or phone
if ( Cart.sharedInstance.User_celular != "") {
txtCelular.text = Cart.sharedInstance.User_celular
} else {
txtCelular.text = Cart.sharedInstance.User_phone
}
let nearesthour = Date().nearestHour()
self.datePicker.minimumDate = nearesthour
self.txtComentario.delegate = self
self.txtCelular.delegate = self
self.txtCelular.tag = 20
self.scrollView.delegate = self
// tap gesture recognizer
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
self.scrollView.addGestureRecognizer(tap)
print("el enarest hour es \(nearesthour as Date?) y el date normal es \(Date())")
self.btn_reservar.layer.cornerRadius = 10
self.cantidadView.layer.cornerRadius = 10
self.lbl_empresa.text = EMP_NOMBRE
self.lbl_direccion.text = DIRECCION
/*
print("VC Reservacion")
print("SUCURSAL \(SUCURSALID) ")
print("EMP NOMBRE " + EMP_NOMBRE)
print("DIRECCION " + DIRECCION)
*/
}
// MARK: TEXTFIELD STUFF
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeField = textField
return true
}
/*
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeField = textField
}
*/
func textFieldDidEndEditing(_ textField: UITextField) {
activeField = nil
}
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#objc func keyboardWasShown(notification: NSNotification){
//Need to calculate keyboard exact size due to Apple suggestions
print(" Keyboaard shown")
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
print(" el keyboardsize is \(keyboardSize)")
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height + 80, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
print("VIEW COMPLETE FRAME IS \(aRect)")
print("KEYBOARD FRAME HEIGHT \(keyboardSize!.height)")
aRect.size.height -= keyboardSize!.height
print("FRAME MENOS KEYBOARD ES \(aRect)")
print("SCROLLVIEW CONTENT \(self.scrollView.contentSize)")
if let activeField = self.activeField {
print("ACTIVEFIELD FRAME ORIGIN \(activeField.frame.origin) ")
print("Active field is textfield tag is \(activeField.tag)")
// if (!aRect.contains(activeField.frame.origin)){
print("arect Does Not contains activeField")
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
print("TEXTFIELD FRAME ES \(activeField.frame)")
print(" SCROLLVIEW CONTENT \(self.scrollView.contentSize)")
//}
}
}
#objc func keyboardWillBeHidden(notification: NSNotification){
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.activeField = nil
self.view.endEditing(true)
self.scrollView.isScrollEnabled = false
}
#objc func handleTap(_ sender: UITapGestureRecognizer) {
self.view.endEditing(true)
print("Tap")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSize(width: view.frame.width, height: view.frame.height)
print(" SCROLLVIEW CONTENT AFTER SUBVIEWS \(self.scrollView.contentSize)")
}
/* // NOT WORKING BECAUSE OF UISCROLLVIEW IN PLACE, MUST USE UITAPGESTURE RECOGNIZER
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
self.activeField?.resignFirstResponder()
}
*/
}
I had the same problem. Apparently there is a change in getting the size of the keyboard. I changed UIKeyboardFrameBeginUserInfoKey to UIKeyboardFrameEndUserInfoKey and got it to work again.
Here is my exact code for moving the view when the textfield is pressed
#objc func keyboardWasShown(notification: NSNotification){
self.scrollView.isScrollEnabled = true
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
guard let kbHeight = keyboardSize?.height else{return}
aRect.size.height -= kbHeight
if let activeField = self.activeTextField {
if (!aRect.contains(activeField.frame.origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
So I want to learn swift and I am making this simple chat application ... and I have some problems controlling the keyboard.
when the keyboard appears I want to push up the frame. If I wont do that I won't have access to my textfield. I found this two functions that are able to do that ... the problem is the devices screen aren't the same, and if i run the app on another device I have to change the size ...
For example if I use iPhon6 i will use a 220 and if I use a 5 it is necessary 150 ... if I remember right. The dimension doesn't matter, the thing it is that aren't the same...
I think it must be a way to easily control this future ... I'll appreciate any kind of help...
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
//hide keyboard and get down the view
func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y += 200
}
//show keyboard and get up the view
func keyboardWillShow(sender: NSNotification) {
self.view.frame.origin.y -= 200
}
//hide keyboard if you tap the screen
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
Thank you !
Add a ScrollView Try Below Code.
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var onTopScrollView: UIView!
var activeTextField: UITextField!
var keyboardHeight: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
//hide keyboard and get down the view
func keyboardWillHide(sender: NSNotification) {
keyboardHeight = 0
self.activeTextField = nil
let contentInsets = UIEdgeInsetsZero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
scrollView.contentOffset = CGPointMake(0, 0)
}
//show keyboard and get up the view
func keyboardWillShow(sender: NSNotification) {
let info : NSDictionary = sender.userInfo!
let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
keyboardHeight = kbSize.height
println(keyboardHeight)
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
var aRect = self.onTopScrollView.frame
aRect.size.height -= keyboardHeight;
if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
var rect = onTopScrollView.convertRect(CGRectZero, fromView: self.activeTextField)
rect.size = self.activeTextField.frame.size
//print(CGRectContainsPoint(aRect, self.activeTextField.frame.origin))
self.scrollView.scrollRectToVisible(rect, animated: true)
}
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
super.viewWillDisappear(animated)
}
// handle TextField Delegates
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
self.activeTextField = textField
}
i have a UITextField added by code, and when the keyboard is opened, it hides the textfield.
i searched a lot and got the same results and her is my code as apple documentation suggest, but still it is not working!
import Foundation
import UIKit
class testkey: UIViewController, UITextFieldDelegate {
var txt1: UITextField! = nil
var scrollView: UIScrollView! = nil
var activeTextField: UITextField!
override func viewDidLoad() {
txt1 = UITextField(frame: CGRect(x: 0, y:250, width: 223, height: 30))
txt1.text = "text"
txt1.borderStyle = UITextBorderStyle.RoundedRect
txt1.delegate = self
scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 225.00, height: 290));
scrollView.addSubview(txt1)
self.view.addSubview(scrollView)
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// Call this method somewhere in your view controller setup code.
func registerForKeyboardNotifications() {
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self,
selector: "keyboardWillBeShown:",
name: UIKeyboardWillShowNotification,
object: nil)
notificationCenter.addObserver(self,
selector: "keyboardWillBeHidden:",
name: UIKeyboardWillHideNotification,
object: nil)
}
// Called when the UIKeyboardDidShowNotification is sent.
func keyboardWillBeShown(sender: NSNotification) {
let info: NSDictionary = sender.userInfo!
let value: NSValue = info.valueForKey(UIKeyboardFrameBeginUserInfoKey) as NSValue
let keyboardSize: CGSize = value.CGRectValue().size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
let activeTextFieldRect: CGRect? = activeTextField?.frame
let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
}
}
// Called when the UIKeyboardWillHideNotification is sent
func keyboardWillBeHidden(sender: NSNotification) {
let contentInsets: UIEdgeInsets = UIEdgeInsetsZero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
func textFieldDidBeginEditing(textField: UITextField!) {
activeTextField = textField
scrollView.scrollEnabled = true
}
func textFieldDidEndEditing(textField: UITextField!) {
activeTextField = nil
scrollView.scrollEnabled = false
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.registerForKeyboardNotifications()
}
override func viewDidDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func textFieldShouldReturn(textField: UITextField!) -> Bool // called when 'return' key pressed. return NO to ignore.
{
textField.resignFirstResponder()
return true;
}
}
(Assuming the maths are correct) what you should use is UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey.
Please check the Documentation of Keyboard Notification User Info Keys
i found the missing part,
the following should be changed for the scroll view:
scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height));
scrollView.contentSize = self.view.frame.size;