Swift'i kullanarak görünümü klavyeyle taşıma


278

Ben görünümün alt yarısında bir metin alanı olan bir uygulama var. Bu, metin alanına yazmaya gittiğimde klavyenin metin alanını kapladığı anlamına gelir.

Yazarken neyi yazdığımı görebilmem ve sonra klavye kaybolduğunda görüntüyü orijinal yerine geri getirebilmem için görünümü yazarken nasıl hareket ettiririm?

Her yere baktım, ancak tüm çözümler henüz tam olarak dönüşemediğim Obj-C'de görünüyor.

Herhangi bir yardım büyük mutluluk duyacağız.


Bunu yapmanın en iyi yolu, içeriğinizi bir UIScrollView içine yerleştirmek , ardından kaydırma görünümünün contentInset özelliğini gösterildiğinde klavyenin yüksekliğine göre ayarlamaktır . Kesinlikle klavye yüksekliğini varsaymayın - "klavye gösterilecek" bildirimindeki değeri kullanın.
nielsbot

1
Aslında, Apple dokümanları bunu "Klavyeyi Yönetme" altında nasıl yapacağınızı söyler: developer.apple.com/library/ios/documentation/StringsTextFonts/…
nielsbot

11
Aşağıdaki tüm cevapların tek bir durumu dikkate almadığını düşünüyorum: Birden fazla metin alanınız varsa ve bazıları ekranın üst kısmındaysa ne olur? Her zaman kullanıcı bu it is actually needed to scroll view up when keyboard appears
metin alanına dokunur

Bu yanıt, şu anda düzenlenmekte olan
metin

Yanıtlar:


710

İşte bir textField öğesinden diğerine geçiş yapmadan bir çözüm:

 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?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y -= keyboardSize.height
    }            
}

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

Bu sorunu çözmek için, iki işlevi aşağıdakilerle değiştirin keyboardWillShow/Hide:

func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

func keyboardWillHide(notification: NSNotification) {
    if view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

SWIFT 3.0 İÇİN DÜZENLE:

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

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

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

SWIFT 4.0 İÇİN DÜZENLEME:

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

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

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

SWIFT 4.2 İÇİN DÜZENLEME:

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.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

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

56
Kullanıcı klavye varken başka bir metin alanına dokunursa, görünüm daha da yukarı itilir ve bu da siyah bir alana (klavyenin boyutu) neden olur - klavyenin mevcut olup olmadığını izleyen bir değişkene sahip olarak bunu düzeltmemiz gerekir. . Örneğin keyboardPresent == true ise görünüm kaynağını vb.
taşımayın

3
@Matthew Lin boolean kullanır, böylece keyboardWillShow and hide sadece bir kez çalışır
iluvatar_GR

11
Sadece bir öneri, böylece benim yaptığım gibi çok hata ayıklamak zorunda değilsiniz. Aynı ekranda birden fazla uitextfield varsa, klavye boyutu değişebilir (ayarlarınıza bağlı olarak bazı girişler için öneriler göstermez), bu nedenle her seferinde self.view.frame.origin.y = 0 ayarlamanız önerilir klavyeyi kapatıyorsunuz. Örneğin, e-posta metin alanınız için gerekli testleri gösterir, böylece klavye boyutu artar ve şifre alanı için öneriler göstermez, böylece klavye boyutu azalır.
Vandan Patel

36
Klavye boyutunu elde etmek UIKeyboardFrameEndUserInfoKeyyerine kullanmak zorundasınız UIKeyboardFrameBeginUserInfoKey. Şu anda neden olduğundan emin değilim, ancak birincisi daha tutarlı sonuçlar verecek.
jshapy8

3
Yerine lütfen UIKeyboardFrameBeginUserInfoKeyile UIKeyboardFrameEndUserInfoKey. Birincisi klavyenin bazen sıfır gelen başlangıç ​​karesini verirken ikincisi klavyenin bitiş karesini verir.
Arnab

90

Herhangi bir kod gerektirmeyen en kolay yol:

  1. Zaten Spring animasyon çerçevesini kullanmıyorsanız, KeyboardLayoutConstraint.swift dosyasını indirin ve dosyayı projenize ekleyin (sürükleyip bırakın).
  2. Film şeridinizde Görünüm veya Metin Alanı için bir alt sınır oluşturun, kısıtlamayı seçin (çift tıklayın) ve Kimlik Denetçisinde sınıfını NSLayoutConstraint yerine KeyboardLayoutConstraint olarak değiştirin.
  3. Bitti!

Nesne, senkronize olarak klavyeyle otomatik olarak yukarı taşınır.


4
Alt kısıtlamayı seçmek için Boyut Denetçisi'ne de gidebilir, ardından listedeki kısıtlamaya çift tıklayabilirsiniz - raywenderlich.com/wp-content/uploads/2015/09/…
gammachill

3
Bu benim için mükemmel çalıştı. kelimenin tam anlamıyla 2 adımlı bir işlemdir. 1. KeyboardLayoutConstraint.swift öğesini ekleyin, 2. Film şeridinde görünüm veya metin alanı için bir alt sınır oluşturun. NOT: Kısıtlamalarımı sildim ve görünümün veya metin alanının altına sadece 1 kısıtlama ekledim ve sınıfını NSLayoutConstraint yerine KeyboardLayoutConstraint olarak değiştirdim. Sonra yukarıdaki görünümler / metin alanları vb. Ben sadece bu öğeden tek bir KeyboardLayoutConstraint ile öğeye kısıtlamalar bağladım ve sonuç tüm öğeler Key Board Göründüğünde / Kaybolurken yukarı / aşağı hareket ettirildi
Brian

4
Bu en iyi çözümdür, sağlanan kod, animasyonun uzunluğu veya eğrisi veya klavyenin boyutu gibi değerleri kodlamaz. Bunu anlamak da kolaydır.
miguelSantirso

3
Bu benim için çalışıyor, ancak klavyenin üst kısmı ve scrollView'imin alt kısmı arasında fazladan 50 piksel boşluk var. Ben kullanıyorum Güvenli Alan alt kısıtlama nedeniyle olup olmadığını merak ediyorum. Herkes bununla karşılaşır mı?
Clifton Labrum

1
Bu harika bir cevaptı. Çok güzel tasarım. Bir öneri: Metin görünümleriniz / metin alanlarınız tablo görünümü hücrelerinde ise, bu kısıtlamaya sahip görünümlerin kullanıcı her tıkladığında ve bir sonraki metin alanına gittiğinde garip bir şekilde atlayacağını fark edebilirsiniz. DispatchQueue.main.async {}Düzeltmek için animasyonları sarın . İyi iş! Başparmak havaya!
19:33, ScottyBlades

68

Bu konudaki popüler cevaplardan biri aşağıdaki kodu kullanır:

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

Görünümünüzü statik bir miktarda dengelemede bariz bir sorun var. Bir cihazda güzel görünecek, ancak diğer boyut yapılandırmalarında kötü görünecektir. Klavyelerin yüksekliğini almanız ve bunu ofset değeriniz olarak kullanmanız gerekir.

İşte size bir çözüm tüm cihazlarda çalışan ve kullanıcının yazarken metin tahmini alanını gizlediği kenar durumunu işleyen .

Çözüm

Aşağıda not etmek önemlidir, self.view.window'u nesne parametremiz olarak geçiriyoruz. Bu bize klavyemizden yüksekliği gibi veriler sağlayacaktır!

@IBOutlet weak var messageField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}

