Pindahkan tampilan dengan keyboard menggunakan Swift

278

Saya memiliki aplikasi yang memiliki bidang teks di bagian bawah tampilan. Ini berarti bahwa ketika saya pergi mengetik di bidang teks keyboard mencakup bidang teks.

Bagaimana cara saya memindahkan tampilan ke atas saat mengetik sehingga saya bisa melihat apa yang saya ketik dan kemudian memindahkannya kembali ke tempat semula ketika keyboard menghilang?

Saya sudah mencari di mana-mana tetapi semua solusi tampaknya berada di Obj-C yang saya belum bisa konversi dulu.

Bantuan apa pun akan sangat dihargai.

Alex Catchpole
sumber
Cara terbaik untuk melakukan ini adalah menempatkan konten Anda di dalam UIScrollView , lalu sesuaikan properti contentInset tampilan gulir dengan ketinggian keyboard saat ditampilkan. Sama sekali tidak menganggap tinggi keyboard - gunakan nilai dari notifikasi "keyboard akan menunjukkan".
nielsbot
1
Bahkan, dokumen Apple memberi tahu Anda cara melakukan ini, di bawah "Mengelola Keyboard": developer.apple.com/library/ios/documentation/StringsTextFonts/…
nielsbot
11
Saya pikir semua jawaban di bawah ini tidak mempertimbangkan satu kasus: bagaimana jika Anda memiliki beberapa bidang teks dan beberapa di antaranya terletak di bagian atas layar? Kapan saja pengguna mengetuk bidang teks itu, ia naik melampaui layar, saya cukup yakin jawaban yang benar akan mendeteksi apakahit is actually needed to scroll view up when keyboard appears
theDC
Jawaban ini dapat mendeteksi apakah sebenarnya diperlukan untuk menggulir tampilan ke atas saat keyboard muncul dengan memeriksa apakah bidang teks yang sedang diedit menempati ruang yang sama dengan keyboard: stackoverflow.com/a/28813720/6749410
HirdayGupta

Jawaban:

710

Berikut ini solusinya, tanpa menangani peralihan dari satu TextField ke yang lain:

 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
}

Untuk mengatasi ini, ganti dua fungsi keyboardWillShow/Hidedengan ini:

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

EDIT UNTUK SWIFT 3.0:

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

EDIT UNTUK SWIFT 4.0:

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

EDIT UNTUK SWIFT 4.2:

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
    }
}
Boris
sumber
56
Jika pengguna menyentuh bidang teks lain saat keyboard hadir, tampilan akan didorong lebih jauh yang menyebabkan area hitam (ukuran keyboard) - kita perlu memperbaikinya dengan memiliki variabel yang melacak apakah keyboard ada atau tidak. . mis. jika keyboardPresent == true maka jangan pindahkan tampilan asal dll.
jonprasetyo
3
@Matthew Lin menggunakan boolean sehingga fungsi keyboardWillShow dan menyembunyikan hanya berfungsi satu kali
iluvatar_GR
11
Hanya satu saran, sehingga Anda tidak perlu men-debug banyak seperti yang saya lakukan. Jika Anda memiliki beberapa bidang uitext pada layar yang sama, ukuran keyboard mungkin bervariasi (tidak menunjukkan saran untuk beberapa input berdasarkan pengaturan Anda), jadi disarankan untuk mengatur self.view.frame.origin.y = 0, setiap kali Anda mengabaikan keyboard. Misalnya, itu akan menunjukkan sestestions untuk bidang teks email Anda, sehingga ukuran keyboard akan meningkat, dan itu tidak akan menampilkan saran untuk bidang kata sandi, sehingga ukuran keyboard akan berkurang.
Vandan Patel
36
Anda perlu menggunakan UIKeyboardFrameEndUserInfoKeydaripada UIKeyboardFrameBeginUserInfoKeysaat mendapatkan ukuran keyboard. Saya tidak yakin mengapa saat ini, tetapi yang pertama akan menghasilkan hasil yang lebih konsisten.
jshapy8
3
Silakan ganti UIKeyboardFrameBeginUserInfoKeydengan UIKeyboardFrameEndUserInfoKey. Yang pertama memberi bingkai awal keyboard, yang kadang-kadang nol, sedangkan yang kedua memberikan bingkai ujung keyboard.
Arnab
90

