Text view up when keyboard appears swift - swift

I have textField and textView in the table. When editing textFiled, this code works and all text fields rise above the keyboard. When I edit a textView, nothing happens. It will help to edit the code so that for textView this code also works. Please do not offer third-party libraries. Thanks
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow(_:)),
name: UIResponder.keyboardWillShowNotification,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillHide(_:)),
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
}
#objc
fileprivate func keyboardWillShow(_ notification: Notification) {
let keyboardFrame = ((notification as NSNotification).userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue ?? CGRect.zero
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardFrame.height, right: 0.0)
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = contentInsets
UIView.animate(withDuration: 0.25) {
self.tableView.layoutIfNeeded()
self.view.layoutIfNeeded()
}
}
#objc
fileprivate func keyboardWillHide(_ notification: Notification) {
tableView.contentInset = .zero
}

yes you can!
all you need to do is knowing where you textfield position,
then set your scroll Offset
write this :
NotificationCenter.default.addObserver(self, selector: #selector(yourMethod(_:)), name: UITextField.textDidBeginEditingNotification, object: nil)
and your function
#objc func yourMethod(_ sender: NSNotification) {
if let tfActive = sender.object as? UITextField {
let frameRelatedToSuper = tfActive.convert(yourScrollView.contentOffset, to: nil)
//[mockTF convertPoint:self.parentScrollView.contentOffset toView:nil];
yourScrollView.setContentOffset(frameRelatedToSuper, animated: true)
}
}
the rest is your logic.
good luck
note: without adding additional height it might stopped on the top of your textfield
you can declare this
var padding: CGFloat = 10
padding = yourTF.bounds.height + padding
frameRelatedToSuper += padding
edit : the rest is your logic what i meant was ,because you need to calculate your keyboard height and add to framerelatedtosuper

Related

View above keyboard don't show up

I want to have a View with a textField an a send button above my keyboard, when the keyboard is shown. But this doesn't work.
I already implemented this in my code:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_ :)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tabBarController?.tabBar.isHidden = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
tabBarController?.tabBar.isHidden = false
}
// MARK: - Keyboard stuff
#objc func keyboardWillShow(_ notification: NSNotification) {
let keyboardFrame = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
print("hier ist \(keyboardFrame!)")
UIView.animate(withDuration: 0.1) {
self.bottomConstraint.constant = keyboardFrame!.height
self.view.layoutIfNeeded()
}
}
#objc func keyboardWillHide(_ notification: NSNotification) {
UIView.animate(withDuration: 0.1) {
self.bottomConstraint.constant = 0
self.view.layoutIfNeeded()
}
}
Check out textField inputAccessoryView. There's a tutorial here that explains what you're trying to do.

Keyboard height observer gives inacurate height

I'm using the observer below to determine my keyboard height.
I then use this keyboardHeight to adjust the bottom constraint for a UIView (image attached):
#IBOutlet weak var postViewBottomContraint: NSLayoutConstraint!
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}
and the method:
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
keyboardHeight = keyboardSize.height
print("Keyboard Height is:",keyboardHeight)
}
}
, and here is where I change the height:
func startEditing() {
UIView.animate(withDuration: 0.5) {
self.postViewBottomContraint.constant = self.keyboardHeight
print ("Bottom constraint is:",self.postViewBottomContraint.constant.description)
self.postTextView.textColor = UIColor.lightGray
self.view.layoutIfNeeded()
}
}
It adds a space between the keyboard and the UIView even though the keyboardHeight and the bottomConstraint are identical (in my case it is 253.0), is it adding something extra that is not visible or is there something else going on?

calculating keyboard height without using NSNotification in swift

