Sembunyikan kursor dari UITextField

137

Saya menggunakan a UITextFielddengan UIPickerViewuntuknya inputView, sehingga ketika pengguna mengetuk bidang teks, seorang pemilih dipanggil untuk memilih opsi.

Hampir semuanya berfungsi, tapi saya punya satu masalah: kursor masih berkedip di bidang teks ketika sedang aktif, yang jelek dan tidak pantas, karena pengguna tidak diharapkan untuk mengetik ke lapangan dan tidak disajikan dengan keyboard. Saya tahu saya bisa memecahkan masalah ini dengan menyetel editingke NObidang teks dan melacak sentuhan di atasnya, atau dengan menggantinya dengan tombol gaya khusus, dan memanggil pemilih melalui kode. Namun, saya ingin menggunakan UITextFieldDelegatemetode untuk semua penanganan acara di bidang teks dan peretasan seperti mengganti bidang teks dengan tombol tidak mengizinkan pendekatan ini.

Bagaimana cara menyembunyikan kursor pada kursor UITextField?

emenegro
sumber

Jawaban:

277

Cukup subkelas UITextField dan ganti caretRectForPosition

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    return CGRectZero;
}
Joseph Chiu
sumber
2
Cantik! Bekerja seperti pesona bagi saya.
Joe Strout
1
@ Joseph Chiu Ini bekerja dengan baik. Tetapi tidak dengan iOS 4.3. Bisakah Anda membantu saya dengan ini?
Dinesh Raja
pendekatan terbersih dan terpendek yang layak mendapat double upvote =)
Ilker Baltaci
1
Hanya sebuah catatan. Dalam subkelas saya, saya menambahkan bool hideCaret kemudian dalam menimpa ini Jika itu benar -> kembali CGRectZero lain mengembalikan hasil super.
WCByrne
6
Perlu diketahui bahwa pengguna dengan keyboard eksternal dapat mengubah nilai bidang teks bahkan jika kursor disembunyikan dan Anda menggunakan tampilan pemilih.
Tandai
156

Pada iOS 7 Anda sekarang dapat hanya mengatur tintColor = [UIColor clearColor]pada TextField dan tanda sisipan akan hilang.

jamone
sumber
1
Ini berfungsi saat ini, namun saya akan menyarankan untuk tidak menggunakannya karena mungkin akan berubah di masa depan. Lebih suka memilih caretRectForPosition:solusi override.
lipka
@lipka Benar, itu mungkin cara yang lebih baik.
jamone
2
Cukup bagus untuk saat ini. Terkadang Anda hanya butuh solusi cepat.
GoldenJoe
Ini adalah solusi termudah sejauh ini!
Jay Q
1
Jawaban ini harus disetujui untuk iOS 7+
tryp
95

Anda bisa menghapus tintColor bidang teks

self.textField.tintColor = [UIColor clearColor];

Swift 3.0

self.textField.tintColor = .clear

masukkan deskripsi gambar di sini

pria tua
sumber
Jawaban termudah terbaik.
Nik Kov
2
Seperti disebutkan di atas, membersihkan warna tidak menghentikan pengguna dengan keyboard eksternal (iPad Pro) mengubah teks.
Michael Long
@MichaelLong ini bukan tentang menghentikan pengguna dari mengubah teks, itu hanya pilihan gaya.
JRam13
21

Anda mungkin juga ingin menghentikan pengguna dari memilih, menyalin atau menempelkan teks apa pun sehingga satu-satunya input teks berasal dari tampilan pemilih.

- (CGRect) caretRectForPosition:(UITextPosition*) position
{
    return CGRectZero;
}

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
    return nil;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(paste:))
    {
        returnNO;
    }

    return [super canPerformAction:action withSender:sender];
}

http://b2cloud.com.au/tutorial/disabling-the-caret-and-text-entry-in-uitextfields/

Nat
sumber
15

Check out properti selectedTextRange dari protokol UITextInput , mana kelas UITextField sesuai. Beberapa! Itu pelajaran dalam pemrograman berorientasi objek di sana.

Sembunyikan Caret