func keyboardWillHide(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    self.view.frame.origin.y += keyboardSize.height
}

Tüm cihazlarda güzel görünmesini sağlayacağız ve kullanıcının tahmini metin alanını eklediği veya çıkardığı durumu ele alacağız.

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y -= keyboardSize.height
        })
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
}

Gözlemcileri Kaldır

Gereksiz mesajların iletilmesini önlemek için görünümden ayrılmadan önce gözlemcilerinizi kaldırmayı unutmayın.

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}

Yorumlardan gelen soruya göre güncelleme:

İki veya daha fazla metin alanınız varsa, view.frame.origin.y dosyanızın sıfır olup olmadığını kontrol edebilirsiniz.

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!

    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        if self.view.frame.origin.y == 0 {
            UIView.animateWithDuration(0.1, animations: { () -> Void in
                self.view.frame.origin.y -= keyboardSize.height
            })
        }
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
     print(self.view.frame.origin.y)
}

1
birden fazla metin alanıyla uğraşırken, görünüm yukarı hareket etmeye devam eder ve geri gelmez
Mugunthan Balakrishnan

Metin alanlarını hesaba katmak için koşullarınızı değiştirmeniz gerekecek
Dan Beaulieu

cevap için teşekkürler, ben yığın taşması bu konu arıyordu cevabı buldum stackoverflow.com/questions/1126726/…
Mugunthan Balakrishnan

@MugunthanBalakrishnan bunu getirdiğin için teşekkürler, bir çözüm ekledim.
Dan Beaulieu

Merhaba arkadaşlar, bir hata var. ViewWillDisappear içinde çağrıldıktan sonra gözlemciler görünümden kaldırılmaz. Bu satırı "NSNotificationCenter.defaultCenter (). RemoveObserver (self, name: UIKeyboardWillHideNotification, object: self.view.window)" ile "NSNotificationCenter.defaultCenter (). RemoveObserver (self, name: UIKeyboardWillHideNotification, object: nil)" ile değiştirin kaldırıldı
rudald

29

Bunu görünüm denetleyicinize ekleyin. Tıkır tıkır çalışıyor. Sadece değerleri ayarlayın.

override func viewDidLoad() {
    super.viewDidLoad()        
    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);
}

@objc func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

