UITextField öğesinin imlecini gizleme


137

Onun için bir UITextFieldile kullanıyorum , böylece kullanıcı metin alanına dokunduğunda, bir seçenek seçmeleri için bir toplayıcı çağrılır.UIPickerViewinputView

Neredeyse her şey işe yarıyor, ama bir sorunum var: imleç etkin olduğunda metin alanında yanıp sönüyor, bu çirkin ve uygunsuz, çünkü kullanıcının alana yazması beklenmiyor ve bir klavye ile sunulmuyor. Metin alanına ayarlayarak editingve NOüzerindeki dokunuşları izleyerek veya özel bir düğmeyle değiştirerek ve seçiciyi kodla çağırarak bunu hackily çözebilirim . Ancak, UITextFieldDelegatemetin alanındaki tüm olay işleme ve metin alanını bir düğme ile değiştirme gibi kesmek için bu yöntemi kullanmak istiyorum, bu yaklaşıma izin vermiyor.

UITextFieldBunun yerine imleci nasıl kolayca gizleyebilirim ?

Yanıtlar:


277

Sadece UITextField öğesini alt sınıflayın ve caretRectForPosition'ı geçersiz kılın

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

2
Güzel! Benim için bir cazibe gibi çalışıyor.
Joe Strout

1
@Joseph Chiu Harika çalışıyor. Ancak iOS 4.3 ile değil. bunun için bana yardım edebilir misiniz?
Dinesh Raja

çifte bir oylamayı hak eden en temiz ve en kısa yaklaşım =)
Ilker Baltaci

1
Sadece bir not. Benim alt sınıfta bir bool hideCaret ekledim o zaman bu geçersiz kılma içinde Eğer doğruysa -> dönüş CGRectZero başka süper sonucu döndürür.
WCByrne

6
Harici klavyeye sahip kullanıcıların, imleç gizlenmiş ve seçici bir görünüm kullansanız bile metin alanının değerini değiştirebileceğini unutmayın.
Mark

156

İOS 7'den itibaren artık tintColor = [UIColor clearColor]textField üzerinde ayar yapabilirsiniz ve düzeltme işareti kaybolacaktır.


1
Bu şu anda işe yarıyor, ancak gelecekte değişebileceğinden kullanmaya karşı tavsiye ederim. Bunun yerine caretRectForPosition:geçersiz kılma çözümünü seçin.
lipka

@lipka Doğru, bu muhtemelen daha iyi bir yol.
jamone

2
Şimdilik yeterince iyi. Bazen hızlı bir çözüme ihtiyacınız vardır.
GoldenJoe

Bu şimdiye kadarki en kolay çözüm!
Jay Q.10

1
Bu yanıt iOS 7+ için onaylanmalıdır
Tryp

95

Metin alanının renk tonunu temizleyebilirsiniz

self.textField.tintColor = [UIColor clearColor];

Swift 3.0

self.textField.tintColor = .clear

resim açıklamasını buraya girin


En kolay cevap.
Nik Kov

2
Yukarıda belirtildiği gibi, renk tonunun temizlenmesi harici klavyelere (iPad Pro) sahip kullanıcıların metni değiştirmesini engellemez.
Michael Long

@MichaelLong, kullanıcının metni değiştirmesini durdurmakla ilgili değil, sadece bir stil seçimi.
JRam13

21

Ayrıca, seçicinin tek metin girişinin seçici görünümünden gelmesi için kullanıcının herhangi bir metni seçmesini, kopyalamasını veya yapışmasını durdurmak isteyebilirsiniz.

