키보드가 입력 필드를 덮는 경우에만 보기 위로 이동
iPhone용 입력화면을 만들려고 합니다.화면에는 다수의 입력 필드가 있습니다.대부분은 화면 상단에 표시되지만 두 개의 필드가 하단에 있습니다.사용자가 화면 하단의 텍스트를 편집하려고 하면 키보드가 팝업되고 화면이 가려집니다.이 때 화면을 위로 이동시킬 수 있는 간단한 솔루션을 찾았는데, 그 결과 사용자가 편집하려고 하면 화면이 항상 위로 이동하고 화면 상단의 필드가 손이 닿지 않는 곳으로 이동하게 됩니다.
하단 필드를 편집할 때만 화면을 이동시킬 수 있는 방법이 있습니까?
여기서 발견한 코드를 사용하고 있습니다.
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(sender: NSNotification) {
self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y += 150
}
이 문서에서는, Apple이 고객의 문제를 충분히 설명하고 있습니다.이 페이지의 샘플 코드(다음 주소)Listing 4-1
을 실시합니다.는 필요한 기능을 정확하게 수행하며, 현재 편집이 키보드 아래에 있어야 하는 경우에만 보기를 스크롤합니다.스크롤 Viiew vi vivivivi 。
변수 선언
var activeField: UITextField?
다음 메서드를 추가합니다.
func registerForKeyboardNotifications()
{
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications()
{
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification)
{
//Need to calculate keyboard exact size due to Apple suggestions
self.scrollView.scrollEnabled = true
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var 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 activeFieldPresent = activeField
{
if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
{
self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification)
{
//Once keyboard disappears, restore original positions
var info : NSDictionary = notification.userInfo!
var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
var 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.scrollEnabled = false
}
func textFieldDidBeginEditing(textField: UITextField!)
{
activeField = textField
}
func textFieldDidEndEditing(textField: UITextField!)
{
activeField = nil
}
를 View Controller로 .UITextFieldDelegate
초기화 방법에 대해 올바른 딜러를 설정합니다. §:
self.you_text_field.delegate = self
잊지 말고 해 주세요.registerForKeyboardNotifications
() 및 온뷰(Init)deregisterFromKeyboardNotifications
나가실 때
편집/갱신:Swift 4.2 구문
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, 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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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 (!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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 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
}
My 2 cents 입니다.
써보셨나요?https://github.com/hackiftekhar/IQKeyboardManager
Swift 또는 Objective-C 설치는 매우 간단합니다.
동작은 다음과 같습니다.
IQKeyboard Manager (Swift):- IQKeyboard Manager Swift는 코코아팟을 통해 이용할 수 있습니다.포드 파일에 다음 행을 추가합니다(#236).
pod 'IQKeyboardManagerSwift'
AppDelegate.swift에서는 IQKeyboardManagerSwift 프레임워크를 Import하여 IQKeyboardManager를 활성화합니다.
import IQKeyboardManagerSwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
IQKeyboardManager.sharedManager().enable = true
// For Swift 4, use this instead
// IQKeyboardManager.shared.enable = true
return true
}
}
그리고 그게 다예요.진정해요!
나에게 딱 맞는다고 생각한 것은, 다음과 같습니다.
func textFieldDidBeginEditing(textField: UITextField) {
if textField == email || textField == password {
animateViewMoving(true, moveValue: 100)
}
}
func textFieldDidEndEditing(textField: UITextField) {
if textField == email || textField == password {
animateViewMoving(false, moveValue: 100)
}
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
let movementDuration:NSTimeInterval = 0.3
let 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()
}
높이 값을 변경할 수도 있습니다.모든 텍스트 필드에 "if 문"을 사용하려면 이를 제거합니다.
TextView와 같이 사용자 입력이 필요한 모든 컨트롤에 사용할 수도 있습니다.
하단 필드를 편집할 때만 화면을 이동시킬 수 있는 방법이 있습니까?
비슷한 문제가 있어서 ScrollView를 사용하지 않고 키보드의 if 문을 사용하여 WillShow/Hide 메서드를 사용하지 않고 매우 간단한 해결책을 찾았습니다.
func keyboardWillShow(notification: NSNotification) {
if bottomText.editing{
self.view.window?.frame.origin.y = -1 * getKeyboardHeight(notification)
}
}
func keyboardWillHide(notification: NSNotification) {
if self.view.window?.frame.origin.y != 0 {
self.view.window?.frame.origin.y += getKeyboardHeight(notification)
}
}
텍스트 필드가 두 개밖에 없었기 때문에 이것은 나에게 좋은 해결책이었다.
전체 보기를 위로 이동: 특정 텍스트 필드(하단 텍스트)를 편집하는 경우에만
전체 뷰를 아래로 이동합니다. 보기가 원래 위치에 없는 경우에만
키보드가 표시될 때 이 확장자를 사용하여 UIView를 이동합니다.
extension UIView {
func bindToKeyboard(){
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
@objc func keyboardWillChange(_ notification: NSNotification){
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = endFrame.origin.y - beginningFrame.origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.frame.origin.y += deltaY
}, completion: nil)
}
}
그런 다음 뷰에서 뷰를 키보드에 바인딩했습니다.
UiView.bindToKeyboard()
대신 UITableViewController에 구현하지 않으시겠습니까?키보드는 텍스트 필드를 표시하지 않습니다.
Swift 4 (*갱신 완료) (확장판**)
- 하나의 용기에 단추를 추가하다
- 컨테이너의 하단 구속조건을 IBOutlet containerBtmConstrain과 연결합니다.
inViewDidLoad
self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain self.watchForKeyboard()
다음 확장자를 추가하다
import UIKit private var xoAssociationKeyForBottomConstrainInVC: UInt8 = 0 extension UIViewController { var containerDependOnKeyboardBottomConstrain :NSLayoutConstraint! { get { return objc_getAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC) as? NSLayoutConstraint } set(newValue) { objc_setAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) } } func watchForKeyboard() { NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown(notification:)), name:UIResponder.keyboardWillShowNotification, object: nil); NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:UIResponder.keyboardWillHideNotification, object: nil); } @objc func keyboardWasShown(notification: NSNotification) { let info = notification.userInfo! guard let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return } UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = -keyboardFrame.height self.view.layoutIfNeeded() }) } @objc func keyboardWillHide(notification: NSNotification) { UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = 0 self.view.layoutIfNeeded() }) } }
저는 Swift Lint를 사용하고 있는데, Swift Lint는 수용된 답변의 형식에 문제가 있었습니다.구체적으로는:
대장 앞에 공간이 없고, 강제 캐스팅이 없으며, UIEdgeInset(위: 등)을 선호합니다.UIEdgeInsetMake 대신.
Swift 3에 대한 업데이트 내용입니다.
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)
}
func keyboardWasShown(notification: NSNotification) {
//Need to calculate keyboard exact size due to Apple suggestions
scrollView?.isScrollEnabled = true
var info = notification.userInfo!
if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
scrollView?.contentInset = contentInsets
scrollView?.scrollIndicatorInsets = contentInsets
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
if let activeField = self.activeField {
if !aRect.contains(activeField.frame.origin) {
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
}
func keyboardWillBeHidden(notification: NSNotification) {
//Once keyboard disappears, restore original positions
var info = notification.userInfo!
if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize.height, right: 0.0)
scrollView?.contentInset = contentInsets
scrollView?.scrollIndicatorInsets = contentInsets
}
view.endEditing(true)
scrollView?.isScrollEnabled = false
}
func textFieldDidBeginEditing(_ textField: UITextField) {
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
activeField = nil
}
Swift: 어떤 textField가 표시되는지 확인함으로써 이 작업을 수행할 수 있습니다.
@objc func keyboardWillShow(notification: NSNotification) {
if self.textField.isFirstResponder == true {
self.view.frame.origin.y -= 150
}
}
@objc func keyboardWillHide(notification: NSNotification){
if self.textField.isFirstResponder == true {
self.view.frame.origin.y += 150
}
}
나는 이 조항이 틀렸다고 생각한다.
if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
activeField의 원점은 키보드 위에 있을 수 있지만 maxY는 그렇지 않을 수 있습니다.
activeField의 'max' 포인트를 만들고 그것이 Rect 키보드에 있는지 확인합니다.
Combine에서 이 작업을 수행하는 방법에 대한 답변이 없었기 때문에, 제가 사용한 접근방식은 다음과 같습니다.
- 알림, 표시 및 숨기기를 모두 듣기 위해 게시자를 만듭니다.
- .
userInfo
현재 액티브한 응답측이 포함되어 있는지 여부를 확인합니다.커버가 되어 있는 경우는, 키보드 프레임의 높이를 되돌립니다.return 0이 커버되지 않으면 프레임을 이동하지 않습니다.숨김 알림의 경우 0을 반환하기만 하면 됩니다.
private var keyboardHeightPublisher: AnyPublisher<CGFloat, Never> {
Publishers.Merge(
NotificationCenter.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect }
.map { $0.intersects(self.view.firstResponder!.frame) ? $0.height : 0 }
.map { $0 * -1 },
NotificationCenter.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ in CGFloat(0) }
).eraseToAnyPublisher()
}
서서 viewDidLoad
우리는 단지 출판사가 그에 따라 뷰 프레임을 변경하는 것을 구독할 뿐이다.
override func viewDidLoad() {
super.viewDidLoad()
keyboardHeightPublisher.sink{ [weak self] height in
self?.view.frame.origin.y = height
}.store(in: &cancelables)
}
★★★★
조심해!이 경우,firstResponder
서브뷰에서 화면 전체에 해당하는 프레임을 계산하여 실제로 교차하는지 확인해야 합니다.
§:
let myViewGlobalFrame = myView.convert(myView.frame, to: parentView)
다음은 Apple이 제공한 문서와 이전 게시물을 읽은 내 버전입니다.한 가지 깨달은 것은 키보드로 커버했을 때 textView가 처리되지 않았다는 것입니다.안타깝게도 어떤 이유로든 키보드는 textViewDidBeginEditing을 호출한 후에 호출되기 때문에 Apple의 문서는 작동하지 않습니다.키보드가 표시되는지, textView 또는 textField가 편집되고 있는지 여부를 확인하는 중앙 메서드를 호출하여 이 문제를 해결했습니다.이렇게 하면 두 조건이 모두 존재할 때만 프로세스가 실행됩니다.
textView의 또 다른 포인트는 키보드가 textView의 맨 아래를 클리핑하여의 왼쪽 상단 포인트가 표시되었을 경우 조정되지 않을 수 있다는 것입니다.따라서 제가 작성한 코드는 실제로 textView 또는 textField의 화면 참조 하단 왼쪽 지점을 취합하여 표시된 키보드의 화면 참조 좌표에 해당하는지 여부를 확인하여 키보드가 그 일부를 커버하고 있음을 나타냅니다.
let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY))) {
// scroll textView/textField into view
}
탐색 컨트롤러를 사용하는 경우 하위 클래스는 삽입에 대한 스크롤 보기 자동 조정도 false로 설정합니다.
self.automaticallyAdjustsScrollViewInsets = false
각 textView 및 textField를 통해 딜러가 처리하도록 설정합니다.
for view in self.view.subviews {
if view is UITextView {
let tv = view as! UITextView
tv.delegate = self
} else if view is UITextField {
let tf = view as! UITextField
tf.delegate = self
}
}
결과를 얻으려면 기본 클래스를 여기서 만든 하위 클래스로 설정하십시오.
import UIKit
class ScrollingFormViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {
var activeFieldRect: CGRect?
var keyboardRect: CGRect?
var scrollView: UIScrollView!
override func viewDidLoad() {
self.automaticallyAdjustsScrollViewInsets = false
super.viewDidLoad()
// Do any additional setup after loading the view.
self.registerForKeyboardNotifications()
for view in self.view.subviews {
if view is UITextView {
let tv = view as! UITextView
tv.delegate = self
} else if view is UITextField {
let tf = view as! UITextField
tf.delegate = self
}
}
scrollView = UIScrollView(frame: self.view.frame)
scrollView.scrollEnabled = false
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.addSubview(self.view)
self.view = scrollView
}
override func viewDidLayoutSubviews() {
scrollView.sizeToFit()
scrollView.contentSize = scrollView.frame.size
super.viewDidLayoutSubviews()
}
deinit {
self.deregisterFromKeyboardNotifications()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func registerForKeyboardNotifications()
{
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications()
{
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification)
{
let info : NSDictionary = notification.userInfo!
keyboardRect = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
adjustForKeyboard()
}
func keyboardWillBeHidden(notification: NSNotification)
{
keyboardRect = nil
adjustForKeyboard()
}
func adjustForKeyboard() {
if keyboardRect != nil && activeFieldRect != nil {
let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY)))
{
scrollView.scrollEnabled = true
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect!.size.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
scrollView.scrollRectToVisible(activeFieldRect!, animated: true)
}
} else {
let contentInsets : UIEdgeInsets = UIEdgeInsetsZero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
scrollView.scrollEnabled = false
}
}
func textViewDidBeginEditing(textView: UITextView) {
activeFieldRect = textView.frame
adjustForKeyboard()
}
func textViewDidEndEditing(textView: UITextView) {
activeFieldRect = nil
adjustForKeyboard()
}
func textFieldDidBeginEditing(textField: UITextField)
{
activeFieldRect = textField.frame
adjustForKeyboard()
}
func textFieldDidEndEditing(textField: UITextField)
{
activeFieldRect = nil
adjustForKeyboard()
}
}
훌륭한 답변이 이미 제공되고 있지만, 이것은 이 상황에 대처하기 위한 다른 방법입니다(Swift 3x 사용).
우선 다음 메서드를 호출합니다.viewWillAppear()
func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
, 그럼 이제 한 번 .IBOutlet
UIView
큰 UIViewcontroller
다음과 같습니다(이 서브뷰는 를 모두 대상으로 합니다).
@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!
그리고 다음과 같은 다른 변수, 즉 대리자를 추가합니다. UITextFieldDelegate
:
var activeTextField = UITextField() //This is to keep the reference of UITextField currently active
그 후, 여기에 마법의 파트가 표시됩니다.아래에 이 스니펫을 붙여 주세요.
func keyboardWasShown(_ notification: Notification) {
let keyboardInfo = notification.userInfo as NSDictionary?
//print(keyboardInfo!)
let keyboardFrameEnd: NSValue? = (keyboardInfo?.value(forKey: UIKeyboardFrameEndUserInfoKey) as? NSValue)
let keyboardFrameEndRect: CGRect? = keyboardFrameEnd?.cgRectValue
if activeTextField.frame.origin.y + activeTextField.frame.size.height + 10 > (keyboardFrameEndRect?.origin.y)! {
UIView.animate(withDuration: 0.3, delay: 0, options: .transitionFlipFromTop, animations: {() -> Void in
//code with animation
//Print some stuff to know what is actually happening
//print(self.activeTextField.frame.origin.y)
//print(self.activeTextField.frame.size.height)
//print(self.activeTextField.frame.size.height)
self.loginViewTopConstraint.constant = -(self.activeTextField.frame.origin.y + self.activeTextField.frame.size.height - (keyboardFrameEndRect?.origin.y)!) - 30.0
self.view.layoutIfNeeded()
}, completion: {(_ finished: Bool) -> Void in
//code for completion
})
}
}
func keyboardWillBeHidden(_ notification: Notification) {
UIView.animate(withDuration: 0.3, animations: {() -> Void in
self.loginViewTopConstraint.constant = self.view.frame.origin.y
self.view.layoutIfNeeded()
})
}
//MARK: textfield delegates
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
activeTextField = textField
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case YOUR_TEXTFIELD_ONE:
YOUR_TEXTFIELD_TWO.becomeFirstResponder()
break
case YOUR_TEXTFIELD_TWO:
YOUR_TEXTFIELD_THREE.becomeFirstResponder()
break
default:
textField.resignFirstResponder()
break
}
return true
}
이제 마지막 조각:
//Remove Keyboard Observers
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
UITextField
in 에 s있 sUIStoryboard
행운을 빕니다.
Swift 3 구문:
func textFieldDidBeginEditing(_ textField: UITextField) {
// add if for some desired textfields
animateViewMoving(up: true, moveValue: 100)
}
func textFieldDidEndEditing(_ textField: UITextField) {
// add if for some desired textfields
animateViewMoving(up: false, moveValue: 100)
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
textFieldDidEndEditing(_ textField: UITextField) {
let movementDuration:TimeInterval = 0.5
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()
}
이것은 원하는 것을 얻기 위한 좋은 방법입니다.특정 텍스트필드에 대해 "if" 조건을 추가할 수 있지만, 이 타입은 모든 사람에게 유효합니다.모두에게 도움이 되길 바랍니다.
먼저 활성 UITextField를 식별하는 변수를 선언합니다.
순서 1:-
var activeTextField: UITextField
스텝 2: 이 후 viewDidLoad에 이 두 줄을 추가합니다.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
순서 3:-
다음으로 컨트롤러 클래스에서 이들2개의 메서드를 정의합니다.
func keyboardWillShow(_ notification: NSNotification) {
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.activeField {
if (!aRect.contains(activeField.frame.origin)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
func keyboardWillHide(_ notification: NSNotification) {
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.endEditing(true)
self.scrollView.isScrollEnabled = true
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
4.2의 고속화를 실현합니다.
이것은 모든 양식에 적용됩니다.스크롤 뷰가 필요 없습니다. 대리인을 설정하는 것을 잊지 마십시오.
uitextfield를 만듭니다.
var clickedTextField = UITextField()
뷰에 로드되었습니까?
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);
클릭된 텍스트 필드를 확인합니다. 아마도 전체 화면에 텍스트 필드가 있을 것입니다.
func textFieldDidBeginEditing(_ textField: UITextField) {
clickedTextField = textField
}
키보드가 텍스트 필드를 커버하고 있는지 확인합니다.
@objc func keyboardWillShow(sender: NSNotification,_ textField : UITextField) {
if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if clickedTextField.frame.origin.y > keyboardSize.origin.y {
self.view.frame.origin.y = keyboardSize.origin.y - clickedTextField.center.y - 20
}
}
}
@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0
}
닫기 키보드로 돌아가기
func textFieldShouldReturn(_ textField: UITextField) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
업데이트 : NSNotification.Name.UIKeyboard Will Show 및 NSNotification.Name.UIKeyboardWillHide는 UIResponder로 이름이 변경됩니다.keyboardWillShowNotification 및 UIResponder.keyboardWillHideNotification이 표시됩니다.
스위프트 3
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var edtEmail: UITextField!
@IBOutlet var bottomTextfieldConstrain: NSLayoutConstraint! // <- this guy is the constrain that connect the bottom of textField to lower object or bottom of page!
@IBAction func edtEmailEditingDidBegin(_ sender: Any) {
self.bottomTextfieldConstrain.constant = 200
let point = CGPoint(x: 0, y: 200)
scrollView.contentOffset = point
}
@IBAction func edtEmailEditingDidEnd(_ sender: Any) {
self.bottomTextfieldConstrain.constant = 50
}
인정받은 앤서는 거의 완벽합니다.하지만 난 그걸 써야 해UIKeyboardFrameEndUserInfoKey
대신UIKeyboardFrameBeginUserInfoKey,
왜냐하면 후자는 키보드 높이 0을 반환하기 때문입니다.그리고 가장 히트한 지점을 원점이 아닌 맨 아래로 변경합니다.
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeField = self.activeField {
var point = activeField.frame.origin
point.y += activeField.frame.size.height
if (!aRect.contains(point)){
self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
}
}
Swift 4 솔루션 업데이트
키보드 쇼/숨김에 구속 애니메이션을 사용하여 즐기십시오.
import Foundation
import UIKit
class PhoneController: UIViewController, UITextFieldDelegate{
var phoneLayoutYConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
phoneField.delegate = self
view.addSubview(phoneField)
NSLayoutConstraint.activate([phoneField.heightAnchor.constraint(equalToConstant: 50),
phoneField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
phoneField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
phoneField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)])
phoneLayoutYConstraint = NSLayoutConstraint(item: phoneField, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
phoneLayoutYConstraint?.isActive = true
}
let phoneField: UITextField = {
let text = UITextField()
text.translatesAutoresizingMaskIntoConstraints = false
text.keyboardType = .numberPad
text.font = UIFont.systemFont(ofSize: 30)
text.layer.cornerRadius = 5.0
text.layer.masksToBounds = true
text.layer.borderColor = UIColor.darkGray.cgColor
text.layer.borderWidth = 2.0
return text
}()
override func viewDidDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
}
func textFieldDidEndEditing(_ textField: UITextField) {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
@objc func handleKeyBoardNotification(_ notification: NSNotification) {
if let info = notification.userInfo {
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let isKeyBoardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow
var aRect : CGRect = self.phoneField.frame
aRect.size.height -= keyboardSize!.height
phoneLayoutYConstraint?.constant = isKeyBoardShowing ? -keyboardSize!.height : 0
UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (boo) in
})
}
}
}
스위프트 4
쉽게 위아래로 이동할 수 있다UITextField
애니메이션이 포함된 키보드 포함
import UIKit
class ViewController: UIViewController {
@IBOutlet var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.resignFirstResponder()
}
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.origin.y - curFrame.origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.textField.frame.origin.y+=deltaY
},completion: nil)
}
스위프트 4.2
솔루션에서는 (수직으로) 뷰의 중심이UITextField
키보드 아래에 있는 경우.
순서 1: 새로운 swift 파일을 생성하여 복사 붙여넣기UIViewWithKeyboard
학급.
순서 2: Interface Builder에서 톱 클래스의 커스텀 클래스로 설정합니다.UIView
.
import UIKit
class UIViewWithKeyboard: UIView {
@IBInspectable var offsetMultiplier: CGFloat = 0.75
private var keyboardHeight = 0 as CGFloat
private weak var activeTextField: UITextField?
override func awakeFromNib() {
super.awakeFromNib()
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.textDidBeginEditing),
name: UITextField.textDidBeginEditingNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillShow),
name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillHide),
name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func textDidBeginEditing(_ notification: NSNotification) {
self.activeTextField = notification.object as? UITextField
}
@objc func keyboardWillShow(_ notification: Notification) {
if let frameValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
keyboardHeight = frameValue.cgRectValue.size.height
if let textField = self.activeTextField {
let offset = textField.frame.maxY < frame.maxY - keyboardHeight ? 0
: textField.frame.maxY - (frame.maxY - keyboardHeight) * offsetMultiplier
self.setView(offset: offset)
}
}
}
@objc func keyboardWillHide(_ notification: NSNotification) {
self.setView(offset: 0)
}
func setView(offset: CGFloat) {
UIView.animate(withDuration: 0.25) {
self.bounds.origin.y = offset
}
}
}
신속한 4.2를 위해 다시 작성
ViewDidLoad에서...
NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWasShown), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWillBeHidden), name: UIResponder.keyboardWillHideNotification, object: nil)
나머지 기능
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, 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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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 (!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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 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
}
"Swift에 처음 온다는 것을 깜빡했습니다. (이것을 체크하기 위한 올바른 구문은 무엇입니까?(이 함수의 필드명은 어떻게 취득합니까?)"
OK. 먼저 UITextFieldDelegate 프로토콜을 확인합니다.
class YourClass:UITextFieldDelegate
그런 다음 기능을 구현합니다.
func textFieldDidBeginEditing(textField: UITextField!) {
if textField == txtOne
{
println("TextOne")
}
if textField == txtTwo
{
println("TextTwo")
}
}
적절한 접근법은 스크롤뷰를 사용하여 스크롤뷰 내에서 위/아래로 이동해야 할 뷰를 배치하고 키보드이벤트를 적절하게 처리하는 것입니다.
이 코드는 편집 중인 텍스트 필드 위로 이동하므로 Swift 3에서 이 답변을 볼 수 있습니다. 또한 보기를 UITextFieldDelegate로 만들어야 합니다.
var moveValue: CGFloat!
var moved: Bool = false
var activeTextField = UITextField()
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
if moved == true{
self.animateViewMoving(up: false, moveValue: moveValue )
moved = false
}
}
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()
}
다음으로 viewDidLoad:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
호출(outside viewDidLoad):
func keyboardWillShow(notification: Notification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardSize.height
if (view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height < keyboardHeight{
moveValue = keyboardHeight - ((view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height)
self.animateViewMoving(up: true, moveValue: moveValue )
moved = true
}
}
}
Swift 4.2의 경우
이 코드를 사용하면 프레임의 Y축 모멘트를 특정 디바이스 화면 크기로 제어할 수 있습니다.
PS: 이 코드는 TextField 위치에 따라 프레임을 인텔리전트하게 이동하지 않습니다.
UIDevice 확장자를 만듭니다.
extension UIDevice {
enum ScreenType: String {
case iPhone4_4S = "iPhone 4 or iPhone 4s"
case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6s, iPhone 7 or iPhone 8"
case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6s Plus, iPhone 7 Plus or iPhone 8 Plus"
case iPhoneX_Xs = "iPhone X, iPhone Xs"
case iPhoneXR = "iPhone XR"
case iPhoneXSMax = "iPhone Xs Max"
case unknown
}
var screenType: ScreenType {
switch UIScreen.main.nativeBounds.height {
case 960:
return .iPhone4_4S
case 1136:
return .iPhones_5_5s_5c_SE
case 1334:
return .iPhones_6_6s_7_8
case 1920, 2208:
return .iPhones_6Plus_6sPlus_7Plus_8Plus
case 1792:
return .iPhoneXR
case 2436:
return .iPhoneX_Xs
case 2688:
return .iPhoneXSMax
default:
return .unknown
}
}
}
viewDidLoad에 NotificationObserver 추가
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 ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
if self.view.frame.origin.y == 0 {
switch (UIDevice.current.screenType.rawValue) {
case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
self.view.frame.origin.y -= 210
case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
self.view.frame.origin.y -= 110
case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
self.view.frame.origin.y -= 80
case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
self.view.frame.origin.y -= 70
case (UIDevice.ScreenType.iPhoneXR.rawValue):
self.view.frame.origin.y -= 70
case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
self.view.frame.origin.y -= 70
default:
self.view.frame.origin.y -= 150
}
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
if self.view.frame.origin.y != 0 {
switch (UIDevice.current.screenType.rawValue) {
case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
self.view.frame.origin.y += 210
case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
self.view.frame.origin.y += 110
case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
self.view.frame.origin.y += 80
case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
self.view.frame.origin.y += 70
case (UIDevice.ScreenType.iPhoneXR.rawValue):
self.view.frame.origin.y += 70
case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
self.view.frame.origin.y += 70
default:
self.view.frame.origin.y += 150
}
}
}
}
언급URL : https://stackoverflow.com/questions/28813339/move-a-view-up-only-when-the-keyboard-covers-an-input-field
'programing' 카테고리의 다른 글
iPhone 앱에서 iOS 7 상태 표시줄을 iOS 6 기본 스타일로 되돌리나요? (0) | 2023.04.23 |
---|---|
Visual Studio에서 생성된 Windows 서비스 설치 (0) | 2023.04.23 |
SQL에서 행을 무작위로 선택하는 방법 (0) | 2023.04.18 |
VBA에서 일부 시트 셀 데이터 옆에 프로그래밍 방식으로 버튼을 추가하는 방법은 무엇입니까? (0) | 2023.04.18 |
ItemsControl DataTemplate에서 캔버스 속성 설정 (0) | 2023.04.18 |