Bu benim için çalışıyor. Ancak biraz sarsıntılı. Bunu smoothley yukarı taşımak için nasıl alabilirim? ayrıca bunu şu anda herkes için yaptığı gibi metin alanlarından birine uygulamanın bir yolu var. :(
DannieCoderBoi

2
"Otomatik Yerleşim" ile çalışmayabilir, öyleyse devre dışı bırakmayı düşünün.
Teodor Ciuraru

1
Autolayout @Josh ile bazı korkak davranışlara neden oluyor, yanılıyorsunuz
Mike

5
Bunu yapma! Klavyenin belirli bir boyutta olduğunu varsayamazsınız.
nielsbot

2
KeyboardSize kullanmalısınız. Cihazlarda aksesuar görünümleriniz ve farklı klavye yükseklikleriniz olduğunda ne olur? Müstakil klavye?
xtrinch

25

Bir sayfada farklı klavyeler ve farklı metin görünümleri / alanlarıyla çalışmasını sağlamak için cevaplardan birini biraz geliştirdim:

Gözlemci ekle:

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

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

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

func keyboardWillHide() {
    self.view.frame.origin.y = 0
}

func keyboardWillChange(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if YOURTEXTVIEW.isFirstResponder {
            self.view.frame.origin.y = -keyboardSize.height
        }
    }
}

Gözlemcileri kaldırın:

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

    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

3
bu çözüm kabul edilen cevaptan daha iyi sonuç verir. Kabul edilen cevap, klavyenin sadece bir kez hata olduğunu gösterir :)
Masih

Bu, Xcode 10.1 ve iOS 12 için geçerlidir. Kabul edilen cevap artık geçerli değil.
zeeshan

Bu mükemmel bir cevap, ekleyeceğim tek şey, yeni cihazlarda (X, XS, vb.) Alt güvenli alanı takip etmektir, böylece bunu açıklar.
Munib

@Munib Bkz. Stackoverflow.com/a/54993623/1485230 Diğer sorunlar görünümün canlandırılmamasını ve klavye yükseklik değişikliğinin izlenmemesini içerir.
Antzi

textField'ım görünümün en üstündeyse ne olur? yani kaynak Y = 0 ile metin alanı varsa .. ?? sonra textField yukarı gidiyor ve göremiyorum
Saifan Nadaf

19

Bir reklam veya promosyon veya spam değil , sadece iyi bir çözüm. Bu sorunun yaklaşık 30 cevabı olduğunu biliyorum ve o kadar şok oldum ki, kimse sizin için her şeyi ve daha iyisini yapan bu güzel GitHub projesi hakkında bir kez bile bahsetmedi . Tüm cevaplar görünümü yukarı taşır. Bu sorunları IQKeyboardManager ile çözdüm. 13000+ yıldıza sahiptir.
Hızlı kullanıyorsanız, bunu pod dosyasına ekleyin

pod 'IQKeyboardManagerSwift'

ve sonra AppDelegate.swift yapın import IQKeyboardManagerSwift

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

      IQKeyboardManager.shared.enable = true // just add this line

      return true
    }
}

IQKeyboardManager.shared.enable = trueEtkinleştirmek için hattı ekleyin
Üretim için gidiyorsanız bu çözüm bir zorunluluktur.


Bu gerçekten iyi, ama en son sürüm benim için çalışmıyor, 6.2.1 import IQKeyboardManagerkullandım IQKeyboardManager.shared().isEnabled = trueve AppDelegate
K

2
Ve çoklu düzenleme metinleri kullanırken bu çok işe yarıyor, Bu benim zaman tasarrufu
Dhanu K

1
Bu harika kütüphaneye işaret ettiğiniz için teşekkür edemem. Bu kütüphane nihayet Apple'ın hiçbir zaman çözüm sunmadığı klavyeyle ilgili tüm saçmalıkların sonuncusu. Şimdi yeni ve eski tüm projelerim için kullanacağım ve bu klavyenin ortaya çıktığı, kaybolup kaybolmadığı veya nasıl gizleneceği ve neden çakıştığı zaman ve baş ağrısından tasarruf edeceğim. gün iPhone'lar için program yapıyorum.
zeeshan

1
Buradaki diğer çözümler gibi, metin alanını taşımak için kendi kodumu yazmıştım. IQKeyboardManager'ın çok iyi olduğunu gördüm ve bundan sonra da dahil edeceğim. Çerçevenin güncel tutulmaması durumunda kodumu kullanışlı tutacaktır.
TM Lynch

@DhanuK, Sadece bu kütüphaneyi buldum ve mükemmel çalışıyor ve zahmetsiz. Uygulama temsilci kodu IQKeyboardManager.shared.enable = true olarak güncellendi
adougies

15

Siyah Ekran Hatası için (Swift 4 ve 4.2) .

Siyah ekran sorununu çözdüm. Doğrulanmış çözümde Dokunduktan sonra klavye yüksekliği değişir ve bu siyah ekrana neden olur.

Kullanmak zorunda UIKeyboardFrameEndUserInfoKey yerine UIKeyboardFrameBeginUserInfoKey

var isKeyboardAppear = false

override func viewDidLoad() {
    super.viewDidLoad() 
    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)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if !isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0{
                self.view.frame.origin.y -= keyboardSize.height
            }
        }
        isKeyboardAppear = true
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y != 0{
                self.view.frame.origin.y += keyboardSize.height
            }
        }
         isKeyboardAppear = false
    }
}

Bir sekme çubuğu varsa çalışmaz. Sekme yüksekliğini hesaplamanız gerekir, aksi takdirde klavye ve görünüm arasında siyah bir ekran boşluğu olacaktır.
Ankur Lahiry

Bu, klavyenin iPhone X ve daha yenisinde olduğu siyah alanı düzeltmez. Ve klavye her göründüğünde ve kaybolduğunda ana görünüm aşağı kayar.
Edison

14

Görüyorum ki tüm cevaplar görünümü klavye yüksekliğinin değerine göre değiştiriyor. Kısıtlı bir cevabım var, kısıtlamalar kullanıyorsanız faydalı olabilir.autolayout , kısıtlama değerini (örneğin alt veya üst kısıtlamalar) önceden tanımlanmış bir değerle değiştirerek hareket ettiren veya klavye boyutu değerini kullanabileceğiniz .

Bu örnekte, başlangıçtaki 175 değeri ile metin alanından Alt Mizanpaj Görünümü'ne alt kısıtlama kullanıyorum.

@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

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) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 260
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

func keyboardWillHide(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 175
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

Merhaba efendim, lütfen neden TableView içeren bir görünüme yerleştirildiğinde bunun çalışmadığını söyleyebilir misiniz? Bir CollectionView içerdiğinde aynı senaryoda iyi çalışır.
elarcoiris

9

KeyboardWillHideNotification işlevini tanımlama şeklimizde bazı değişiklikler yapıldı.

Bu çözüm Swift 4.2 ile çalışır :

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)


@objc func keyboardWillShow(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y -= keyboardSize.height
    }
}

@objc func keyboardWillHide(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y += keyboardSize.height
    }
}

2
textField'ım görünümün en üstündeyse ne olur? yani kaynak Y = 0 ile metin alanı varsa .. ?? sonra textField yukarı gidiyor ve göremiyorum
Saifan Nadaf

7

Swift 5.0:

4-5 saatlik kavgadan sonra çekicilik gibi çalışan basit kodla UIViewController'ın basit bir uzantısıyla geldim

* TextField klavyenin üzerindeyken görünüm hareket etmemelidir

* NSLayoutConstraint için sabit değer ayarlamanıza gerek yoktur

* Üçüncü taraf kitaplığı gerekmez

* Animasyon kodu gerekmez

* Tablo görünümünde de çalışır

* Bu, Otomatik düzen / otomatik yeniden boyutlandırma üzerinde çalışır

extension UIViewController {
    func addKeyboardObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotifications(notification:)),
                                               name: UIResponder.keyboardWillChangeFrameNotification,
                                               object: nil)
    }

    func removeKeyboardObserver(){
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }

    // This method will notify when keyboard appears/ dissapears
    @objc func keyboardNotifications(notification: NSNotification) {

        var txtFieldY : CGFloat = 0.0  //Using this we will calculate the selected textFields Y Position
        let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard


        var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
            // Here we will get accurate frame of textField which is selected if there are multiple textfields
            frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
            txtFieldY = frame.origin.y + frame.size.height
        }

        if let userInfo = notification.userInfo {
            // here we will get frame of keyBoard (i.e. x, y, width, height)
            let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
            let keyBoardFrameY = keyBoardFrame!.origin.y
            let keyBoardFrameHeight = keyBoardFrame!.size.height

            var viewOriginY: CGFloat = 0.0
            //Check keyboards Y position and according to that move view up and down
            if keyBoardFrameY >= UIScreen.main.bounds.size.height {
                viewOriginY = 0.0
            } else {
                // if textfields y is greater than keyboards y then only move View to up
                if txtFieldY >= keyBoardFrameY {

                    viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard

                    //This condition is just to check viewOriginY should not be greator than keyboard height
                    // if its more than keyboard height then there will be black space on the top of keyboard.
                    if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
                }
            }

            //set the Y position of view
            self.view.frame.origin.y = -viewOriginY
        }
    }
}

Hangi TextField öğesinin seçildiğini elde etmek için bu UIResponder Uzantısını ekleyin

extension UIResponder {

    static weak var responder: UIResponder?

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

    @objc private func trap() {
        UIResponder.responder = self
    }
}

