Mendapatkan dan Menyetel Posisi Kursor UITextField dan UITextView di Swift

109

Saya telah bereksperimen UITextFielddan bagaimana bekerja dengan posisi kursornya. Saya telah menemukan sejumlah relasi jawaban Objective-C, seperti pada

Tetapi karena saya bekerja dengan Swift, saya ingin belajar bagaimana mendapatkan lokasi kursor saat ini dan juga mengaturnya di Swift.

Jawaban di bawah ini adalah hasil eksperimen dan terjemahan saya dari Objective-C.

Suragch
sumber

Jawaban:

316

Konten berikut berlaku untuk UITextFielddan UITextView.

Informasi berguna

Bagian paling awal dari teks bidang teks:

let startPosition: UITextPosition = textField.beginningOfDocument

Bagian paling akhir dari teks bidang teks:

let endPosition: UITextPosition = textField.endOfDocument

Rentang yang saat ini dipilih:

let selectedRange: UITextRange? = textField.selectedTextRange

Dapatkan posisi kursor

if let selectedRange = textField.selectedTextRange {

    let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)

    print("\(cursorPosition)")
}

Atur posisi kursor

Untuk menyetel posisi, semua metode ini sebenarnya menyetel rentang dengan nilai awal dan akhir yang sama.

Untuk permulaan

let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

Sampai akhir

let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

Ke satu posisi di sebelah kiri posisi kursor saat ini

// only if there is a currently selected range
if let selectedRange = textField.selectedTextRange {

    // and only if the new position is valid
    if let newPosition = textField.position(from: selectedRange.start, offset: -1) {

        // set the new position
        textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
    }
}

Ke posisi yang sewenang-wenang

Mulailah dari awal dan pindahkan 5 karakter ke kanan.

let arbitraryValue: Int = 5
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: arbitraryValue) {

    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}

Terkait

Pilih semua teks

textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)

Pilih serangkaian teks

// Range: 3 to 7
let startPosition = textField.position(from: textField.beginningOfDocument, offset: 3)
let endPosition = textField.position(from: textField.beginningOfDocument, offset: 7)

if startPosition != nil && endPosition != nil {
    textField.selectedTextRange = textField.textRange(from: startPosition!, to: endPosition!)
}

Sisipkan teks pada posisi kursor saat ini

textField.insertText("Hello")

Catatan

  • Gunakan textField.becomeFirstResponder()untuk memberi fokus pada bidang teks dan membuat keyboard muncul.

  • Lihat jawaban ini untuk mengetahui cara mendapatkan teks pada rentang tertentu.

Lihat juga

Suragch
sumber
Apa tujuan startPosition? Apa yang dapat Anda lakukan dengannya? Juga apa tujuan yang mungkin diperlukan untuk mendapatkan posisi kursor?
Madu
2
@Sayang, saya menggunakan nama variabel itu untuk merujuk ke dua hal berbeda di sini. Yang pertama adalah merujuk ke awal bidang teks. Akan berguna jika Anda ingin memindahkan kursor ke sana. Yang kedua adalah mengacu pada memohon pada teks yang dipilih. Ini berguna jika Anda ingin menyalin rentang itu atau menyetel beberapa atribut di atasnya.
Suragch
Apakah ada sesuatu untuk memindahkan kursor ke kanan saat textfield kosong? Saya mengikuti jawaban Anda tetapi saya tidak bisa.
Yucel Bayram
1
@yucelbayram, Anda dapat menempatkan kursor setelah huruf H menggunakan textField.endOfDocument. Anda juga bisa menggunakan garis bawah atau spasi untuk mewakili huruf yang hilang.
Suragch
1
@ArielSD, maaf, saya belum mengerjakan ini untuk sementara waktu. Saya tidak ingat.
Suragch
42

dalam kasus saya, saya harus menggunakan DispatchQueue:

func textViewDidBeginEditing(_ textView: UITextView) {

   DispatchQueue.main.async{
      textField.selectedTextRange = ...
   }
}

tidak ada yang lain dari ini dan utas lainnya yang berfungsi.

PS: Saya memeriksa ulang utas mana yang menjalankan textViewDidBeginEditing, dan itu utas utama, karena semua UI harus berjalan, jadi tidak yakin mengapa penundaan kecil itu menggunakan main.asynch bekerja.

Michael Ros
sumber
2
Ini bukan penundaan tetapi putaran putaran berikutnya. Kemungkinan besar rentang yang dipilih textfield sedang dimodifikasi oleh fungsi yang sama yang dipanggil textViewDidBeginEditing. Jadi dengan menempatkannya di antrian, itu akan terjadi setelah pemanggil selesai.
Michael Ozeryansky
@MichaelOzeryansky Ya, saya rasa juga begitu. Tapi ini menimbulkan pertanyaan - apa metode yang tepat untuk mengatur posisi kursor secara manual?
pertanyaan jadwal
mengerjakan solusi ini dalam kasus saya, juga
Hattori Hanzō
1

Untuk mengatur posisi kursor pada titik Anda:

textView.beginFloatingCursor(at: CGPoint(x: 10.0, y: 10.0))

Untuk mengatur ulang posisi kursor:

textView.endFloatingCursor()

Catatan : Contoh ini berfungsi di Textview & Textfield.

Parth Patel
sumber
@Suragch Floating Cursor adalah salah satu metode untuk mengatur lokasi kursor di textView atau textField.
Parth Patel
1
let range = field.selectedTextRange

field.text = "hello world"

field.selectedTextRange = range 
Ivan
sumber