问题
I'm making a UITextField
that has a UIPickerView
as inputView
. Its all good, except that I can edit by copy, paste, cut and select text, and I don't want it. Only the Picker should modify text field.
I've learned that I can disable editing by setting setEnabled
or setUserInteractionEnabled
to NO
. Ok, but the TextField stop responding to touching and the picker don't show up.
What can I do to achieve it?
回答1:
Using the textfield delegate, there's a method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Return NO from this, and any attempt by the user to edit the text will be rejected.
That way you can leave the field enabled but still prevent people pasting text into it.
回答2:
Translate the answer of Nick to swift:
P/S: Return false => the textfields cannot input, edit by the keyboard. It just can set text by code.EX: textField.text = "My String Here"
override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return false
}
回答3:
This would be the simplest of all:
in viewDidLoad:(set the delegate only for textfields which should not be editable.
self.textfield.delegate=self;
and insert this delegate function:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
return NO;
}
Thats it!
回答4:
In swift 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
}
}
回答5:
It would be more elegant to create a custom subclass of UITextField
that returns NO
for all calls to canPerformAction:withSender:
(or at least where action
is @selector(cut)
or @selector(paste)
), as described here.
In addition, I'd also implement - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string as per Nick's suggestion in order to disable inputting text from Bluetooth keyboards.
回答6:
Simply place a UIButton exactly over the entire UITextField with no Label-text which makes it "invisible". This button can receive and delegate touches instead of the Textfield and the content of the TextField is still visible.
回答7:
In Swift:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
questionField.resignFirstResponder();
// Additional code here
return false
}
回答8:
I used the solution provided by MrMage. The only thing I'd add is you should resign the UITextView as first responder, otherwise you're stuck with the text selected.
Here's my swift code:
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
}
}
回答9:
For an alternative that handles the UIPickerView and Action Sheets, checkout ActionSheetPicker
https://github.com/TimCinel/ActionSheetPicker
It's cocoapods enabled. It handles all of the cancel and done buttons on the Action Sheet. The examples within the sample project are great. I choose the ActionSheetStringPicker, which handles easily just String based options, but the API can handle most anything that I can think of.
I originally started a solution much like the checkmarked answer, but stumbled onto this project and took me roughly 20 minutes to get things integrated into my app for usage including using cocopods: ActionSheetPicker (~> 0.0)
Hope this helps.
Download the git project and look at the following classes:
- ActionSheetPickerViewController.m
- ActionSheetPickerCustomPickerDelegate.h
Here is roughly most of the code that I added, plus the *.h imports.
- (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.
}
回答10:
To prevent editing of UITextField while using UIPickerView for selecting values(in 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
}
回答11:
This workaround works. Put a transparent UIView above the text field and implement the following code:
- (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];
}
回答12:
Make your inputView be presented by an hidden textfield which also change the text of the presented and disabled one.
回答13:
I used :
[self.textField setEnabled:NO];
and its work fine
回答14:
This worked for me
[textview setEditable:NO];
The above answers are overcomplicating the situation.
来源:https://stackoverflow.com/questions/9116969/how-to-disable-uitextfield-editing-but-still-accept-touch