Daha sonra bunu herhangi bir ViewController'ınızda kullanın

   override func viewWillAppear(_ animated: Bool) {
        self.addKeyboardObserver()
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.removeKeyboardObserver()
    }

  • Bu Bildirimi şuraya kaydet: func viewWillAppear(_ animated: Bool)

  • Bu Bildirimin kaydını sil func viewWillDisappear(_ animated:Bool)

    Demoyu Buradan İndirin


Bu en iyi çözüm gibi görünüyordu, ancak birkaç hata var. 1, metin alanı yukarı hareket eder ama yazmaya başladığımda biraz daha yukarı atlar. 2, metin yazarken manzarada bazen sola atlar.
Darren

@Darren bu hataları anlamaya çalışıyorum ama bulamadım, lütfen hangi sürümü / cihaz için demek istediğim bu hataları nerede söyleyebilir misiniz ... ??
Saifan Nadaf

6

Swift 3 için, tüm Görünüm Denetleyicilerinde sürekli davranışa ihtiyaç duyduğum için bir UIViewController alt sınıfı yaptım.

class SomeClassVC: UIViewController {

  //MARK: - Lifecycle
  override func viewDidLoad() {
    super.viewDidLoad()

    addKeyboardObservers()
  }

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

    removeKeyboardObservers()
  }

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

  //MARK: - Help
  func addKeyboardObservers() {
    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)
  }

  func removeKeyboardObservers() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
  }

  func keyboardWillShow(notification: NSNotification) {
    let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = -1 * keyboardHeight!
      self.view.layoutIfNeeded()
    })
  }

  func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = 0
      self.view.layoutIfNeeded()
    })
  }

  func resignTextFieldFirstResponders() {
    for textField in self.view.subviews where textField is UITextField {
      textField.resignFirstResponder()
    }
  }

  func resignAllFirstResponders() {
      view.endEditing(true)
  }
}

Pavle'ın çözümünden esinlenerek, klavyeyi kalan kullanılabilir alanın belirli bir yüzdesi kadar otomatik olarak yükseltmek ve aynı zamanda düzgün bir düzen için odaklanmış alanı tekrar tekrar bulmak için yükselttim. Buradan yakalayın
Noor Dawod

Sekme çubuğum da pencerede yukarı çıkıyor! :(
Alfi

6

Doğrulanmış cevap metin alanı konumunu dikkate almaz ve bazı hatalar vardır (çift yer değiştirme, asla birincil konuma geri dönme, texfield görünümün üstünde olsa bile yer değiştirme ...)

Fikir:

  • TextField mutlak Y konumunu almak için
  • klavye yüksekliğini elde etmek için
  • ScreenHeight'ı almak için
  • Ardından klavye konumu ile metin alanı arasındaki mesafeyi hesaplayın (<0 -> görünümü yukarı taşıyorsanız)
  • UIView.frame.origin.y - = .. yerine UIView.transform kullanmak için, UIView.transform = .identity ile orijinal konumuna geri dönmek daha kolay

o zaman görünümü yalnızca gerektiğinde ve odaklanmış texField'in klavyenin üzerinde olması için belirli yer değiştirmenin yerini değiştirebiliriz.

İşte kod:

Hızlı 4

class ViewController: UIViewController, UITextFieldDelegate {

var textFieldRealYPosition: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

  // Delegate all textfields

}


@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let distanceBetweenTextfielAndKeyboard = self.view.frame.height - textFieldRealYPosition - keyboardSize.height
        if distanceBetweenTextfielAndKeyboard < 0 {
            UIView.animate(withDuration: 0.4) {
                self.view.transform = CGAffineTransform(translationX: 0.0, y: distanceBetweenTextfielAndKeyboard)
            }
        }
    }
}


@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.4) {
        self.view.transform = .identity
    }
}


func textFieldDidBeginEditing(_ textField: UITextField) {
  textFieldRealYPosition = textField.frame.origin.y + textField.frame.height
  //take in account all superviews from textfield and potential contentOffset if you are using tableview to calculate the real position
}

}


Çok iyi! (ViewDidLoad içinde sadece "ViewController" yerine "VehiculeViewController" vardır).
rene

Çok daha eksiksiz ve kullanışlı bir cevap. Teşekkür ederim! Klavyenin tutarlı bir boyut vereceği için klavye kontrolünün şu şekilde çağrılmasını öneririm ......... if klavyeSize = (bildirim.userInfo? [UIResponder.keyboardFrameEndUserInfoKey]? NSValue)? Olarak. CgRectValue .size
Ben

4

Diğer cevapların tepeden bazı kısımları görüşten kesmek olduğunu fark ettim. Herhangi bir içeriği kesmeden görünümü yeniden boyutlandırmak istiyorsanız, bu yöntemi deneyin :)

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
    }
}

4

Yeni başlayanlar için iki sentim: yukarıdaki örneklerde birisi koordinatları değiştirir, diğerlerinde "otomatikleştirme maskesi" ve diğer kısıtlamalar kullanılır:

Apple'ın dediği gibi, bu 3 tip mantığı karıştırmayın. Storyboard'da kısıtlamalarınız varsa, x / y'yi değiştirmeye çalışmayın. Kesinlikle işe yaramıyor.


4

Yani diğer cevapların hiçbiri doğru değil.

İOS'taki İyi Davranış Klavyesi:

  • Klavye boyutları değiştiğinde otomatik olarak yeniden boyutlandır (YES IT CAN)
  • Klavye ile aynı hızda canlandırın
  • Klavyeyle aynı eğriyi kullanarak canlandırın
  • İlgili ise güvenli alanlara saygı gösterin.
  • İPad / Undocked modunda da çalışır

Kodum kullanımı NSLayoutConstraintbir ilan@IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

Ayrıca dönüşümleri, görünüm ofsetlerini de kullanabilirsiniz, ... tho kısıtlamasıyla daha kolay olduğunu düşünüyorum. En alta bir kısıtlama ayarlayarak çalışır, sabitiniz 0 / En alta değilse kodu değiştirmeniz gerekebilir.

İşte kod:

// In ViewDidLoad
    NotificationCenter.default.addObserver(self, selector: #selector(?MyViewController.keyboardDidChange), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)


@objc func keyboardDidChange(notification: Notification) {
    let userInfo = notification.userInfo! as [AnyHashable: Any]
    let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
    let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber
    bottomLayoutConstraint.constant = view.frame.height - endFrame.origin.y - view.safeAreaInsets.bottom // If your constraint is not defined as a safeArea constraint you might want to skip the last part.
    // Prevents iPad undocked keyboard.
    guard endFrame.height != 0, view.frame.height == endFrame.height + endFrame.origin.y else {
        bottomLayoutConstraint.constant = 0
        return
    }
    UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
    UIView.animate(withDuration: animationDuration.doubleValue) {
        self.view.layoutIfNeeded()
        // Do additional tasks such as scrolling in a UICollectionView
    }
}

3

% 100 Mükemmel Cevap Açık Klavye tüm Guy Güncelleme Tableview Yüksekliği için

Swift4.2 için

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

      NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
   }

   @objc func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {

        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)

        var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset
    }
}

   @objc func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        self.tbl.contentInset = contentInset
    }
}

Swift3.2

    override func viewDidLoad() {
          super.viewDidLoad()

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    func keyboardWillShow(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         //self.view.frame.origin.y -= keyboardSize.height
         var userInfo = notification.userInfo!
         var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
          keyboardFrame = self.view.convert(keyboardFrame, from: nil)

          var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset

       }
    }

    func keyboardWillHide(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
         self.tbl.contentInset = contentInset
         }
    }

Bu en iyi cevap. tbl tableView olmalı ve bazı dolgu ekledim: contentInset.bottom = keyboardFrame.size.height + 10
iphaaw

2

İçin Swift 3

func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder

    //move textfields up
    let myScreenRect: CGRect = UIScreen.main.bounds
    let keyboardHeight : CGFloat = 216

    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var needToMove: CGFloat = 0

    var frame : CGRect = self.view.frame
    if (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
        needToMove = (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
    }

    frame.origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(_ textField: UITextField) {
    //move textfields back down
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var frame : CGRect = self.view.frame
    frame.origin.y = 0
    self.view.frame = frame
    UIView.commitAnimations()
}

2

Hızlı 4:

Klavyeyi gizlemenin görünümü sayfanın sonuna kadar döndürmediği en kabul edilen cevapla ilgili bir sorunum vardı (sadece kısmen). Bu benim için çalıştı (+ Swift 4 için güncellendi).

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
    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)
}

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

@objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y = 0
        }
    }
}

textField'ım görünümün en üstündeyse ne olur? yani kaynak Y = 0 ile metin alanı varsa .. ?? o zaman textField yukarı gidiyor ve göremiyorum
Saifan Nadaf

2

@Boris yanıtına benzer, ancak Swift 5'te :

override func 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)
}

@IBAction 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 -= keyboardSize.height
        }
    }
}

@IBAction func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

1

İşte benim çözümüm (aslında bu kod, görünümünüzde çok az metin alanınız olduğunda, bu da bir metin alanınız olduğunda da geçerlidir)

class MyViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!

var activeTextField: UITextField!
var viewWasMoved: Bool = false


override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}

override func viewDidDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func textFieldDidBeginEditing(textField: UITextField) {
    self.activeTextField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
    self.activeTextField = nil
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}


func keyboardWillShow(notification: NSNotification) {

    let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()

    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height

    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin

    if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
        self.viewWasMoved = true
        self.view.frame.origin.y -= keyboardSize!.height
    } else {
        self.viewWasMoved = false
    }
}