Cara termudah yang bahkan tidak memerlukan kode apa pun:

  1. Unduh KeyboardLayoutConstraint.swift dan tambahkan (seret & jatuhkan) file ke proyek Anda, jika Anda belum menggunakan kerangka animasi Spring.
  2. Di storyboard Anda, buat batasan bawah untuk View atau Textfield, pilih kendala (klik dua kali) dan di Inspektur Identitas, ubah kelasnya dari NSLayoutConstraint ke KeyboardLayoutConstraint.
  3. Selesai!

Objek akan dipindahkan secara otomatis dengan keyboard, dalam sinkronisasi.

gammachill
sumber
4
Untuk memilih batasan bawah Anda juga dapat pergi ke Ukuran Inspektur, lalu klik dua kali pada kendala dalam daftar - raywenderlich.com/wp-content/uploads/2015/09/…
gammachill
3
Ini bekerja sempurna untuk saya. secara harfiah proses 2 langkah. 1. Tambahkan KeyboardLayoutConstraint.swift, 2. Di storyboard, buat batasan bawah untuk bidang tampilan atau teks. CATATAN: Saya menghapus kendala saya dan menambahkan hanya 1 kendala di bagian bawah tampilan atau bidang teks dan mengubah kelasnya dari NSLayoutConstraint ke KeyboardLayoutConstraint. Maka setiap pandangan / bidang teks dll. Di atas Saya baru saja menghubungkan batasan dari item itu ke item dengan satu KeyboardLayoutConstraint dan hasilnya semua item dalam pandangan dipindahkan ke atas / BAWAH saat Papan Kunci Muncul / Hilang
Brian
4
Ini adalah solusi terbaik, kode yang diberikan tidak meng-hardcode nilai apa pun seperti panjang atau kurva animasi, atau ukuran keyboard. Ini juga mudah dimengerti.
miguelSantirso
3
Ini berfungsi untuk saya, tetapi saya mendapatkan ruang ekstra 50px antara bagian atas keyboard dan bagian bawah scrollView saya. Saya bertanya-tanya apakah itu karena batasan bawah Area Aman yang saya gunakan. Adakah yang mengalami hal ini?
Clifton Labrum
1
Ini jawaban yang luar biasa. Desain yang sangat keren juga. Satu saran: Jika tampilan teks / bidang teks Anda berada di sel tampilan tabel, Anda mungkin melihat tampilan yang memiliki kendala ini akan melompat dengan canggung setiap kali pengguna mengklik masuk dan pergi ke bidang teks berikutnya. Anda dapat membungkus animasi DispatchQueue.main.async {}untuk memperbaikinya. Kerja bagus! Jempolan!
ScottyBlades
68

Salah satu jawaban populer di utas ini menggunakan kode berikut:

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

Ada masalah nyata dengan mengimbangi tampilan Anda dengan jumlah statis. Ini akan terlihat bagus pada satu perangkat tetapi akan terlihat buruk pada konfigurasi ukuran lainnya. Anda harus mendapatkan ketinggian keyboard dan menggunakannya sebagai nilai offset Anda.

Berikut adalah solusi yang berfungsi di semua perangkat dan menangani kasus tepi di mana pengguna menyembunyikan bidang teks prediktif saat mengetik.

Larutan

Penting untuk dicatat di bawah ini, kami meneruskan self.view.window sebagai parameter objek kami. Ini akan memberi kami data dari Keyboard kami, seperti tingginya!

@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
}

Kami akan membuatnya terlihat bagus di semua perangkat dan menangani kasus di mana pengguna menambahkan atau menghapus bidang teks prediktif.

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

Hapus Pengamat

Jangan lupa untuk menghapus pengamat Anda sebelum meninggalkan tampilan untuk mencegah pengiriman pesan yang tidak perlu.

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

Pembaruan berdasarkan pertanyaan dari komentar:

Jika Anda memiliki dua atau lebih bidang teks, Anda dapat memeriksa untuk melihat apakah view.frame.origin.y Anda nol.

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)
}
Dan Beaulieu
sumber
1
ketika berhadapan dengan banyak bidang teks, tampilan terus bergerak ke atas dan tidak kembali turun
Mugunthan Balakrishnan
Anda harus mengubah ketentuan Anda untuk memperhitungkan bidang teks
Dan Beaulieu
terima kasih atas tanggapannya, saya menemukan jawaban yang saya cari di utas ini di stack overflow stackoverflow.com/questions/1126726/…
Mugunthan Balakrishnan
@MugunthanBalakrishnan terima kasih telah membawa ini, saya telah menambahkan solusi.
Dan Beaulieu
Hai teman-teman, ada bug. Pengamat tidak dihapus dari tampilan setelah dipanggil di viewWillDisappear. Ganti baris ini "NSNotificationCenter.defaultCenter (). RemoveObserver (diri, nama: UIKeyboardWillHideNideification, objek: self.view.window)" dengan "NSNotificationCenter.defaultCenter (). RemoveObserver (self, nama: UIKeyboardWillHideNot) objek" dihapus
rudald
29

Tambahkan ini ke viewcontroller Anda. Bekerja seperti pesona. Cukup sesuaikan nilainya.

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
}
pengguna3677173
sumber
Ini bekerja untuk saya. Namun itu sedikit tersentak-sentak. Bagaimana saya bisa membuat ini naik smoothley? juga apakah ada cara untuk hanya menerapkannya ke salah satu bidang teks karena saat ini melakukan ini untuk semua. :(
DannieCoderBoi
2
Mungkin tidak bekerja dengan "Auto-Layout" jadi pertimbangkan untuk menonaktifkannya jika demikian.
Teodor Ciuraru
1
Ini menyebabkan beberapa perilaku funky dengan autolayout @ Astaga, Anda salah
Mike
5
Jangan lakukan ini! Anda tidak dapat menganggap keyboard adalah ukuran tertentu.
nielsbot
2
Harus menggunakan ukuran keyboard. Apa yang terjadi ketika Anda memiliki tampilan aksesori dan ketinggian keyboard yang berbeda di perangkat? Keyboard terpisah?
xtrinch
25

Saya sedikit memperbaiki salah satu jawaban agar berfungsi dengan keyboard yang berbeda & tampilan teks / bidang yang berbeda pada satu halaman:

Tambahkan pengamat:

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

Hapus pengamat:

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)
}
scipianne
sumber
3
solusi ini bekerja lebih baik daripada jawaban yang diterima. Jawaban yang diterima menunjukkan keyboard hanya sekali yang bagi saya adalah bug :)
Masih
Ini berfungsi untuk Xcode 10.1 dan iOS 12. Jawaban yang diterima tidak berlaku lagi.
zeeshan
Ini adalah jawaban yang sangat baik, satu-satunya hal yang akan saya tambahkan adalah melacak area aman di bawah di perangkat yang lebih baru (X, XS, dll) sehingga dapat menjelaskannya.
Munib
@Munib Lihat stackoverflow.com/a/54993623/1485230 Masalah lainnya termasuk tampilan tidak menggerakkan, dan perubahan ketinggian keyboard tidak diikuti.
Antzi
bagaimana jika textField saya berada di atas tampilan ..? Maksud saya jika ada textfield dengan asal Y = 0 .. ?? kemudian textField naik dan saya tidak bisa melihatnya
Saifan Nadaf
19

Bukan iklan atau promosi atau spam , hanya solusi yang bagus. Saya tahu bahwa pertanyaan ini memiliki hampir 30 jawaban dan saya sangat terkejut bahwa tidak seorang pun pernah menyebutkan tentang proyek GitHub yang indah ini yang melakukan semuanya untuk Anda dan bahkan lebih baik. Semua jawaban hanya memindahkan tampilan ke atas. Saya baru saja menyelesaikan semua masalah saya dengan Manajer IQKeyboard ini. Ini memiliki 13000+ bintang.
Cukup tambahkan ini di podfile Anda jika Anda menggunakan swift

pod 'IQKeyboardManagerSwift'

dan kemudian di dalam AppDelegate.swift Anda lakukan 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
    }
}

Tambahkan baris IQKeyboardManager.shared.enable = trueuntuk mengaktifkannya
Solusi ini adalah suatu keharusan jika Anda akan berproduksi.

Weegee
sumber
Ini sangat bagus, tetapi versi terbaru tidak berfungsi untuk saya, saya telah menggunakan 6.2.1, dan mengimpor sebagai import IQKeyboardManagerdan digunakan IQKeyboardManager.shared().isEnabled = truedi AppDelegate
Dhanu K
2
Dan ini bekerja luar biasa ketika menggunakan beberapa teks edit, Ini menghemat waktu saya
Dhanu K
1
Tidak bisa cukup berterima kasih karena menunjukkan perpustakaan yang indah ini. Pustaka ini akhirnya THE FINAL JAWABAN untuk semua omong kosong terkait keyboard yang Apple tidak pernah memberikan solusi untuk. Sekarang saya akan menggunakannya untuk semua proyek saya, baru dan lama, dan menghemat waktu dan sakit kepala yang keyboard ini muncul, menghilang atau tidak menghilang, atau bagaimana menyembunyikannya, dan mengapa itu tumpang tindih, masalah telah menyebabkan saya sejak hari saya pemrograman untuk iPhone.
zeeshan
1
Saya telah menulis kode saya sendiri untuk memindahkan bidang teks, sama seperti solusi lain di sini. Saya menemukan bahwa IQKeyboardManager sangat baik dan saya akan menggabungkannya mulai sekarang. Akan membuat kode saya berguna kalau-kalau kerangka kerja tidak tetap up to date.
TM Lynch
1
Jawaban ini harus lebih tinggi, jauh lebih tinggi.
JC
15

Untuk Kesalahan Layar Hitam (Swift 4 & 4.2) .

Saya memperbaiki masalah layar hitam. Dalam solusi terverifikasi Ketinggian keyboard berubah setelah mengetuk dan ini menyebabkan layar hitam.

Harus menggunakan UIKeyboardFrameEndUserInfoKey alih-alih 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
    }
}
Ali Ihsan URAL
sumber
Tidak akan berfungsi jika ada tabbar. Anda harus menghitung ketinggian tabbar, jika tidak, akan ada celah layar hitam antara keyboard dan tampilan.
Ankur Lahiry
Ini tidak memperbaiki area hitam di mana keyboard berada di iPhone X dan yang lebih baru. Dan setiap kali keyboard muncul dan menghilang tampilan utama terus meluncur ke bawah.
Edison
14

Saya melihat semua jawaban menggerakkan tampilan itu sendiri dengan nilai ketinggian keyboard. Yah, saya punya jawaban yang rumit, yang bisa berguna jika Anda menggunakan kendala yaituautolayout , yang menggerakkan tampilan dengan mengubah nilai kendala (misalnya batasan bawah atau atas) dengan nilai yang ditentukan sebelumnya atau Anda dapat menggunakan nilai ukuran keyboard.

Dalam contoh ini, saya menggunakan batasan bawah dari bidang teks ke Tampilan Tata Letak Bawah dengan nilai awal 175.

@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()
    }
}
Amro Shafie
sumber
Hai pak, bisakah Anda memberi tahu saya mengapa ini tidak berhasil ketika ditempatkan di tampilan yang juga berisi TableView? Ini berfungsi dengan baik dalam skenario yang sama ketika berisi CollectionView.
elarcoiris
9

Ada beberapa perubahan pada bagaimana kita mendefinisikan KeyboardWillHideNotification.

Solusi ini bekerja dengan Swift 4.2 :

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
    }
}
Ivan Le Hjelmeland
sumber
2
bagaimana jika textField saya berada di atas tampilan ..? Maksud saya jika ada textfield dengan asal Y = 0 .. ?? kemudian textField naik dan saya tidak bisa melihatnya
Saifan Nadaf
7

Swift 5.0:

Setelah 4-5 jam berjuang saya datang dengan ekstensi sederhana dari UIViewController dengan kode sederhana yang berfungsi seperti pesona

* Tampilan tidak boleh bergerak saat TextField berada di atas keyboard

* Tidak perlu menetapkan nilai konstan ke NSLayoutConstraint

* Tidak diperlukan perpustakaan pihak ketiga

* Tidak diperlukan kode animasi

* Bekerja pada tampilan tabel juga

* Ini berfungsi pada Auto layout / resize otomatis

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

Tambahkan Extension Of UIResponder ini untuk mendapatkan TextField yang dipilih

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

Kemudian gunakan ini di ViewController Anda

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

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

  • Daftarkan Notifikasi ini di func viewWillAppear(_ animated: Bool)

  • Daftarkan Notifikasi ini di func viewWillDisappear(_ animated:Bool)

    Unduh Demo Di Sini

Saifan Nadaf
sumber
Ini tampak seperti solusi terbaik, namun ada beberapa bug. 1, bidang teks bergerak tetapi ketika saya mulai mengetik itu melompat lebih banyak. 2, Dalam lanskap saat mengetik textField kadang-kadang melompat ke kiri.
Darren
@ Darren saya mencoba untuk mencari tahu bug ini tetapi saya belum menemukan, dapatkah Anda memberi tahu di mana Anda mendapatkan bug ini maksud saya untuk versi / perangkat ... ??
Saifan Nadaf
6

Untuk Swift 3, saya membuat subclass UIViewController karena saya membutuhkan perilaku konstan di semua View Controllers.

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 Mijatovic
sumber
Terinspirasi oleh solusi Pavle, saya memutakhirkannya untuk secara otomatis menaikkan keyboard dengan persentase tertentu dari ruang yang tersisa dan juga menemukan bidang fokus secara rekursif untuk tata letak yang tepat. Raih di
Noor Dawod
Bilah tab saya juga bergerak ke atas dengan jendela! :(
Alfi
6

Jawaban yang divalidasi tidak memperhitungkan posisi textfield dan memiliki beberapa bug (perpindahan ganda, tidak pernah kembali ke posisi utama, perpindahan bahkan jika texfield berada di atas tampilan ...)

Idenya adalah:

  • untuk mendapatkan posisi TextField Y absolut fokus
  • untuk mendapatkan ketinggian keyboard
  • untuk mendapatkan ScreenHeight
  • Kemudian hitung jarak antara posisi keyboard dan bidang teks (jika <0 -> naikkan tampilan)
  • untuk menggunakan UIView.transform alih-alih UIView.frame.origin.y - = .., karena lebih mudah untuk kembali ke posisi semula dengan UIView.transform = .identity

maka kita akan dapat memindahkan tampilan hanya jika perlu dan perpindahan spesifik di untuk memiliki texField terfokus hanya di atas keyboard

Ini kodenya:

Cepat 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
}

}

Quentin N
sumber
Baik sekali! (Dalam viewDidLoad Anda memiliki "VehiculeViewController" bukan hanya "ViewController").
rene
Jawaban yang jauh lebih lengkap dan bermanfaat. Terima kasih! Saya menyarankan agar pemeriksaan keyboard disebut sebagai berikut karena akan memberikan ukuran yang konsisten dari keyboard ......... jika biarkan keyboardSize = (notification.userInfo? [UIResponder.keyboardFrameEndUserInfoKey] sebagai? NSValue) ?. cgRectValue .ukuran
Ben
4

Saya perhatikan bahwa jawaban lain melibatkan memotong beberapa bagian atas dari pandangan. Jika Anda ingin mengubah ukuran tampilan tanpa memotong konten apa pun, coba saja metode ini :)

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)
    }
}
Grant Park
sumber
4

Dua sen saya untuk pemula: dalam sampel di atas seseorang mengubah koordinat, penggunaan lainnya "topeng autoresizing", dan kendala lainnya:

Seperti kata Apple, jangan campur 3 tipe logika ini. Jika Anda memiliki kendala di Storyboard, jangan mencoba mengubah x / y. Ini pasti tidak berfungsi.

ingconti
sumber
4

Jadi tidak ada jawaban lain yang tampaknya benar.

Keyboard Perilaku Baik di iOS harus:

  • Ubah ukuran secara otomatis ketika keyboard berubah ukuran (YA ITU BISA)
  • Hidupkan dengan kecepatan yang sama dengan keyboard
  • Hidupkan menggunakan kurva yang sama dengan keyboard
  • Hormati daerah aman jika relevan.
  • Bekerja pada iPad / mode Undocked juga

Kode saya menggunakan yang NSLayoutConstraintdinyatakan sebagai@IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

Anda juga bisa menggunakan transformasi, tampilan offset, .... Saya pikir lebih mudah dengan kendala tho. Ini bekerja dengan menetapkan batasan ke bawah, Anda mungkin perlu mengubah kode jika konstanta Anda tidak 0 / Tidak ke bawah.

Ini kodenya:

// 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
    }
}
Antzi
sumber
3

100% Jawaban Sempurna Untuk Tinggi Pembaruan Tableview Semua Pria saat membuka Keyboard

Untuk Swift4.2

   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
         }
    }
Maulik Patel
sumber
Ini jawaban terbaik. tbl harus berupa tableView dan saya menambahkan beberapa lapisan: contentInset.bottom = keyboardFrame.size.height + 10
iphaaw
2

Untuk 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()
}
Celil Bozkurt
sumber
2

Swift 4:

Saya mengalami masalah dengan jawaban yang paling diterima, di mana menyembunyikan keyboard tidak mengembalikan tampilan sepenuhnya ke bagian bawah halaman (hanya sebagian). Ini bekerja untuk saya (+ diperbarui untuk Swift 4).

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
        }
    }
}
Rbar
sumber
bagaimana jika textField saya berada di atas tampilan ..? Maksud saya jika ada textfield dengan asal Y = 0 .. ?? kemudian textField naik dan saya tidak bisa melihatnya
Saifan Nadaf
2

Mirip dengan jawaban @Boris, tetapi di Swift 5 :

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
    }
}
Jerry Chong
sumber
1

Inilah solusi saya (sebenarnya kode ini untuk kasus ketika Anda memiliki beberapa bidang teks dalam pandangan Anda, ini juga berfungsi untuk kasus ketika Anda memiliki satu bidang teks)

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
        }
    }
}
Vah.Sah
sumber
Jangan lupa untuk mengatur Delegasi ke textFields
SwingerDinger
Ubah kondisi di keyboard akan ditampilkan sebagai, jika (! CGRectContainsPoint (aRect, newOrgin!) &&!
Self.viewWasMoved
tambahkan self.viewWasMoved = false ketika Anda mengatur ulang bingkai
KingofBliss
1

Diperbarui untuk Swift 3 ...

Seperti yang orang lain katakan, Anda perlu menambahkan pengamat pemberitahuan dalam metode viewDidLoad () pengontrol Anda, seperti:

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

Ingatlah untuk menghapus pengamat Anda jika perlu (saya melakukannya dalam metode viewWillDisappear ())

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)

Lalu, terapkan metode acara dan sembunyikan Anda - perhatikan garis yang memberitahu aplikasi untuk mengabaikan acara interaksi (beginIgnoringInteractionEvents). Ini penting karena tanpa itu, pengguna dapat mengetuk bidang atau bahkan scrollview dan menyebabkan pergeseran terjadi untuk kedua kalinya, menghasilkan kesalahan UI yang mengerikan. Mengabaikan peristiwa interaksi sebelum keyboard menampilkan dan menyembunyikan akan mencegah hal ini:

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

Terakhir, aktifkan kembali interaksi pengguna (ingat, metode ini aktif setelah keyboard didShow atau didHide):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }
Gene Loparco
sumber
1

3 kode cepat

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
}
Rohit Sharma
sumber
1