Untuk menyembunyikan tanda sisipan, kosongkan rentang teks yang dipilih bidang teks.

textField.selectedTextRange = nil; // hides caret

Unhide Caret

Berikut adalah dua cara untuk menyembunyikan tanda sisipan.

  1. Setel rentang teks bidang teks yang dipilih ke akhir dokumen.

    UITextPosition *end = textField.endOfDocument;
    textField.selectedTextRange = [textField textRangeFromPosition:end
                                                        toPosition:end];
    
  2. Untuk menjaga tanda sisipan di tempat yang sama, pertama, simpan rentang teks yang dipilih bidang teks ke variabel instan.

    _textFieldSelectedTextRange = textField.selectedTextRange;
    textField.selectedTextRange = nil; // hides caret
    

    Kemudian, ketika Anda ingin menyembunyikan tanda sisipan, cukup setel rentang teks yang dipilih bidang teks kembali ke yang semula:

    textField.selectedTextRange     = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;
    
ma11hew28
sumber
3
Solusi khusus ini tidak berfungsi untuk implementasi saya. Kursor masih berkedip.
Seni Geigel
Nah, maka, mungkin Anda harus mengajukan bug di bugreport.apple.com karena dokumen iOS mengatakan: "Jika rentang teks memiliki panjang, ini menunjukkan teks yang saat ini dipilih. Jika memiliki panjang nol, ini menunjukkan tanda sisipan (penyisipan point). Jika objek rentang teks nihil, ini menunjukkan bahwa tidak ada pilihan saat ini. "
ma11hew28
4
Saya tidak cukup peduli untuk mengajukan laporan. Jika orang lain menggunakan "solusi" Anda dan tidak melihatnya berfungsi, saya ingin mereka tahu bahwa mereka tidak sendirian.
Seni Geigel
Terlepas dari komentar @ ArtGeigel, ini bekerja dengan baik untuk saya. Namun, saya lebih suka solusi yang melibatkan penggantian caretRectForPosition. Ini lebih eksplisit apa yang dilakukannya, dan dokumen yang Anda kutip tidak menjelaskan perilaku caret seharusnya ketika ada 'tidak ada pilihan saat ini'. Jika klaim @ ArtGeigel bahwa ini tidak berfungsi adalah benar (yang tidak, setidaknya sejauh yang saya bisa lihat) tidak akan jelas bahwa itu adalah bug.
Mark Amery
Juga tidak bekerja untuk saya. Caret masih ada di sana dan berkedip.
CW0007007
11

Jawaban diberikan oleh OP, disalin dari badan pertanyaan untuk membantu membersihkan pertanyaan yang tidak terjawab yang terus tumbuh.

Saya menemukan solusi lain: subclass UIButtondan menimpa metode ini

- (UIView *)inputView {
    return inputView_;
}

- (void)setInputView:(UIView *)anInputView {
    if (inputView_ != anInputView) {
        [inputView_ release];
        inputView_ = [anInputView retain];
    }
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

Sekarang tombol, sebagai UIResponder, memiliki perilaku yang mirip UITextFielddan implementasi yang cukup mudah.

Robert Höglund
sumber
5
Ini sebenarnya bukan solusi yang bagus. Lihatlah jawaban ini di bawah ini: stackoverflow.com/a/13660503/1103584
DiscDev
2
Mengapa ini bukan solusi yang bagus? Ini mencapai efek yang dimaksudkan dan juga menyediakan fungsionalitas ke kelas yang sebelumnya tidak memilikinya. Ini juga bukan peretasan. Saya pikir itu sangat keren. Jadi apa yang salah dengannya?
BreadicalMD
2
@BreadicalMD Masalah terbesar yang dapat saya lihat adalah bahwa Anda tidak dapat menggunakan UITextFieldDelegatedengan ini untuk menangani acara penyuntingan mulai dan berakhir. Alih-alih - kecuali ada cara untuk menangani acara-acara yang tidak saya ketahui - Anda harus mengganti becomeFirstResponderdan resignFirstResponderdi subkelas tombol, dan mungkin membuat protokol delegasi Anda sendiri, menambahkan delegateproperti, dan memanggil delegasi dari yang disebutkan di atas. metode. Ini semua jauh lebih berhasil daripada hanya mengesampingkan caretRectForPositiondalam UITextFieldsubkelas.
Mark Amery
1
@BreadicalMD Yang mengatakan, meskipun jawaban Joseph Chiu lebih unggul dari sudut pandang praktis, saya masih setuju dengan Anda bahwa ini sangat seksi. Saya tidak pernah melihat dengan seksama UIResponderreferensi kelas sebelumnya, dan tidak tahu bahwa trik seperti ini dimungkinkan.
Mark Amery
Terlambat ke pesta, tapi saya pikir ini adalah solusi yang sangat bagus dan rasanya jauh lebih tepat dan lebih sedikit meretas daripada menggunakan UITextFielddan menyembunyikan kursor, yang pada dasarnya merupakan peretasan karena kita kemudian menggunakan bidang teks sebagai label sementara tidak menggunakan salah satu fungsi dari UITextField.
Rupert
7

Versi cepat dari 5 posting Net

  override func caretRect(for position: UITextPosition) -> CGRect {
    return .zero
  }
  
  override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
    return []
  }
  
  override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return false
  }
