-->

Adding an uneditable text suffix to a UITextField

2020-07-07 08:00发布

问题:

I have a UITextField that I'd like to add a "?" suffix to all text entered.

The user should not be able to remove this "?" or add text to the right hand side of it.

What's the best way to go about this?

回答1:

You'll probably need to subclass UITextField and override its drawText: method to draw an additional "?" character to the right of the actual text. (Rather than actually add a "?" to the text of the view.



回答2:

Use the UITextFieldDelegate protocol to alter the string whenever the field is being edited. Here's a quick stab at it; this will need work, but it should get you started.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * currentText = [textField text];
    if( [currentText characterAtIndex:[currentText length] - 1] != '?' ){
        NSMutableString * newText = [NSMutableString stringWithString:currentText];
        [newText replaceCharactersInRange:range withString:string];
        [newText appendString:@"?"];
        [textField setText:newText];
        // We've already made the replacement
        return NO;
    }
    // Allow the text field to handle the replacement 
    return YES;
}


回答3:

I had this issue and I wrote a subclass to add this functionality: https://github.com/sbaumgarten/UIPlaceholderSuffixField. Hopefully you have found a solution by now but if you haven't, this should work.



回答4:

I realize this answer is late, but I found most of these did not work for my scenario. I have a UITextField that I simply want to force to have a suffix that the user cannot edit. However, I don't want to subclass UITextView, modify how it handles drawing, etc. I just want to prevent the user from modifying the suffix.

First, I ensure the suffix is set in the textfield when editing takes place. This could be done any number of ways depending upon your scenario. For mine, I wanted it there from the start, so I simply set the textfield's text property equal to the suffix when the view loads and store off the length of the suffix for later. For example:

- (void)viewDidLoad {
    [super viewDidLoad];
    myTextField.text = "suffix";
    _suffixLength = myTextField.text.length;
}

Then I used the UITextFieldDelegate protocol as Josh suggested above, but use the length of the string and the range to ensure nothing edits the suffix:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // Determine starting location of the suffix in the current string
    int suffixLocation = textField.text.length - _suffixLength;

    // Do not allow replacing anything in/past the suffix
    if (range.location + range.length > suffixLocation)
    {
        return NO;
    }

    // Continue with delegate code...
}

This should work for any suffix value you assign to the textfield.



回答5:

For a single-line UITextField you should be able to measure the size of the NSString (it has a measurement function in there, somewhere) and move a UILabel to the right position.



回答6:

I would add a method that is called when edit finishes:

`- (void)editDidFinish {
  NSString* str=[[NSString alloc] init];
  str=myEdit.text;
  [str stringByAppendingString:@"?"];
  myEdit.text=str;
}`


回答7:

OK, im definitly too late, but maybe i can help someone out either way: The intended way to accomplish this is by using a custom NSFormatter. Heres the docs: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFormatter_Class/Reference/Reference.html

The basic idea is this: you create a subclass of NSFormatter, and the override at least the two worker methods:

-stringObjectForValue:

this will produce the dipsplay-String from the value stored in the object (i.e. add your questionmark here)

-objectValue:ForString:errorDescription

here, you need to transform the display-string into an object you want to store, i.e. remove the questionmark

The formatter can then be used to convert the data from the stored objects into strings that are suitable for presentation to the user. The big advantage is that you can use formatters wherever your string will appear in the UI. It is not limited to certain UI-Elements like the solution where you override -drawText in UITextField. Its just hella convenient.



回答8:

This class method I have written in Objective-C, helps you to add a suffix text to a UITextField. I order to make it work, you need to initialize the UILabel to the prefix or suffix in your UITextFieldLabel as follow:

myTextField.rightView = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, myTextField.frame.size.height)];
myTextField.rightViewMode = UITextFieldViewModeAlways;
[MyClass UpdateUITextFieldSuffix:myTextField withString:@"My Suffix!"];

Once we have the UILabel attached to the UITextField, you can use this class method to update the text, and this text will be automatically resized to fit in the field.

+ (BOOL)UpdateUITextFieldSuffix:(UITextField*)textField withString:(NSString*)string
{
    BOOL returnUpdateSuffix = NO;
    if (string != nil && [string respondsToSelector:@selector(length)] && [string length] > 0)
    {
        NSObject *labelSuffix = textField.rightView;
        if (labelSuffix != nil && [labelSuffix respondsToSelector:@selector(setText:)])
        {
            [(UILabel*)labelSuffix setTextAlignment:NSTextAlignmentRight];
            [(UILabel*)labelSuffix setText:string];
            [(UILabel*)labelSuffix setBackgroundColor:[UIColor redColor]];
            {
                NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                                      ((UILabel*)labelSuffix).font, NSFontAttributeName,nil];
                CGRect frame = [((UILabel*)labelSuffix).text boundingRectWithSize:CGSizeMake(0.0f, CGFLOAT_MAX)
                                                                          options:NSStringDrawingUsesLineFragmentOrigin
                                                                       attributes:attributesDictionary
                                                                          context:nil];
                CGSize size = frame.size;
                CGRect newFrame = [(UILabel*)labelSuffix frame];
                newFrame.size.width = size.width;
                [(UILabel*)labelSuffix setFrame:newFrame];
                [(UILabel*)labelSuffix setNeedsLayout];
                [(UILabel*)labelSuffix layoutIfNeeded];
            }            
            returnUpdateSuffix = YES;
        }
    }    
    return returnUpdateSuffix;
}


回答9:

I have written the following method to achieve the above task of placing non-editable suffix to UITextField:

    - (void)setSuffixText:(NSString *)suffix
    {
      UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    [label setBackgroundColor:[UIColor clearColor]];
    [label setFont:[UIFont fontWithName:self.tfdDistance.font.fontName size:self.tfdDistance.font.pointSize]];
    [label setTextColor:self.tfdDistance.textColor];
    [label setAlpha:.5];
    [label setText:suffix];

    CGSize suffixSize = [suffix sizeWithFont:label.font];
    label.frame = CGRectMake(0, 0, suffixSize.width, self.tfdDistance.frame.size.height);

    [self.tfdDistance setRightView:label];
    [self.tfdDistance setRightViewMode:UITextFieldViewModeAlways];
}​