func keyboardWillHide(notification: NSNotification) {
    if (self.viewWasMoved) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

Temsilciyi
metne

Keyboardwillshow'daki koşulu (! CGRectContainsPoint (aRect, newOrgin!) &&! Self.viewWasMoved) olarak değiştirin
KingofBliss

Çerçeveyi sıfırlarken self.viewWasMoved = false değerini ekleyin
KingofBliss

1

Swift 3 için güncellendi ...

Diğerlerinin söylediği gibi, denetleyicinizin viewDidLoad () yöntemine aşağıdaki gibi bildirim gözlemcileri eklemeniz gerekir:

NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
    { notification in
    self.keyboardWillShow(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
    { notification in
    self.keyboardWillHide(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

Uygun olduğunda gözlemcilerinizi kaldırmayı unutmayın (bunu viewWillDisappear () yönteminde yaparım)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)

Ardından, şovunuzu ve gizleme yöntemlerinizi uygulayın - uygulamaya etkileşim etkinliklerini (beginIgnoringInteractionEvents) yoksaymasını söyleyen satıra dikkat edin. Bu önemlidir, çünkü onsuz, kullanıcı bir alana veya hatta bir kaydırma görüntüsüne dokunabilir ve vardiyayı ikinci kez meydana getirebilir ve bu da korkunç bir UI aksaklığına neden olabilir. Klavye gösterilmeden ve gizlenmeden önce etkileşim olaylarını yok saymak bunu önleyecektir:

func keyboardWillShow(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y -= keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top += keyboardSize.height
        }
    }

func keyboardWillHide(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y += keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top -= keyboardSize.height
        }
    }

Son olarak, kullanıcı etkileşimlerini yeniden etkinleştirin (unutmayın, bu yöntem klavye didShow veya didHide sonra tetiklenir):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }

1

Swift 3 kodu

var activeField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if (self.activeField?.frame.origin.y)! >= keyboardSize.height {
            self.view.frame.origin.y = keyboardSize.height - (self.activeField?.frame.origin.y)!
        } else {
            self.view.frame.origin.y = 0
        }
    }
}

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

1

Aynı VC'de 2 veya daha fazla metin alanınız varsa ve kullanıcı klavyeWillHide işlevini çağırmadan bunlardan birine dokunur ve diğerine dokunursa, görünüm bir kez daha yukarı doğru gider; düzenlediğim cevaptaki kodu kullanarak klavyeye, klavyenin yüksekliğine sahip boş bir alana ve daha sonra görünüme sahip olacaksınız:

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.view.frame.origin.y -= keyboardSize.height
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y += keyboardSize.height
    }
}

Bunu çözmek için, iki "KeyboardWillShow / Hide" işlevini bunlarla değiştirin:

func keyboardWillShow(notification: NSNotification) {
 if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    if view.frame.origin.y == 0{
        self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y != 0 {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

textField'ım görünümün en üstündeyse ne olur? yani kaynak Y = 0 ile metin alanı varsa .. ?? sonra textField yukarı gidiyor ve göremiyorum
Saifan Nadaf

1

@ Boris'in çözümü ÇOK iyi ama görünüm bazen bozulabilir.

Mükemmel hizalama için aşağıdaki kodu kullanın

override func viewDidLoad() {
super.viewDidLoad()            
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)}

Fonksiyonlar:

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

Ve,

@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.origin.y != 0{
        self.view.frame.origin.y = 0 
    }
} }

0

Bu video eğitimi en iyisidir. 7 dakika uzunluğunda ve çok mantıklı olacak. Birden çok metin alanınız olduğunda ve bu metin alanına dokunulduğunda kaydırma görünümünün piksel sayısını "x" taşımasını istediğinizde böyle basit bir çözüm.

https://youtu.be/VuiPGJOEBH4

Sadece şu adımlar:

-Tüm metin alanlarını, görünümün kenarlarıyla sınırlı bir kaydırma görünümünde yerleştirin.

-Tüm metin alanlarını bağlayın ve görünüm denetleyicisine delege olarak görünümü kaydırın.

Bir IBOutlet ile tüm metin alanlarını bağlayın ve görünümü kaydırın.