I have a very small question - can we calculate the Keyboard Height with out using Notification. All the answers in stake overflow is using NSNotification but is there simpler way of calculating it?
below is the code:
NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil
#objc func keyboardWillShow(notification: ) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let kbHeight = keyboardSize.height
}
}
}
Code to use keyboard height in textFieldDidBeginEditing:
var kbHeight: CGFloat?
#objc func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
kbHeight = keyboardSize.height
}
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField.frame.maxY > self.kbHeight!
{
self.scrollView.setContentOffset(CGPoint.init(x: 0, y: textField.frame.maxY - (self.kbHeight! + 2.0)), animated: true)
}
else{
return
}
print(textField.frame.maxY)
print(self.view.frame.height * 0.6)
print(textField.frame.maxY - self.view.frame.height * 0.6)
}
func textFieldDidEndEditing(_ textField: UITextField)
{
self.scrollView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: true)
self.view.endEditing(true);
}
actually i don't have any idea for getting keyboard hight directly.. but you can save the keyboard height in variable when keyboard is present and use them where you want
Use these two Observers for keyboard and manage the keyboard hight
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
Must be remove these observer at dinit method when pop or dismiss the view controller.
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Selector methods for keyboard notification ...
#objc func keyboardWillShow(notification: NSNotification) {
var keyBoardHeight: CGFloat = 0
if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
keyBoardHeight = keyboardRectangle.height
}
}
#objc func keyboardWillHide(notification: NSNotification) {
}

move UITextField up when keyboard present

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
}

Move button when keyboard appears swift

In a UIViewController I have several text fields and a button is on the bottom of the UIViewController.
For the button, I have set a bottom constraint with a constant of 0.
Then I made an outlet from the bottom constraint to the UIViewController.
When I run my code, the button does not move upwards. I have seen suggestions on stackoverflow that I should add UIScrollView, but that means, I would have to delete all the objects on the UIViewController, put the UIScrollView and then put my objects on the UIVIewController again.
#IBOutlet weak var bottomConstraint: NSLayoutConstraint!
// When tapping outside of the keyboard, close the keyboard down
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
// Stop Editing on Return Key Tap. textField parameter refers to any textfield within the view
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// When keyboard is about to show assign the height of the keyboard to bottomConstraint.constant of our button so that it will move up
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize: CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
bottomConstraint.constant = keyboardSize.size.height
view.setNeedsLayout()
}
}
}
// When keyboard is hidden, move the button to the bottom of the view
func keyboardWillHide(notification: NSNotification) {
bottomConstraint.constant = 0.0
view.setNeedsLayout()
}
The typical way to address this would be to move the keyboard with code like this:
in ViewController class:
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.origin.y == 0{
let height = keyboardSize.height
self.view.frame.origin.y += height
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.origin.y != 0 {
let height = keyboardSize.height
self.view.frame.origin.y -= height
}
}
}
in ViewDidLoad method:
NotificationCenter.default.addObserver(self, selector: Selector("keyboardWillShow:"), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: Selector("keyboardWillHide:"), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
Please Read This:
The way you are trying to solve your problem is not allowed. In the code above, if you change view to your button variable name, the button will shoot up and then fall back down. This is because Auto Layout and Programmatic layout do not work together, it is one or the other. The way you fix this is by programmatically creating that button (with CGRect), then using the code above to move only that button on keyboard press. (Do that by changing view to your button variable name.
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if view.frame.origin.y == 0{
let height = keyboardSize.height
self.yourBtn.frame.origin.y += height
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if view.frame.origin.y != 0 {
let height = keyboardSize.height
self.yourBtn.frame.origin.y -= height
}
}
}
To programmatically create the button you would use code similar to this:
myButton.frame = CGRect(...)
Complimentary to Ryan's answer above, this can be done all with auto-layout and no need for frames and CGRect.
Swift 5
In your view, constrain your button as you normally would but add a reference to the constraint for modification when the keyboard hides/shows:
var bottomButtonConstraint = NSLayoutConstraint()
bottomButtonConstraint = yourButton.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -12)
bottomButtonConstraint.isActive = true
In your ViewController's viewDidLoad():
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
Also in your ViewController:
#objc private func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.yourCustomView.bottomButtonConstraint.constant -= keyboardSize.height
}
}
#objc private func keyboardWillHide(notification: NSNotification) {
self.yourCustomView.bottomButtonConstraint.constant = -12
}
You need add(viewDidLoad) observers to call your functions:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillShow), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillHide), name: UIKeyboardDidHideNotification, object: nil)
Consider using this pod: https://cocoapods.org/pods/IQKeyboardManager
In AppDelegate.swift, just import IQKeyboardManagerSwift framework and enable IQKeyboardManager.
import IQKeyboardManagerSwift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
IQKeyboardManager.shared.enable = true
return true
}
}