UITextField düzenlemesini nasıl devre dışı bırakabilirim ama yine de dokunmayı kabul edebilirim?


107

Ben yapıyorum UITextFieldbir olduğunu UIPickerViewolarak inputView. Kopyala, yapıştır, kes ve metin seçerek düzenleyebilmem dışında her şey yolunda ve bunu istemiyorum. Yalnızca Seçici metin alanını değiştirmelidir.

Ben ayarlayarak düzenleme devre dışı olabileceğini öğrendim setEnabledya setUserInteractionEnabledkadar NO. Tamam, ancak TextField dokunmaya yanıt vermiyor ve seçici görünmüyor.

Bunu başarmak için ne yapabilirim?

Yanıtlar:


131

Metin alanı temsilcisini kullanarak, bir yöntem var

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

Bundan HAYIR döndürürseniz, kullanıcının metni düzenleme girişimleri reddedilecektir.

Bu şekilde alanı etkin bırakabilir, ancak yine de insanların içine metin yapıştırmasını engelleyebilirsiniz.


4
Yine de dokunmaya yanıt vermek istiyorsanız, "dokunuşa" yanıt verin ve "içeriye dokunmayın". Aksi takdirde etkinliğiniz asla çağrılmaz.
radven

@NickLockwood, textField’ın ilk yanıt veren olmasına izin vermenin, ancak kullanıcı etkileşimini devre dışı bırakıp imleci gizlemenin herhangi bir yolu var mı?
onmyway133

1
@entropy Kullanıcının kopyalayabilmesi için içeriği seçebilmek istediğinizi varsayıyorum? UITextField'ı alt sınıflarsanız hemen hemen her davranışı geçersiz kılabilirsiniz - örneğin alanı, kullanıcı her dokunduğunda her zaman tümünü seçmeye zorlayabilir, bu da imleci etkili bir şekilde gizler.
Nick Lockwood

1
@LoryLory aynıdır, bunun yerine temsilci yöntemi için Swift sözdizimini kullanın.
Nick Lockwood

5
Daha doğrusu, gerekirse "textFieldShouldBeginEditing" i kullanabiliriz
Naveen Shan

22

Nick'in cevabını Swift'e çevirin:

P / S: false => döndürür, metin alanları girilemez, klavye ile düzenlenir. Metni yalnızca code.EX'e göre ayarlayabilir: textField.text = "My String Here"

override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    return false
}

3
Bu benim için çalışmıyor. Yakınlaştırma görünene ve iOS kes / kopyala / yapıştır menüsü görünene kadar metin alanına uzun tıklamanız yeterli ve bunu metni değiştirmek için kullanabilirim.
RowanPD

2
swift 4: `func textField (_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replaceString string: String) -> Bool {return false}`
lionello

16

Bu, en basit olanı olacaktır:

viewDidLoad'da: (temsilciyi yalnızca düzenlenebilir olmaması gereken metin alanları için ayarlayın.

self.textfield.delegate=self;

ve bu temsilci işlevini ekleyin:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
return NO;
}

Bu kadar!


27
Bu, seçicinin gösterilmesini engeller ve bu nedenle açıklanan sorunu
çözmez

6
@MartinLockett UIPickerViewDavranışı bu temsilci yönteminden tetiklerseniz, iyi çalışır.
Albert Bori

9

Swift 3+ sürümünde:

class MyViewController: UIViewController, UITextFieldDelegate {

   override func viewDidLoad() {
      self.myTextField.delegate     = self
   }

   func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
      if textField == myTextField {
         // code which you want to execute when the user touch myTextField
      }
      return false
   }
}

7

Özel bir alt sınıfını oluşturmak için daha şık olurdu UITextFieldo dönene NOkadar tüm aramalar için canPerformAction:withSender:(burada ya da en azından actionbir @selector(cut)ya @selector(paste)) açıklandığı gibi, burada .

Ayrıca, Bluetooth klavyelerden metin girişini devre dışı bırakmak için Nick'in önerisine göre - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range replaceString: (NSString *) dizesini de uygularım.


Hayatım boyunca bunu nasıl yapacağımı çözemem. Alt sınıflar canPerformActionve shouldChangeCharactersInRangeyöntemler asla çağrılmaz.
Nestor

7

Basitçe bir UIButton'u tüm UITextField'in üzerine hiçbir Label metni olmadan yerleştirerek onu "görünmez" yapar. Bu düğme, Metin Alanı yerine dokunuşları alabilir ve devredebilir ve TextField içeriği hala görünür durumdadır.


7

Swift'de:

func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
    questionField.resignFirstResponder();
    // Additional code here
    return false
}

3

MrMage tarafından sağlanan çözümü kullandım. Ekleyeceğim tek şey, UITextView'ı ilk yanıtlayıcı olarak bırakmanız gerektiğidir, aksi takdirde seçilen metne bağlı kalırsınız.

İşte benim hızlı kodum:

class TouchableTextView : UITextView {

    override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        self.resignFirstResponder()
        return false
    }

    override func shouldChangeTextInRange(range: UITextRange, replacementText text: String) -> Bool {
        self.resignFirstResponder()
        return false
    }

}

1

UIPickerView ve Eylem Sayfalarını işleyen bir alternatif için ActionSheetPicker'ı kontrol edin

https://github.com/TimCinel/ActionSheetPicker