- (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/


15

Check out özelliği selectedTextRange bir protokol UITextInput için sınıf UITextField uygun olup. Az! Bu, orada nesne yönelimli programlama konusunda bir ders.

Caret'i Gizle

Düzeltme işaretini gizlemek için metin alanının seçilen metin aralığını sıfırlayın.

textField.selectedTextRange = nil; // hides caret

Caret'i Göster

İşte şapka işaretini göstermenin iki yolu.

  1. Metin alanının seçilen metin aralığını belgenin sonuna ayarlayın.

    UITextPosition *end = textField.endOfDocument;
    textField.selectedTextRange = [textField textRangeFromPosition:end
                                                        toPosition:end];
  2. İmleci aynı noktada tutmak için, önce metin alanının seçilen metin aralığını bir örnek değişkenine kaydedin.

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

    Ardından, düzeltme işaretini göstermek istediğinizde, metin alanının seçilen metin aralığını orijinaline geri ayarlayın:

    textField.selectedTextRange     = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;

3
Bu özel çözüm benim uygulamamda işe yaramadı. İmleç hala yanıp sönüyor.
Art Geigel

Öyleyse, belki de bugreport.apple.com'da bir hata vermelisiniz çünkü iOS dokümanları şöyle diyor: "Metin aralığı bir uzunluğa sahipse, o anda seçili metni gösterir. Sıfır uzunluğa sahipse, düzeltme işaretini (ekleme Metin aralığı nesnesi sıfır ise geçerli seçim olmadığını gösterir. "
ma11hew28

4
Rapor vermek için yeterince umrumda değil. Diğerleri "çözümünüzü" kullanıyor ve işe yaramıyorsa, yalnız olmadıklarını bilmelerini istedim.
Art Geigel

@ ArtGeigel'in yorumlarına rağmen, bu benim için mükemmel bir şekilde çalışıyor. Ancak, geçersiz kılmayı içeren çözümü tercih ederim caretRectForPosition. Ne yaptığı daha açıktır ve alıntıladığınız dokümanlar, 'mevcut seçim' olmadığında caret davranışının ne olması gerektiğini netleştirmez. @ ArtGeigel'in bunun işe yaramadığı iddiası doğruysa (ki en azından görebildiğim kadarıyla) bunun bir hata olduğu açık değildir.
Mark Amery

Benim için de çalışmadı. Caret hala orada ve yanıp sönüyor.
CW0007007

11

Cevap OP tarafından sağlanan, cevapsız soruların sürekli büyüyen kuyruğunu temizlemek için soru gövdesinden kopyalandı.

Başka bir çözüm buldum: alt sınıf UIButtonve bu yöntemleri geçersiz kılma

- (UIView *)inputView {
    return inputView_;
}

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

- (BOOL)canBecomeFirstResponder {
    return YES;
}

Şimdi düğme, a'ya UIResponderbenzer bir davranışa UITextFieldve oldukça basit bir uygulamaya sahiptir.


5
Bu gerçekten harika bir çözüm değil. Aşağıdaki cevabı inceleyin: stackoverflow.com/a/13660503/1103584
DiscDev

2
Bu neden harika bir çözüm değil? Amaçlanan efekti elde eder ve daha önce olmayan bir sınıfa işlevsellik sağlar. Ayrıca bir hack değil. Bence gerçekten harika. Peki bunun nesi var?
BreadicalMD

2
@BreadicalMD Gördüğüm en büyük sorun, başlangıç UITextFieldDelegateve bitiş olaylarını işlemek için bununla birlikte kullanamamanız . Bunun yerine - hakkında bilmediğim olayları ele almanın bir yolu yoksa - geçersiz kılmanız becomeFirstResponderve resignFirstResponderdüğme alt sınıfında olmanız ve muhtemelen kendi temsilci protokolünüzü oluşturmanız, bir delegateözellik eklemeniz ve yukarıda belirtilen temsilci olarak çağırmanız gerekir. yöntemleri. Bu sadece caretRectForPositionbir UITextFieldalt sınıfta geçersiz kılmaktan çok daha fazla iştir .
Mark Amery

1
@BreadicalMD Bu, Joseph Chiu'nun herhangi bir pratik açıdan üstün olmasına rağmen, bunun oldukça seksi olduğuna hala katılıyorum. Daha UIResponderönce hiç sınıf referansına dikkatle bakmamıştım ve böyle bir hile mümkün olduğu hakkında hiçbir fikrim yoktu.
Mark Amery

Partiye geç, ama bence bu çok iyi bir çözüm ve UITextFieldimleci a kullanmaktan ve gizlemekten çok daha uygun ve daha az hile hissettiriyor , bu da daha sonra metin alanını etiket olarak kullandığımız için temelde bir hack işlevlerinden herhangi birini kullanmamak UITextField.
Rupert

7

Net'in gönderisinin Swift 5 sürümü

  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
  }

Benim durumumda işe yaradı. Swift 4 kullanarak bu yöntemlerle bir UITextField alt sınıfı eklendi.
J. Fdez

3

tintColor öğesini Rengi Temizle olarak ayarlama

textfield.tintColor = [UIColor clearColor];

arayüz oluşturucudan da ayarlayabilirsiniz.


2
2 yıldan uzun bir süre önce bir cevap kopyaladınız.
Ashley Mills

1
üzgünüm arkadaşım, ama hiçbir şey kopyalamamıştım.
Ahmad Al-Attal

4
Bu ilginç, "arkadaşım". Cevabınız 1 '15 Mayıs'tan @ oldman'ın cevabına oldukça yakın görünüyor. Bana seninkinin nasıl farklı olduğunu söyleyebilir misin?
Ashley Mills

1
Yukarıda belirtildiği gibi, renk tonunun temizlenmesi harici klavyelere (iPad Pro) sahip kullanıcıların metni değiştirmesini engellemez.
Michael Long

Profesyonel kullanıcılar istediklerini yapabilirler. Profesyoneller: ne yaptıklarını biliyorlar; ^)
Anton Tropashko

2

İmleci gizlemek istiyorsanız, bunu kolayca kullanabilirsiniz! Benim için çalıştı.

[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]

3
Bu bildiğim kadarıyla belgelenmemiş. Bu spekülasyonu, bu spekülasyonu şu ya da bu şekilde test etmek için kullanan herhangi bir başvuru bilmiyorum, ancak uygulama mağazasına gönderirseniz, uygulamanızı özel API'leri çağırmak için reddedebilirsiniz. Yazık, çünkü bu problemi alt sınıflama olmadan çözebilmek güzel olurdu ve bu cevap bunu mümkün kılıyor.
Mark Amery

1

Cevap OP tarafından sağlanan, cevapsız soruların sürekli büyüyen kuyruğunu temizlemek için soru gövdesinden kopyalandı.

Ben doğru bir çözüm var ama geliştirilebilir eğer kabul edilecektir :) Eh, ben bir UITextField alt sınıfı yaptı ve sınırlar için CGRect döndüren yöntemi geçersiz kılar

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

Sorun? Metin gösterilmiyor çünkü rekt sıfır. Ancak, denetimin alt görünümü olarak bir UILabel ekledim ve setText yöntemini geçersiz kıldım, böylece her zamanki gibi bir metin girerken, metin alanı metni nil ve metni gösteren etiket

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

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

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

Bununla birlikte beklendiği gibi çalışır. Bunu geliştirmenin bir yolunu biliyor musunuz?


Joseph Chiu'nun alternatif yaklaşımının çok benzer ama çok daha basit olduğu göz önüne alındığında, bu cevap temelde değersizdir. Sadece silmenizi önerebilir miyim?
Mark Amery

1

Hem imleci hem de menüyü devre dışı bırakmak için şu 2 yöntemle alt sınıfı kullanıyorum:

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

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

    return NO;
}

0

Ben sadece alt sınıf UITextFieldve layoutSubviewsaşağıdaki gibi geçersiz kılmak :

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

Bu kirli bir saldırı ve gelecekte başarısız olabilir (hangi noktada imleç tekrar görünür olacak - uygulamanız çökmeyecek), ancak çalışıyor.


-1

Bir kategoriye ilişkili nesneler aracılığıyla bir BOOL cursorlessözellik ekleyebilirsiniz UITextField.

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

Ardından caretRectForPosition:, arasında geçiş yapan bir yöntemle CGRectZerove varsayılan değeri kullanılarak swizzle yapmak için yöntem swizzling'i kullanın cursorless.

Bu, bir açılır kategori aracılığıyla basit bir arayüze yol açar. Bu, aşağıdaki dosyalarda gösterilmiştir.

Onları bırakın ve bu basit arayüzden yararlanın

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

Yöntem 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


Pek çok düzeyde kötü bir çözüm! yeni başlayanlar için: Kategorilerdeki yöntemleri asla geçersiz kılmayın. Eğer gerçekten, gerçekten ihtiyacınız yoksa Yöntem Swizziling kaçının (diğerleri bu soruya iyi çözümler ile geldi). Kodunuzu çok daha karmaşık hale getirir.
EsbenB

Eğer koda gerçekten bakarsanız, kategoride hiçbir yöntemin geçersiz kılınmadığını ve yöntem dolandırıcılığının doğru uygulandığını fark edersiniz. Bu uygulamayı yıllardır hatasız kullanıyorum.
Harika-o

Ayrıca, sürekli yinelenen bir sorunu kalıcı olarak çözmek için ~ 150 satırlık yalıtılmış bir kod tabanı eklemenin karmaşıklığını açıklayın. Bu sadece kod tabanınızı karmaşıklaştırmaz, aynı zamanda mümkün olan en basit arayüzü sağlar; işlevselliği dikte etmek için tek bir boole.
Awesome-o

yöntem swizzling hakkında bu mükemmel tartışmaya bir göz atın stackoverflow.com/questions/5339276/… Özellikle hata ayıklama hakkında. Yöntem swizzling inanılmaz bir özelliktir, ancak IMHO sadece gerektiğinde kullanılmalıdır. Bu sorunun burada sunulan önerilerden birini kullanarak çözmesi kolaydır ve kodun bakımı ve diğer programcılar için okunması daha kolay olacaktır.
EsbenB

Bunu daha önce okudum ve doğruluk için uyguladığımdaki tüm ana hatlara uydum. Tartışmalı olarak, bu yöntem dolandırıcılığın ne zaman kazanacağının sağlam bir örneğidir. Temel kütüphanelerin, platformlar arasında çok ihtiyaç duyulan bir özelliği basit bir şekilde uygulayamadığı, ancak yaygın bir durumdur. Önerilen diğer örnekler anlamsız bir imleçsiz metin alanı tanımlamaz, sadece imlecin çerçevesinin veya renginin gizlenmesiyle gerçekleştirilir. Yeni bir programcı için, bu arayüz okunması en kolay olanıdır ve tam olarak ne beklendiğini yapar.
Awesome-o
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.