ROM.
sumber
Dalam kasus saya ini berhasil. Menambahkan subclass dari UITextField dengan metode ini menggunakan Swift 4. Terima kasih!
J. Fdez
3

atur tintColor ke Clear Color

textfield.tintColor = [UIColor clearColor];

dan Anda juga dapat mengatur dari pembangun antarmuka

Ahmad Al-Attal
sumber
2
Anda baru saja menyalin jawaban dari lebih dari 2 tahun yang lalu.
Ashley Mills
1
maaf teman saya, tetapi saya tidak menyalin apa pun.
Ahmad Al-Attal
4
Itu menarik, "temanku". Jawaban Anda terlihat cukup dekat dengan jawaban oldman mulai 1 Mei '15. Bisakah Anda ceritakan bagaimana perbedaan Anda?
Ashley Mills
1
Seperti disebutkan di atas, membersihkan warna tidak menghentikan pengguna dengan keyboard eksternal (iPad Pro) mengubah teks.
Michael Long
Pengguna pro dapat melakukan apa yang mereka inginkan. Mereka pro: mereka tahu apa yang mereka lakukan; ^)
Anton Tropashko
2

Jika Anda ingin menyembunyikan kursor, Anda dapat dengan mudah menggunakan ini! Itu bekerja untuk saya ..

[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]
Göktuğ Aral
sumber
3
Ini tidak berdokumen, sejauh yang saya tahu. Mungkin menggunakan ini akan membuat aplikasi Anda ditolak karena memanggil API pribadi jika Anda mengirimkannya ke app store, meskipun saya tidak tahu ada pengiriman yang menggunakan ini untuk menguji spekulasi itu dengan satu atau lain cara. Sayang sekali, karena alangkah baiknya bisa menyelesaikan masalah ini tanpa subklasifikasi, dan jawaban ini memungkinkan hal itu.
Mark Amery
1

Jawaban diberikan oleh OP, disalin dari badan pertanyaan untuk membantu membersihkan pertanyaan yang tidak terjawab yang terus tumbuh.

Saya pikir saya punya solusi yang benar tetapi jika itu dapat ditingkatkan akan diterima :) Yah, saya membuat subkelas dari UITextField dan mengganti metode yang mengembalikan CGRect untuk batas

-(CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectZero;
}

Masalah? Teks tidak muncul karena kotak adalah nol. Tapi saya menambahkan UILabel sebagai subview dari kontrol dan menimpa metode setText sehingga, saat kita memasukkan teks seperti biasa, teks bidang teks nil dan merupakan label yang menunjukkan teks

- (void)setText:(NSString *)aText {
    [super setText:nil];

    if (aText == nil) {
        textLabel_.text = nil;
    }

    if (![aText isEqualToString:@""]) {
        textLabel_.text = aText;
    }
}

Dengan ini masalahnya berfungsi seperti yang diharapkan. Apakah Anda tahu cara untuk memperbaikinya?