Kokoapodlar etkin. Eylem Sayfasındaki tüm iptal ve tamamlama düğmelerini kullanır. Örnek projedeki örnekler harika. Sadece String tabanlı seçenekleri kolayca işleyen ActionSheetStringPicker'ı seçiyorum, ancak API aklıma gelen çoğu şeyi halledebilir.

Başlangıçta onay işaretli cevaba çok benzeyen bir çözüme başladım, ancak bu projeye tökezledim ve cocopods: ActionSheetPicker (~> 0.0) dahil kullanım için her şeyi uygulamama entegre etmem için yaklaşık 20 dakika sürdü

Bu yardımcı olur umarım.

Git projesini indirin ve aşağıdaki sınıflara bakın:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

İşte eklediğim kodun kabaca çoğu artı * .h içe aktarımları.

- (IBAction)gymTouched:(id)sender {
      NSLog(@"gym touched");

      [ActionSheetStringPicker showPickerWithTitle:@"Select a Gym" rows:self.locations initialSelection:self.selectedIndex target:self successAction:@selector(gymWasSelected:element:) cancelAction:@selector(actionPickerCancelled:) origin:sender];
 }


- (void)actionPickerCancelled:(id)sender {
    NSLog(@"Delegate has been informed that ActionSheetPicker was cancelled");
}


- (void)gymWasSelected:(NSNumber *)selectedIndex element:(id)element {
    self.selectedIndex = [selectedIndex intValue];

    //may have originated from textField or barButtonItem, use an IBOutlet instead of element
    self.txtGym.text = [self.locations objectAtIndex:self.selectedIndex];
}


-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    return NO;  // Hide both keyboard and blinking cursor.
}

Bölmenin güncellenmiş bir sürümü burada. github.com/skywinder/ActionSheetPicker-3.0
Nick N

1

Değerleri seçmek için UIPickerView kullanırken UITextField'in düzenlenmesini önlemek için (Swift'de):

self.txtTransDate = self.makeTextField(self.transDate, placeHolder: "Specify Date")
self.txtTransDate?.addTarget(self, action: "txtTransDateEditing:", forControlEvents: UIControlEvents.EditingDidBegin)

func makeTextField(text: String?, placeHolder: String) -> UITextField {
    var textField = UITextField(frame: CGRect(x: 140, y: 0, width: 220.00, height: 40.00));
    textField.placeholder = placeHolder
    textField.text = text
    textField.borderStyle = UITextBorderStyle.Line
    textField.secureTextEntry = false;
    textField.delegate = self
    return textField
}


func txtTransDateEditing(sender: UITextField) {
    var datePickerView:UIDatePicker = UIDatePicker()
    datePickerView.datePickerMode = UIDatePickerMode.Date
    sender.inputView = datePickerView
    datePickerView.addTarget(self, action: Selector("datePickerValueChanged:"), forControlEvents: UIControlEvents.ValueChanged)
}

func datePickerValueChanged(sender: UIDatePicker) {
    var dateformatter = NSDateFormatter()
    dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
    self.txtTransDate!.text = dateformatter.stringFromDate(sender.date)
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool  {
    self.resignFirstResponder()
    return false
}

0

Bu geçici çözüm işe yarıyor. Metin alanının üstüne şeffaf bir UIView yerleştirin ve aşağıdaki kodu uygulayın:

- (void)viewDidLoad
{
 [super viewDidLoad];

   UILongPressGestureRecognizer *press = [[UILongPressGestureRecognizer alloc]             initWithTarget:self action:@selector(longPress)];
[transparentView addGestureRecognizer:press];
 [press release];
  press = nil;
}

-(void)longPress
{
   txtField.userInteractionEnabled = NO;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   txtField.userInteractionEnabled = YES;
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  [txtField becomeFirstResponder];
}

1
Neden basit bir şeffaf UIButton + touchUpInside kullanmadığınız ve bunun yerine UIView + hareketini tercih ettiğiniz konusunda kafam karıştı.
Chen Li Yong

0

Girdi Görünümü'nün, sunulan ve devre dışı bırakılanın metnini de değiştiren gizli bir metin alanı tarafından sunulmasını sağlayın.


0

Bunun ne kadar hileli olduğundan tam olarak emin değilim ama benim durumumda hile yapan tek şey bir hedef eylem eklemek ve endEditing'i çağırmaktı. Seçicim UITextField.text değerimi kontrol ettiğinden, kullanıcı alanı tıklar tıklamaz klavyeyi kapatabilirim. İşte bazı kodlar:

uiTextFieldVariable.addTarget(self, action: #selector(dismissKeyboard), for: .editingDidBegin)

@objc private func dismissKeyboard() {
    endEditing(true)
}

-5

Kullandım :

[self.textField setEnabled:NO];

ve işi iyi


-7

Bu benim için çalıştı [textview setEditable:NO]; Yukarıdaki cevaplar durumu aşırı karmaşık hale getiriyor.


1
OP, "setEnabled veya setUserInteractionEnabled'ı ayarlayarak düzenlemeyi devre dışı bırakabileceğimi öğrendim: HAYIR'ı HAYIR'a ayarlayın. Tamam, ancak TextField dokunmaya yanıt vermiyor ve seçici görünmüyor." Cevabınız, istenen sonucu olmayan tüm olayları durduracaktır.
maninvan

@Tolgab bu OP için bile ilgili bir çözüm değil!
Anurag Sharma
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.