I am showing a popup in my view controller and the popup contains a tableview and a textfield so when I am clicking on textfield , my popup height remains same . so I want to reduce the height of my popup view when clicked on textfield. can anyone please help me out in this?
Just add two this line in viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
// keyboard delegates method implement
func keyboardWasShown(aNotification: NSNotification) {
print("Keyboard is active.")
// write your code that changes pop up frame.
}
func keyboardWillBeHidden(aNotification: NSNotification) {
print("Keyboard is hidden")
// write your code that changes pop up default frame.
}
You try this code add notification add notification
NotificationCenter.default.addObserver(self, selector: #selector(ClassName.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ClassName.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
Table automatic manage when keyboard appear
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
UIView.animate(withDuration: 0.5) {
var contentInsets:UIEdgeInsets
if (UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)) {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height - (self.tabBarController?.tabBar.frame.size.height)!), 0.0);
} else {
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.width - (self.tabBarController?.tabBar.frame.size.width)!), 0.0);
}
self.tableView.contentInset = contentInsets
self.tableView.scrollIndicatorInsets = self.tableView.contentInset
}
}
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.5) {
let contentInset:UIEdgeInsets = UIEdgeInsets.zero
self.tableView.contentInset = contentInset
}
}
Related
I have a Uiviewcontroller, in this viewcontroller I put a uiview called categUIV. The categUIV contains uitexfields and a button. The idea is to move the hole categUIV up when the keyboard is up.
I use the code below
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)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.categUIV.frame.origin.y -= keyboardSize.height
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.categUIV.frame.origin.y += keyboardSize.height
}
}
Now when I click to a uitextfied the keyboard pops up and categUIV pops up correctly, the problem is when I start typing the categUIV go back to his initial position by itself.
I don’t know why but i wonder is that maybe because of the constraints of categUIV?
The problem is with frame-layout things don't work as expected , Try autolayout , hook the bottom constraint of the categUIV as IBOutlet and do this
#objc func handleKeyboardDidShow (notification: NSNotification)
{
let keyboardRectAsObject = notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue
var keyboardRect = CGRect.zero
keyboardRectAsObject.getValue(&keyboardRect)
self.categUIVBotcon.constant = -1 * keyboardRect.height
UIView.animate(withDuration: 0.5,animations: {
self.view.layoutIfNeeded()
})
}
#objc func handleKeyboardWillHide(notification: NSNotification)
{
self.categUIVBotcon.constant = 0
UIView.animate(withDuration: 0.5,animations: {
self.view.layoutIfNeeded()
})
}
To make this work, you need to put your view into a scroll view so that your hierarchy looks like this:
- View Controller
- View
- Scroll View
- Content View
- categUIV
You must also connect the scroll view and the categUIV to your code:
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var categUIV: UIView!
You can then register your keyboard observers:
override func viewDidLoad() {
super.viewDidLoad()
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)
}
With the following functions:
func keyboardWasShown(notification: NSNotification) {
self.keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
self.scrollView.isScrollEnabled = true
let contentInsets = UIEdgeInsetsMake(0.0, 0.0, self.keyboardSize.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var rect = self.view.frame
rect.size.height -= self.keyboardSize.height
if !rect.contains(self.categUIV.frame.origin) {
self.scrollView.scrollRectToVisible(self.categUIV.frame, animated: true)
}
}
func keyboardWillBeHidden(notification: NSNotification) {
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
let contentInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize.height, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.scrollView.isScrollEnabled = false
}
I have a UIViewController with a container View. The container view's child is a static tableView. The last cell of the tableView has a text field. While working with only UITableViewController, tableViewController handled the movement of the tableView when text field was selected. Now, even though the keyboard appears, the tableView is not adjusting itself. Any solution?
You can use keyboard notification for scrolling the tableview up
// Keyboard
func registerForKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(keyboardWillShow),
name: UIKeyboardWillShowNotification,
object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(keyboardWillHide),
name: UIKeyboardWillHideNotification,
object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let keyboardHeight = keyboardSize.height
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0)
tableView.contentInset = contentInsets
tableView.scrollIndicatorInsets = contentInsets
}
}
}
func keyboardWillHide(notification: NSNotification) {
tableView.contentInset = UIEdgeInsetsZero
tableView.scrollIndicatorInsets = UIEdgeInsetsZero
}
them you call on viewDidLoad function
override func viewDidLoad() {
super.viewDidLoad()
registerForKeyboardNotifications()
}
This question was already asked here
Offset UITableView Content When Keyboard Appears
in objective C. I had tried to implement the accepted answer in Swift but in vain.
I have a TableView in which I want to offset the table view when the keyboard appears and I have wrote the code as follows -
In viewWillAppear()
self.automaticallyAdjustsScrollViewInsets = false
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
And then -
func keyboardWillShow(notification: NSNotification)
{
let contentInsets:UIEdgeInsets!
let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation)
{
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize!.height), 0.0)
}
else
{
contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize!.width), 0.0)
}
self.TableVieww.contentInset = contentInsets;
self.TableVieww.scrollIndicatorInsets = contentInsets;
TableVieww.scrollToRowAtIndexPath(self.editingIndexPath, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
}
But I am getting error as - value of type 'SearchVC' has no property 'editingIndexPath'.
EDIT: Adding in viewDidLoad code
So i had done some research to learn how to move one of my text views so that when the keyboard popped up, it scrolled the view up so that the keyboard was not covering the textview. I have seemed to be able to get that work, but now my issue is that after dismissing the keyboard, the view stays where it was. It does not 'snap' back to its original it was in position prior to the keyboard popping up and scrolling the textview out of the way. Am i missing something in my code? Or do i need to add something?
override func viewDidLoad() {
super.viewDidLoad()
self.questionInput.delegate = self
self.answerInput.delegate = self
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target:self, action: "DismissKeyboard")
view.addGestureRecognizer(tap)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardDidShow:", name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
var activeView: UITextView?
func textViewDidEndEditing(textView: UITextView) {
self.activeView = nil
}
func textViewDidBeginEditing(textView: UITextView) {
self.activeView = textView
}
func keyboardDidShow(notification: NSNotification) {
if let activeView = self.answerInput, keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
var aRect = self.view.frame
aRect.size.height -= keyboardSize.size.height
if (!CGRectContainsPoint(aRect, activeView.frame.origin)) {
self.scrollView.scrollRectToVisible(activeView.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification) {
let contentInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
}
My second question was i had read about needing to unregister for keyboard notifications this was the exact quote..
"Do not forget to unregister from these events when you are transitioning away from your view controller."
What exactly does this mean? Does code needed to be added when segueing?
Any help is appreciated as i am quite stuck with both these questions. Thank you.
If you're in the inital stage of the development you can use this library which will take care of keyboard handling throughout your project
https://github.com/hackiftekhar/IQKeyboardManager
regarding your second question here is the sample code that you'll need to implement
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);
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self);
}
If you use autolayout you need to implement this instead
func keyboardWasShown(notification: NSNotification) {
var info = notification.userInfo!
var keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.bottomConstraint.constant = keyboardFrame.size.height + 20
})
}
Try this
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
let insets: UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0, keyboardSize.height, 0)
self.scrollView.contentInset = insets
self.scrollView.scrollIndicatorInsets = insets
}
}
I have a scrollView that i want to scroll up when the keyboard is shown.
I have a crash with this error when the keyboard show :
2014-09-29 14:48:50.738 swrd[1563:472888] -[swrd.EditPhotoViewController keyboardWasShown]: unrecognized selector sent to instance 0x14ed36640
Here is my code, what's wrong ?:
func registerForKeyboardNotifications ()-> Void {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown", name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden", name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications () -> Void {
let center: NSNotificationCenter = NSNotificationCenter.defaultCenter()
center.removeObserver(self, name: UIKeyboardDidHideNotification, object: nil)
center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown (notification: NSNotification) {
let info : NSDictionary = notification.userInfo!
let keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.frame
let insets: UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0, keyboardSize!.height, 0)
self.scrollView.contentInset = insets
self.scrollView.scrollIndicatorInsets = insets
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, self.scrollView.contentOffset.y + keyboardSize!.height)
}
func keyboardWillBeHidden (notification: NSNotification) {
let info : NSDictionary = notification.userInfo!
let keyboardSize = info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.frame
let insets: UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0, keyboardSize!.height, 0)
self.scrollView.contentInset = insets
self.scrollView.scrollIndicatorInsets = insets
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
self.registerForKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
self.deregisterFromKeyboardNotifications()
}
In your code, keyboardWasShown and keyboardWasHidden each take an argument, the NSNotification. You need to terminate your selectors in addObserver with a colon so that it gets passed. I.e., keyboardWasShown and keyboardWasShown: are different selectors.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
See a self-contained solution below:
private func startObservingKeyboardEvents() {
NSNotificationCenter.defaultCenter().addObserver(self,
selector:Selector("keyboardWillShow:"),
name:UIKeyboardWillShowNotification,
object:nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector:Selector("keyboardWillHide:"),
name:UIKeyboardWillHideNotification,
object:nil)
}
private func stopObservingKeyboardEvents() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size {
let contentInset = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
}
}
}
func keyboardWillHide(notification: NSNotification) {
let contentInset = UIEdgeInsetsZero;
}
Use the contentInset variable to adjust the content insets.
In my case, was need some changes in the codes above:
1 - First you need put a Scrollview in your view, and set constraints like this:
It's important your scrollView be grater than view.
2 - Put your TextField's and other components you need.
3 - Link ScrollView to the ViewController with #IBOutlet
4 - Add the Delegate to ScrollView:
class ViewController: UIViewController, UITextFieldDelegate, UIScrollViewDelegate {
...
5 - Add the Observer's:
override func viewWillAppear(animated: Bool) {
self.startKeyboardObserver()
}
override func viewWillDisappear(animated: Bool) {
self.stopKeyboardObserver()
}
private func startKeyboardObserver(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil) //WillShow and not Did ;) The View will run animated and smooth
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
private func stopKeyboardObserver() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
6 - Add The code to scroll, calculating KeyboardSize.
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size {
let contentInset = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
self.scrollView.contentInset = contentInset
self.scrollView.scrollIndicatorInsets = contentInset
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, 0 + keyboardSize.height) //set zero instead self.scrollView.contentOffset.y
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size {
let contentInset = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInset
self.scrollView.scrollIndicatorInsets = contentInset
self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, self.scrollView.contentOffset.y)
}
}
}