Jika Anda memiliki 2 atau lebih bidang teks pada VC yang sama, dan pengguna mengetuk salah satunya, lalu mengetuk yang lain, tanpa memanggil fungsi keyboardWillHide, tampilan akan naik sekali lagi, yang tidak perlu, karena tidak diperlukan, karena Anda akan memiliki keyboard, ruang kosong yang memiliki ketinggian keyboard, dan kemudian tampilan, menggunakan kode dalam jawaban yang saya edit:

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

Untuk mengatasi ini, ganti dua fungsi "KeyboardWillShow / Sembunyikan" untuk ini:

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
        }
    }
}
Tuan Xcoder
sumber
bagaimana jika textField saya berada di atas tampilan ..? Maksud saya jika ada textfield dengan asal Y = 0 .. ?? kemudian textField naik dan saya tidak bisa melihatnya
Saifan Nadaf
1

Solusi @ Boris SANGAT bagus tetapi pandangannya terkadang rusak.

Untuk perataan yang sempurna, gunakan kode di bawah ini

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

Fungsi:

@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
    }
}}    

Dan,

@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 
    }
} }
Eray Alparslan
sumber
0

tutorial video ini adalah yang terbaik. 7 menit panjang dan itu akan sangat masuk akal. Solusi sederhana untuk ketika Anda memiliki beberapa bidang teks dan ingin tampilan gulir untuk memindahkan jumlah piksel "x" ketika bidang teks tertentu diketuk.

https://youtu.be/VuiPGJOEBH4

Hanya langkah-langkah ini:

-Tempatkan semua bidang teks Anda dalam tampilan gulir yang dibatasi ke tepi tampilan.

-Hubungkan semua bidang teks dan gulir tampilan sebagai delegasi ke pengontrol tampilan.

-Hubungkan Semua bidang teks dan gulir tampilan dengan IBOutlet.

class ViewController: UIViewController, UITextFieldDelegate {

-Tambahkan protokol UITextFieldDelegate ke kelas Anda

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

-Tambahkan metode UITextFieldDelegate ke file cepat Anda:

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

Metode pertama hanya mengaktifkan tombol kembali pada keyboard untuk mengabaikan keyboard. Yang kedua adalah ketika Anda memasuki bidang teks apa pun yang spesifik kemudian mengatur y offset dari seberapa jauh scrollview Anda bergulir (tambang didasarkan pada lokasi y pada pengontrol tampilan saya 25,57.112.142). Yang terakhir mengatakan ketika Anda menekan keyboard, scrollview kembali ke lokasi semula.

Saya membuat pixel view saya sempurna dengan cara ini!

bme003
sumber
0

Fitur ini seharusnya sudah dibangun di Ios, namun yang perlu kita lakukan secara eksternal.
Masukkan kode di bawah ini
* Untuk memindahkan tampilan ketika textField berada di bawah keyboard,
* Tidak untuk memindahkan tampilan ketika textField berada di atas keyboard
* Untuk memindahkan Lihat berdasarkan ketinggian keyboard saat diperlukan.
Ini berfungsi dan diuji dalam semua kasus.

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

| :: | Kadang-kadang Lihat akan turun, Dalam hal ini gunakan tinggi +/- 150:

    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)
Sujay UN
sumber
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
}

itu harus lebih stabil

Play Hadevs
sumber
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)
 }
Himali Shah
sumber
0

Gunakan kode berikut untuk melihat Up di UITextField diklik

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()
}
Jugal K Balara
sumber
0

Saya membuat cocoapod untuk menyederhanakan masalah:

https://github.com/xtrinch/KeyboardLayoutHelper

Bagaimana cara menggunakannya:

Buat batasan bawah tata letak otomatis, berikan kelas KeyboardLayoutConstraint dalam modul KeyboardLayoutHelper dan pod akan melakukan pekerjaan yang diperlukan untuk meningkatkannya untuk mengakomodasi keyboard yang muncul dan menghilang. Lihat contoh proyek tentang contoh cara menggunakannya (saya membuat dua: textFields di dalam scrollView, dan textFields yang berpusat secara vertikal dengan dua tampilan dasar - login & daftar).

Kendala tata letak bawah bisa dari tampilan wadah, textField itu sendiri, apa pun, apa saja.

xtrinch
sumber