class ViewController: UIViewController, UITextFieldDelegate {

-Sınıfınıza UITextFieldDelegate protokolü ekleyin

@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!    
@IBOutlet weak var scrollView: UIScrollView!

-Hızlı dosyanıza UITextFieldDelegate yöntemlerini ekleyin:

func textFieldShouldReturn(textField: UITextField) -> Bool {

    textField.resignFirstResponder()
    return true
}


func textFieldDidBeginEditing(textField: UITextField) {

    if (textField == self.stateAddress) {
        scrollView.setContentOffset(CGPointMake(0, 25), animated: true)
    }
    else if (textField == self.zipAddress) {
        scrollView.setContentOffset(CGPointMake(0, 57), animated: true)
    }
    else if (textField == self.phoneNumber) {
        scrollView.setContentOffset(CGPointMake(0, 112), animated: true)
    }
    else if (textField == self.vetEmailAddress) {
        scrollView.setContentOffset(CGPointMake(0, 142), animated: true)
    }
}

func textFieldDidEndEditing(textField: UITextField) {

    scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}

İlk yöntem, klavyeyi kapatmak için klavyedeki dönüş düğmesini etkinleştirir. İkincisi, belirli bir metin alanına dokunduğunuzda, sonra kaydırma görünümünüzün ne kadar kaydırıldığına ilişkin y ofsetini ayarladığınızda (benimki, görünüm denetleyicilerimdeki 25 y konumunun dışındadır 25,57,112,142). Sonuncusu, klavyeden uzaklaştığınızda kaydırma görüntüsünün orijinal konumuna geri döndüğünü belirtir.

Görüntü pikselimi bu şekilde mükemmel yaptım!


0

Bu özellik, Ios'ta inşa edilmiştir, ancak harici olarak yapmamız gerekir.
Aşağıdaki kodu ekleyin
* textField klavyenin altındayken
görünümü taşımak için , * textField klavyenin üzerindeyken görünümü taşımak için değil * Görünümü gerektiğinde klavyenin
yüksekliğine göre taşımak için.
Bu her durumda çalışır ve test edilir.

import UIKit

class NamVcc: UIViewController, UITextFieldDelegate
{
    @IBOutlet weak var NamTxtBoxVid: UITextField!

    var VydTxtBoxVar: UITextField!
    var ChkKeyPadDspVar: Bool = false
    var KeyPadHytVal: CGFloat!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        NamTxtBoxVid.delegate = self
    }

    override func viewWillAppear(animated: Bool)
    {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadVyd(_:)),
            name:UIKeyboardWillShowNotification,
            object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadHyd(_:)),
            name:UIKeyboardWillHideNotification,
            object: nil);
    }

    func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = TxtBoxPsgVar
    }

    func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = nil
    }

    func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
    {
        self.VydTxtBoxVar.resignFirstResponder()
        return true
    }

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

    func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
    {
        if(!self.ChkKeyPadDspVar)
        {
            self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height

            var NonKeyPadAraVar: CGRect = self.view.frame
            NonKeyPadAraVar.size.height -= self.KeyPadHytVal

            let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.origin

            if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
            {
                self.ChkKeyPadDspVar = true
                UIView.animateWithDuration(1.0,
                    animations:
                    { self.view.frame.origin.y -= (self.KeyPadHytVal)},
                    completion: nil)
            }
            else
            {
                self.ChkKeyPadDspVar = false
            }
        }

    }

    func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
    {
        if (self.ChkKeyPadDspVar)
        {
            self.ChkKeyPadDspVar = false
            UIView.animateWithDuration(1.0,
                animations:
                { self.view.frame.origin.y += (self.KeyPadHytVal)},
                completion: nil)
        }
    }

    override func viewDidDisappear(animated: Bool)
    {
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self)
        view.endEditing(true)
        ChkKeyPadDspVar = false
    }
}

| :: | Bazen Görünüm düşecek, bu durumda +/- 150 yükseklik kullanın:

    NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150

    { self.view.frame.origin.y -= self.KeyPadHytVal  - 150},
                    completion: nil)

    { self.view.frame.origin.y += self.KeyPadHytVal  - 150},
                completion: nil)

0
func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y = self.view.frame.height - (self.view.frame.height + keyboardSize.height)
    }

}

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

daha kararlı olmalı


0
 override func viewWillAppear(animated: Bool)
 {
 super.viewWillAppear(animated)

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)

 }

 // MARK: - keyboard
 func keyboardWillShow(notification: NSNotification) 
{

if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: keyboardSize.height, right:contentInsets.right)
                    // ...
                } else {
                    // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
                }
            } else {
                // no userInfo dictionary in notification
            }
        }

func keyboardWillHide(notification: NSNotification) 
{
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: 0, right:contentInsets.right)
 }

0

Tıklamak için aşağıdaki kodu kullanın UITextField Tıklandı

func textFieldDidBeginEditing(textField: UITextField) {
    ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
    ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
    var durationMovement:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -upValue : upValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(durationMovement)
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

0

Konuyu basitleştirmek için bir cocoapod yaptım:

https://github.com/xtrinch/KeyboardLayoutHelper

Bu nasıl kullanılır:

Bir otomatik düzen alt kısıtlaması yapın, ona bir sınıf KeyboardLayoutConstraint verin modülünde bir KeyboardLayoutConstraint ve pod, görünen ve kaybolan klavyeyi karşılamak için gereken işi yapacaktır. Nasıl kullanılacağı ile ilgili örnek projeye bakın (iki tane yaptım: scrollView içinde textFields ve iki temel görünüme sahip dikey olarak ortalanmış textFields - giriş ve kayıt).

Alt mizanpaj kısıtlaması kapsayıcı görünümü, textField'ın kendisi, herhangi bir şey olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.