简体   繁体   中英

A static character prefix in UITextField

Is there a built-in way to add a character prefix to a UITextField like the screenshot below?

在此输入图像描述

If no, what is the best, most straight-forward way to accomplish this? I am thinking the background property might be able to do this.

Simply adding a gray UILabel on top of the UITextField does the trick:

001002

Note that the UILabel behaves like a background image, the entered text stays on top:

003

UPDATE

Additionally you can add some padding to the UITextField using the following code:

UIView *thePadding = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
theTextField.leftView = thePadding;
theTextField.leftViewMode = UITextFieldViewModeAlways;

This way the text cannot cover the prefix character.
Adjust the rect to make it working properly in your situation.

Following on from Anne's code you can also do this directly in code without the UILabel in IB and UIView in code:

UILabel *poundLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
poundLabel.text = @"£";
[self.paymentAmount setLeftView:poundLabel];
[self.paymentAmount setLeftViewMode:UITextFieldViewModeAlways];

With Ditiet's solution (on retina using size 15 system font), the text field positioned its text 0.5 points too close to the dollar sign. Using -sizeWithAttributes: , I fit the width of the dollar sign label to about 8.5 but the text field positioned its text at an x of 8 (the floor of the left view's width).

I found two solutions to perfect the relative positioning between the dollar sign (left view) & text.

Solution 1: Right Align the Dollar Sign

Set the dollar sign label's width to the ceiling of the width of the dollar sign (or hard code it). Then, right align the dollar sign label's text.

UIFont *font = [UIFont systemFontOfSize:15];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 200, 120, 44)];
textField.font = font;
NSString *dollarSignText = @"$";
CGSize size = [dollarSignText sizeWithAttributes:@{NSFontAttributeName: font}];
UILabel *dollarSignLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, ceilf(size.width), 44)];
dollarSignLabel.font = font;
dollarSignLabel.text = dollarSignText;
dollarSignLabel.textAlignment = NSTextAlignmentRight;
textField.leftView = dollarSignLabel;
textField.leftViewMode = UITextFieldViewModeAlways;
[self.view addSubview:textField];

Although this solution perfects the relative positioning between the dollar sign label (left view) & text, it will likely increase the width of the dollar sign label a bit (not more than 1 pt), causing the same increase to the text field's width and shifting all the text to the right by the same amount.

I don't recommend this solution if the text field's height will change, eg, due to Auto Layout (or autoresizing).

Solution 2: Subclass UITextField & Override Its Positioning

This solution supports you're using Auto Layout (or autoresizing) to adjust the text field's height.

// VVMAmountTextField.h

@import UIKit;

@interface VVMAmountTextField : UITextField

@end


// VVMAmountTextField.m

#import "VVMAmountTextField.h"

@implementation VVMAmountTextField

#pragma mark - UIView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIFont *font = [UIFont systemFontOfSize:15];
        self.font = font;
        self.keyboardType = UIKeyboardTypeDecimalPad;
        self.placeholder = @"0.00";

        // Set leftView to dollarSignLabel ($).
        UILabel *dollarSignLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        dollarSignLabel.backgroundColor = [UIColor whiteColor];
        dollarSignLabel.font = font;
        dollarSignLabel.text = @"$";
        self.leftView = dollarSignLabel;
        self.leftViewMode = UITextFieldViewModeAlways;
    }
    return self;
}

#pragma mark - UITextField

// Override positioning to make things pixel perfect.

#define DOLLAR_SIGN_WIDTH() [((UILabel *)self.leftView).text sizeWithAttributes:@{NSFontAttributeName: self.font}].width

- (CGRect)textRectForBounds:(CGRect)bounds
{
    bounds = [super textRectForBounds:bounds];
    bounds.origin.x = DOLLAR_SIGN_WIDTH();
    return bounds;
}

- (CGRect)editingRectForBounds:(CGRect)bounds
{
    bounds = [super editingRectForBounds:bounds];
    bounds.origin.x = DOLLAR_SIGN_WIDTH();
    return bounds;
}

- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
    bounds.size.width = DOLLAR_SIGN_WIDTH();
    return bounds;
}

@end

Conclusion

Either solution seems to work well. Solution 1 will likely cause a shift but has less code and still looks pixel-perfect. I only thought of it after Solution 2. Solution 2 is elegant and supports you're using Auto Layout (or autoresizing) to adjust the text field's height.

Dont think you can do this as part of UITextField alone.

One way I can thing of is to make your UITextField borderless and keep a UILabel on the left (but adjacent) of the UITextField . And finally if you want border than put these 2 elements (UITextField and UILabel) inside a UIView and give border to this view. This setup should look exactly same as the image you have put up.

Let me know if this works out.

UPDATE : you could do as @Anne points but there is a risk of text running on top of the UILabel. I feel what I suggested is better.

To add to Anne's answer. You could also make it a UIImageView and use any image you want there. With a UIImageView you can set the background to be white so text will tuck underneath it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM