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:
  • 315 Vote(s) - 3.57 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Move textfield when keyboard appears swift

#1
I'm using Swift for programing with iOS and I'm using this code to move the `UITextField`, but it does not work. I call the function `keyboardWillShow` correctly, but the textfield doesn't move. I'm using autolayout.

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);
}

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
//let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

var frame = self.ChatField.frame
frame.origin.y = frame.origin.y - keyboardSize.height + 167
self.chatField.frame = frame
println("asdasd")
}
}
Reply

#2
If you have more than one text field on the view, then I suggest that you look at this method. When switching between fields, you will not have a problem with the fact that the view runs away, it will simply adapt to the desired text field. It works in swift 5


override func viewDidLoad() {
super.viewDidLoad()
registerForKeyboardNotification()
}

All methods in extensions

extension StartViewController: UITextFieldDelegate {

func registerForKeyboardNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(sender:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(sender:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWillShow(sender: NSNotification) {
guard let userInfo = sender.userInfo,
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue,
let currentTextField = UIResponder.currentFirst() as? UITextField else { return }

let keyboardTopY = keyboardFrame.cgRectValue.origin.y
let convertedTextFieldFrame = view.convert(currentTextField.frame, from: currentTextField.superview)
let textFieldBottomY = convertedTextFieldFrame.origin.y + convertedTextFieldFrame.size.height

if textFieldBottomY > keyboardTopY {
let textBoxY = convertedTextFieldFrame.origin.y
let newFrameY = (textBoxY - keyboardTopY / 2) * -1
view.frame.origin.y = newFrameY
}
}


@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0
}


func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case emailTextField :
passwordTextField.becomeFirstResponder()
default:
emailTextField.becomeFirstResponder()
}
return true
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches , with:event)
view.endEditing(true)
}
}

At the end we set up the method with UIResponder

extension UIResponder {
private struct Static {
static weak var responder: UIResponder?
}

static func currentFirst() -> UIResponder? {
Static.responder = nil
UIApplication.shared.sendAction(#selector(UIResponder._trap), to: nil, from: nil, for: nil)
return Static.responder
}

@objc private func _trap() {
Static.responder = self
}
}
Reply

#3
For anyone not using storyboards to set the layout constraint. This is a pure programmatic way to get it working on Swift 5:

1. Define an empty constraint in your viewController. In this case, I am building a chat app that has a UIView containing text view at the very bottom of the screen.

```
var discussionsMessageBoxBottomAnchor: NSLayoutConstraint = NSLayoutConstraint()
```

2. In viewDidLoad add the constraints for the bottom-most view. In this case `discussionsMessageBox`. Also, add the listener for keyboard events.

*For correctly initializing the constraint, you need to first add the subview and then define the constraint.*

```
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotification(notification:)),
name: NSNotification.Name.UIKeyboardWillChangeFrame,
object: nil)

view.addSubview(discussionsMessageBox)

if #available(iOS 11.0, *) {
discussionsMessageBoxBottomAnchor = discussionsMessageBox.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
} else {
// Fallback on earlier versions
discussionsMessageBoxBottomAnchor = discussionsMessageBox.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)
}

NSLayoutConstraint.activate([ discussionsMessageBoxBottomAnchor ])

```

3. Define `deinit`.

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

4. Next add the code that @JosephLord defined, with one correction to fix offset math.

```
extension DiscussionsViewController {
@objc func keyboardNotification(notification: NSNotification) {
guard let userInfo = notification.userInfo else { return }

let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)

if endFrameY >= UIScreen.main.bounds.size.height {
self.discussionsMessageBoxBottomAnchor.constant = 0.0
} else {
//Changed line
self.discussionsMessageBoxBottomAnchor.constant = -1 * (endFrame?.size.height ?? 0.0)
}

UIView.animate(
withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}
}
```



Reply

#4
A `Swift 5` solution for [frédéric-adda][1] :

``` import UIKit

protocol KeyboardHandler: class {
var bottomConstraint: NSLayoutConstraint! { get set }

func keyboardWillShow(_ notification: Notification)
func keyboardWillHide(_ notification: Notification)
func startObservingKeyboardChanges()
func stopObservingKeyboardChanges()
}


extension KeyboardHandler where Self: UIViewController {

func startObservingKeyboardChanges() {

// NotificationCenter observers
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}

// Deal with rotations
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}

// Deal with keyboard change (emoji, numerical, etc.)
NotificationCenter.default.addObserver(forName: UITextInputMode.currentInputModeDidChangeNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}

NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillHide(notification)
}
}


func keyboardWillShow(_ notification: Notification) {

let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard

guard let value = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardHeight = value.cgRectValue.height

// Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that's out of this scope.
self.bottomConstraint.constant = keyboardHeight + verticalPadding

UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}


func keyboardWillHide(_ notification: Notification) {
self.bottomConstraint.constant = 0

UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}


func stopObservingKeyboardChanges() {
NotificationCenter.default.removeObserver(self)
}
}
```

In any `UIViewController`:

- Conform to `KeyboardHandler` protocol
```
extension AnyViewController: KeyboardHandler {}
```

- Add bottom constraint for the last-bottom element on the screen.

```
@IBOutlet var bottomConstraint: NSLayoutConstraint!
```

- Add Observer subscribe/unsubscribe:

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

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

Enjoy!


[1]:

[To see links please register here]

Reply

#5
There are a couple of improvements to be made on the existing answers.

Firstly the **UIKeyboardWillChangeFrameNotification** is probably the best notification as it handles changes that aren't just show/hide but changes due to keyboard changes (language, using 3rd party keyboards etc.) and rotations too (but note comment below indicating the keyboard will hide should also be handled to support hardware keyboard connection).

Secondly the animation parameters can be pulled from the notification to ensure that animations are properly together.

There are probably options to clean up this code a bit more especially if you are comfortable with force unwrapping the dictionary code.


class MyViewController: UIViewController {

// This constraint ties an element at zero points from the bottom layout guide
@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotification(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
guard let userInfo = notification.userInfo else { return }

let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)

if endFrameY >= UIScreen.main.bounds.size.height {
self.keyboardHeightLayoutConstraint?.constant = 0.0
} else {
self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
}

UIView.animate(
withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}
}
Reply

#6
For moving your view while editing textfield try this , I have applied this ,

**Option 1 :- ** **Update in Swift 5.0 and iPhone X , XR , XS and XS Max**
Move using NotificationCenter

- Register this Notification in `func viewWillAppear(_ animated: Bool)`

- Deregister this Notification in `func viewWillDisappear(_ animated: Bool)`

**Note:- If you will not deregister than it will call from child class and will reason of crashing or else.**

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil )
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc func keyboardWillShow( notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
var newHeight: CGFloat
let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
if #available(iOS 11.0, *) {
newHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
} else {
newHeight = keyboardFrame.cgRectValue.height
}
let keyboardHeight = newHeight + 10 // **10 is bottom margin of View** and **this newHeight will be keyboard height**
UIView.animate(withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: {
self.view.textViewBottomConstraint.constant = keyboardHeight **//Here you can manage your view constraints for animated show**
self.view.layoutIfNeeded() },
completion: nil)
}
}