Robert Höglund
sumber
Jawaban ini pada dasarnya tidak berharga sekarang mengingat bahwa pendekatan alternatif Joseph Chiu sangat mirip tetapi jauh lebih sederhana. Bolehkah saya menyarankan hanya menghapusnya?
Mark Amery
1

Untuk menonaktifkan kursor dan menu saya menggunakan subclass dengan 2 metode ini:

- (CGRect)caretRectForPosition:(UITextPosition *)position {
    return CGRectZero;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    [UIMenuController sharedMenuController].menuVisible = NO;
    self.selectedTextRange = nil;

    return NO;
}
Vive
sumber
0

Saya cukup subkelas UITextField, dan menimpa layoutSubviewssebagai berikut:

- (void)layoutSubviews
{
    [super layoutSubviews];
    for (UIView *v in self.subviews)
    {
        if ([[[v class] description] rangeOfString:@"UITextSelectionView"].location != NSNotFound)
        {
            v.hidden = YES;
        }
    }
}

Ini peretasan yang kotor, dan mungkin gagal di masa mendatang (saat itu kursor akan terlihat lagi - aplikasi Anda tidak akan macet), tetapi itu berfungsi.

Mark Beaton
sumber
-1

Anda dapat menambahkan BOOL cursorlessproperti ke UITextFielddalam kategori melalui objek terkait.

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

Kemudian gunakan metode swizzling untuk swizzle caretRectForPosition:dengan metode yang beralih antara CGRectZerodan menggunakan nilai defaultnya cursorless.

Ini mengarah ke antarmuka sederhana melalui kategori drop-in. Ini ditunjukkan dalam file-file berikut.

Cukup masukkan mereka dan dapatkan manfaat dari antarmuka sederhana ini

UITextFieldkategori: https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless.h https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless .m

Metode Swizzling: https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.h https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject% 2BRXRuntimeAdditions.m

Luar biasa
sumber
solusi buruk pada banyak level SO! untuk pemula: Jangan pernah menimpa metode dalam kategori. Hindari Metode Mendesah kecuali Anda benar-benar membutuhkannya (orang lain telah memberikan solusi yang bagus untuk pertanyaan ini). Itu membuat kode Anda jauh lebih rumit.
EsbenB
Jika Anda benar-benar melihat kode Anda akan menyadari bahwa tidak ada metode yang ditimpa dalam kategori dan metode swizzling diimplementasikan dengan benar. Saya telah menggunakan implementasi ini selama bertahun-tahun tanpa gagal.
Hebat-o
Juga, jelaskan apa yang rumit tentang menambahkan basis kode terisolasi ~ 150 baris untuk secara permanen menyelesaikan masalah yang berulang? Tidak hanya ini TIDAK akan menyulitkan basis kode Anda tetapi juga menyediakan antarmuka sesederhana mungkin; satu boolean untuk menentukan fungsi.
Hebat-o
lihat diskusi yang sangat baik ini tentang metode swizzling stackoverflow.com/questions/5339276/... Khususnya pada debugging. Metode swizzling adalah fitur yang luar biasa, tetapi IMHO hanya boleh digunakan saat dibutuhkan. Masalah ini mudah diselesaikan dengan menggunakan salah satu saran yang disediakan di sini, dan akan memberikan kode yang lebih mudah dipelihara dan dibaca untuk programmer lain.
EsbenB
Saya telah membaca itu sebelumnya dan saya mengikuti semua pedoman yang diuraikan dalam implementasi saya untuk kebenaran. Dapat diperdebatkan, ini adalah contoh solid ketika metode swizzling menang. Ini adalah kasus yang terisolasi, namun umum di mana perpustakaan dasar gagal menerapkan fitur yang sangat dibutuhkan di seluruh platform dengan cara yang sederhana. Contoh-contoh lain yang disarankan tidak secara semantik mendefinisikan bidang teks tanpa kursor, mereka hanya melakukannya melalui kekaburan baik dari bingkai kursor atau warnanya. Bagi seorang programmer baru, antarmuka ini adalah yang termudah untuk dibaca dan melakukan apa yang diharapkan darinya.
Hebat-o