How do I add padding to a UITextField with an icon

12,699

Solution 1

"Update: Thanks for the replies. I achieved this in the end by creating a UIView for the entire object with a UIImageView for the icon and a UITextField embedded in another UIView for the text."

You could have continued using the leftView property of the UITextField such:

UIView *vwContainer = [[UIView alloc] init];
[vwContainer setFrame:CGRectMake(0.0f, 0.0f, 50.0f, 45.0f)];
[vwContainer setBackgroundColor:[UIColor clearColor]];

UIImageView *icon = [[UIImageView alloc] init];
[icon setImage:[UIImage imageNamed:@"text-input-icon-password-key.png"]];
[icon setFrame:CGRectMake(0.0f, 0.0f, 45.0f, 45.0f)];
[icon setBackgroundColor:[UIColor lightGrayColor]];

[vwContainer addSubview:icon];

[self.passwordTextField setLeftView:vwContainer];
[self.passwordTextField setLeftViewMode:UITextFieldViewModeAlways];

Solution 2

If you want full control over the custom layout then you should subclass UITextField and override both the leftViewRectForBounds: and placeholderRectForBounds: methods. Then you can return the frames for both areas and thus specify the padding in between them.

Solution 3

Here is a UITextField subclass that allows for insets on the leftView (icon), the text and the placeholder text. These are all configurable in IB

class UITextFieldWithInsets: UITextField {
    @IBInspectable var horizontalInset:CGFloat = 0
    @IBInspectable var verticalInset:CGFloat = 0

    @IBInspectable var leftViewHorizontalInset:CGFloat = 0
    @IBInspectable var leftViewVerticalInset:CGFloat = 0

    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , horizontalInset , verticalInset)
    }

    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , horizontalInset + leftViewHorizontalInset + leftViewWidth, verticalInset)
    }

    override func placeholderRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds, horizontalInset + leftViewHorizontalInset + leftViewWidth, verticalInset)
    }

    override func leftViewRectForBounds(bounds: CGRect) -> CGRect {
        let verticalInsetForCentered = (bounds.height - leftViewHeight) / 2
        return CGRect(x: leftViewHorizontalInset, y: leftViewVerticalInset > 0 ? leftViewVerticalInset : verticalInsetForCentered, width: leftViewWidth, height: leftViewHeight)
    }

    private var leftViewWidth : CGFloat { get { return leftView?.frame.width ?? 0 } }
    private var leftViewHeight : CGFloat { get { return leftView?.frame.width ?? 0 } }
}
Share:
12,699
Steve Walsh
Author by

Steve Walsh

Head of Software, Nixplay website You can see more about me here

Updated on June 04, 2022

Comments

  • Steve Walsh
    Steve Walsh almost 2 years

    I currently have the following code to setup a password textfield:

      self.passwordTextField = [UITextField new];
      self.passwordTextField.placeholder = @"Password";
      self.passwordTextField.font = [UIFont systemFontOfSize:18.f];
      self.passwordTextField.secureTextEntry = YES;
      self.passwordTextField.returnKeyType = UIReturnKeyDone;
      self.passwordTextField.delegate = self;
      self.passwordTextField.backgroundColor = [UIColor colorWithRed:255 green:255 blue:255 alpha:0.64];
      self.passwordTextField.layer.borderColor = [[UIColor lightGrayColor] CGColor];
      self.passwordTextField.layer.borderWidth = 1.0f;
    
      CGFloat textFieldHeight = 45.f;
      CGFloat textFieldWidth = 300.f;
      self.passwordTextField.frame = CGRectMake(DIALOG_VIEW_WIDTH/2.f - textFieldWidth / 2.f, 240.f, textFieldWidth, textFieldHeight);
    
      UIImageView *icon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"text-input-icon-password-key.png"]];
      icon.frame = CGRectMake(0, 0, 45.f, 45.f);
      icon.backgroundColor = [UIColor lightGrayColor];
      self.passwordTextField.leftView = icon;
      self.passwordTextField.leftViewMode = UITextFieldViewModeAlways;
    
      [self.dialogView addSubview:self.passwordTextField];
    

    which gives me this:

    enter image description here

    However, I want to add some more transparent padding to the left of the placeholder text and to the right of the image view showing the icon. Any ideas how this can be done?


    Update: Thanks for the replies. I achieved this in the end by creating a UIView for the entire object with a UIImageView for the icon and a UITextField embedded in another UIView for the text. The result was as follows:

    enter image description here

  • Steve Walsh
    Steve Walsh about 10 years
    Is there a way to do this without overriding UITextField?
  • Jano
    Jano almost 7 years
    Reader beware: with this solution the inset is applied on both sides decreasing the editing area. This can be corrected, for example, for editingRect, let the body be let xMargin = horizontalInset + leftViewHorizontalInset + leftViewWidth; return CGRect(x: xMargin, y: bounds.origin.y, width: bounds.size.width - xMargin, height: bounds.size.height)