Як відключити редагування UITextField, але все ж прийняти дотик?


107

Я роблю те, UITextFieldщо має UIPickerViewяк inputView. Це все добре, за винятком того, що я можу редагувати за допомогою копіювання, вставлення, вирізання та вибору тексту, і я цього не хочу. Тільки Picker повинен змінювати текстове поле.

Я дізнався , що я можу відключити редагування шляхом установки setEnabledабо setUserInteractionEnabledдо NO. Гаразд, але TextField перестає реагувати на торкання, і вибирач не з’являється.

Що я можу зробити, щоб досягти цього?

Відповіді:


131

Використовуючи делегат текстового поля, існує метод

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

Не повертайте НІ з цього, і будь-яка спроба користувача відредагувати текст буде відхилена.

Таким чином ви можете залишити поле ввімкненим, але все-таки не дозволяти людям вставляти текст у нього.


4
Якщо ви все ще хочете відповісти на дотик, відповідайте на "торкніться вниз", а не "торкайтеся всередину". Інакше ваша подія ніколи не називається.
радвен

@NickLockwood Чи існують способи, які ми можемо дозволити textField стати першим відповіддю, але відключити взаємодію користувачів та приховати карету?
onmyway133

1
@entropy Я припускаю, що ви хочете мати можливість вибрати вміст, щоб користувач міг скопіювати його? Якщо ви підклас UITextField, ви можете майже перекрити будь-яку поведінку - наприклад, ви можете змусити поле завжди вибирати все, коли користувач торкається, що ефективно приховуватиме карету.
Нік Локвуд

1
@LoryLory це те саме, просто використовуйте синтаксис Swift для методу делегата.
Нік Локвуд

5
Точніше ми можемо використовувати "textFieldShouldBeginEditing", якщо потрібно
Naveen Shan

22

Перекладіть відповідь Ніка на швидку:

P / S: Return false => текстові поля не можна вводити, редагувати за допомогою клавіатури. Він просто може встановити текст за кодом.EX: textField.text = "My String Here"

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

3
Це не працює для мене. Просто натискайте текстове поле, доки не з’явиться масштаб і не з’явиться меню вирізання / копіювання / вставки для iOS, і я можу використовувати це для зміни тексту.
RowanPD

2
swift 4: `func textField (_ textField: UITextField, shouldChangeCharactersВ діапазоні: NSRange, замінаString string: String) -> Bool {return false}`
lionello

16

Це було б найпростіше з усіх:

у viewDidLoad: (встановити делегат лише для текстових полів, які не мають бути редаговані.

self.textfield.delegate=self;

і вставити цю функцію делегата:

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

Це воно!


27
Це запобігає підбирача від того , представлені і тому не вирішити цю проблему описав
Martin Локетт

6
@MartinLockett Якщо ви запускаєте UIPickerViewповедінку цього методу делегата, він працює добре.
Альберт Борі

9

Швидкий 3+:

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

Було б більш елегантно створити спеціальний підклас, UITextFieldякий повертається NOдля всіх дзвінків до canPerformAction:withSender:(або принаймні, де actionє @selector(cut)або @selector(paste)), як описано тут .

Крім того, я б також реалізував - (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) діапазон заміниString: (NSString *) рядок за пропозицією Ніка, щоб відключити введення тексту з клавіатур Bluetooth.


Не можу життя мене розробити, як це зробити. Підклас canPerformActionта shouldChangeCharactersInRangeметоди ніколи не називаються.
Нестор

7

Просто розмістіть UIButton точно над усім UITextField без мітки тексту, що робить його "невидимим". Ця кнопка може приймати та делегувати дотики замість Textfield, і вміст TextField все ще видно.


7

У Свіфті:

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

3

Я використав рішення, яке надав MrMage. Єдине, що я хочу додати, - це ви повинні подати у відставку UITextView як перший відповідь, інакше ви застрягли у вибраному тексті.

Ось мій швидкий код:

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 та таблиці дій, перевірте ActionSheetPicker

https://github.com/TimCinel/ActionSheetPicker

Це ввімкнено кокаподи. Він обробляє всі кнопки скасування та виконання в аркуші дій. Приклади у зразковому проекті чудові. Я вибираю ActionSheetStringPicker, який легко обробляє лише параметри на основі String, але API може обробляти більшість всього, що я можу придумати.

Спочатку я почав рішення, схоже на відповідь відмітки, але натрапив на цей проект і зайняв у мене приблизно 20 хвилин, щоб інтегрувати речі в мій додаток для використання, включаючи використання кокоподів: ActionSheetPicker (~> 0.0)

Сподіваюся, це допомагає.

Завантажте проект git і подивіться на наступні класи:

  • ActionSheetPickerViewController.m
  • ActionSheetPickerCustomPickerDelegate.h

Ось приблизно більшу частину коду, який я додав, плюс імпорт * .h.

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

Тут оновлена ​​версія стручка. github.com/skywinder/ActionSheetPicker-3.0
Nick N

1

Щоб запобігти редагуванню UITextField під час використання UIPickerView для вибору значень (у Swift):

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

Це вирішення працює. Помістіть прозорий UIView над текстовим полем та реалізуйте такий код:

- (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
Мене бентежить, чому ви не використовуєте простий прозорий UIButton + touchUpInside, а замість цього вибрали UIView + жест.
Чень Лі Йонг

0

Зробіть так, щоб ваш inputView був представлений прихованим текстовим полем, яке також змінює текст представленого та відключеного.


-5

Я використав :

[self.textField setEnabled:NO];

і його робота прекрасна


-7

Це спрацювало для мене. [textview setEditable:NO]; Наведені вище відповіді ускладнюють ситуацію.


1
В ОП написано: "Я дізнався, що можу відключити редагування, встановивши setEnabled або setUserInteractionEnabled: НІ-НІ. Добре, але TextField перестає реагувати на торкання, і вибирач не з'являється". Ваша відповідь зупинить усі події, які не були бажаним результатом.
maninvan

@Tolgab навіть не пов'язане рішення для цієї ОП!
Анураг Шарма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.