**Option 2 :-**
Its work fine

func textFieldDidBeginEditing(textField: UITextField) {
self.animateViewMoving(up: true, moveValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
self.animateViewMoving(up: false, moveValue: 100)
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
var movementDuration:NSTimeInterval = 0.3
var movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration )
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}

I got this answer from this source **[UITextField move up when keyboard appears in Swift**][1]


[1]:

[To see links please register here]





IN the Swift 4 ---



func textFieldDidBeginEditing(_ textField: UITextField) {
animateViewMoving(up: true, moveValue: 100)
}

func textFieldDidEndEditing(_ textField: UITextField) {
animateViewMoving(up: false, moveValue: 100)
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
let movementDuration:TimeInterval = 0.3
let movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration )
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}





Reply

#7
Complete code for managing keyboard.


override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
guard let userInfo = notification.userInfo else {return}
guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {return}
let keyboardFrame = keyboardSize.cgRectValue

if self.view.bounds.origin.y == 0{
self.view.bounds.origin.y += keyboardFrame.height
}
}


@objc func keyboardWillHide(notification: NSNotification) {
if self.view.bounds.origin.y != 0 {
self.view.bounds.origin.y = 0
}
}
Reply

#8
A simple solution is to move view up with constant of keyboard height.

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);
}

@objc func keyboardWillShow(sender: NSNotification) {
self.view.frame.origin.y = -150 // Move view 150 points upward
}

@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0 // Move view to original position
}


**Swift 5:**

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(sender:)), name: UIResponder.keyboardWillShowNotification, object: nil);

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(sender:)), name: UIResponder.keyboardWillHideNotification, object: nil);
Reply

#9
Very Simple and no need to code more.
Just add `pod 'IQKeyboardManagerSwift'` in your podfile, and in your `AppDelegate` page add code below.


import IQKeyboardManagerSwift

and in method `didFinishLaunchingWithOptions()` type

IQKeyboardManager.shared.enable = true

that is it.
check this video link for better understanding
Hope this will help you.
Reply

#10
Here is a generic solution for all TextField
Steps -

1) Create a common ViewController that is extended by other ViewControllers

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= getMoveableDistance(keyboarHeight: keyboardSize.height)
}
}
}

@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
deinit {
NotificationCenter.default.removeObserver(self)
}

//get the distance to move up the main view for the focus textfiled
func getMoveableDistance(keyboarHeight : CGFloat) -> CGFloat{
var y:CGFloat = 0.0
if let activeTF = getSelectedTextField(){
var tfMaxY = activeTF.frame.maxY
var containerView = activeTF.superview!
while containerView.frame.maxY != self.view.frame.maxY{
let contViewFrm = containerView.convert(activeTF.frame, to: containerView.superview)
tfMaxY = tfMaxY + contViewFrm.minY
containerView = containerView.superview!
}
let keyboardMinY = self.view.frame.height - keyboarHeight
if tfMaxY > keyboardMinY{
y = (tfMaxY - keyboardMinY) + 10.0
}
}

return y
}

2) Create a extension of UIViewController and the currently active TextField

//get active text field
extension UIViewController {
func getSelectedTextField() -> UITextField? {

let totalTextFields = getTextFieldsInView(view: self.view)

for textField in totalTextFields{
if textField.isFirstResponder{
return textField
}
}

return nil

}

func getTextFieldsInView(view: UIView) -> [UITextField] {

var totalTextFields = [UITextField]()

for subview in view.subviews as [UIView] {
if let textField = subview as? UITextField {
totalTextFields += [textField]
} else {
totalTextFields += getTextFieldsInView(view: subview)
}
}

return totalTextFields
}
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

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