Đặt phần đệm cho UITextField với UITextBorderStyleNone


399

Tôi muốn sử dụng một nền tùy chỉnh cho tôi UITextFields. Điều này hoạt động tốt, ngoại trừ thực tế là tôi phải sử dụng UITextBorderStyleNoneđể làm cho nó trông đẹp. Điều này buộc văn bản dính vào bên trái mà không có bất kỳ phần đệm.

Tôi có thể đặt phần đệm thủ công để nó trông tương tự UITextBorderStyleRoundedRectngoại trừ việc sử dụng hình nền tùy chỉnh của tôi không?

Câu trả lời:


837

Tôi tìm thấy một bản hack nhỏ gọn để đặt phần đệm bên trái cho tình huống chính xác này.

Về cơ bản, bạn đặt thuộc tính bên trái của UITextFieldchế độ xem thành chế độ xem trống về kích thước của phần đệm bạn muốn:

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

Làm việc như một cơ duyên cho tôi!

Trong Swift 3 / Swift 4 , có thể được thực hiện bằng cách làm điều đó

let paddingView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 20))
textField.leftView = paddingView
textField.leftViewMode = .always

1
Chính xác những gì tôi cần, ngoại trừ tôi cần đệm ở bên phải, hầu như giống nhau, tất nhiên. Cảm ơn!
cg.

@Lukasz Tôi đã thêm một autorelease cho câu trả lời này, câu trả lời được chấp nhận. Dòng đầu tiên. EDIT: Rất tiếc, có lẽ tôi đã không lưu? hoặc chỉnh sửa của tôi đã bị từ chối? Dù bằng cách nào, Vincent đã thêm vào một bản tự động, vì vậy yay cho điều đó!
Eric Goldberg

1
Sử dụng ARC, tại sao ứng dụng của tôi bị treo và sử dụng nhiều CPU nếu tôi sử dụng lại *paddingViewvới nhiều trường văn bản?
Người đàn ông Muffin

3
Đó là một giải pháp tồi, tốt hơn hết là dùng cho Nate Flink. Thios một không bao gồm đệm chế độ editiong.
Jacek Kwiecień

3
Nó không hoạt động với nhiều trường văn bản. Chỉ cần tiêu thụ rất nhiều bộ nhớ và sau đó sụp đổ.
lồng chim

177

Tôi đã tạo ra thực hiện thể loại này và thêm nó vào đầu .mtập tin.

@implementation UITextField (custom)
    - (CGRect)textRectForBounds:(CGRect)bounds {
        return CGRectMake(bounds.origin.x + 10, bounds.origin.y + 8,
                          bounds.size.width - 20, bounds.size.height - 16);
    }
    - (CGRect)editingRectForBounds:(CGRect)bounds {
        return [self textRectForBounds:bounds];
    }
@end

Dựa trên liên kết Piotr Blasiak cung cấp. Nó dường như đơn giản hơn sau đó tạo ra một lớp con hoàn toàn mới, và cũng đơn giản hơn sau đó thêm phần bổ sung UIView. Tuy nhiên, có vẻ như thiếu một cái gì đó để không thể kiểm soát phần đệm bên trong một trường văn bản.

Giải pháp Swift 4:

class CustomTextField: UITextField {
    struct Constants {
        static let sidePadding: CGFloat = 10
        static let topPadding: CGFloat = 8
    }

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(
            x: bounds.origin.x + Constants.sidePadding,
            y: bounds.origin.y + Constants.topPadding,
            width: bounds.size.width - Constants.sidePadding * 2,
            height: bounds.size.height - Constants.topPadding * 2
        )
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return self.textRect(forBounds: bounds)
    }
}

6
Điều này ném cảnh báo về các thể loại ghi đè phương pháp. Xem câu trả lời này để đàn áp họ.
pdenya

5
Tôi không thích làm điều này trong một danh mục, nhưng khác hơn là đây là một giải pháp sạch hơn câu trả lời được chấp nhận.
Bob Vork

2
Tốt hơn là sử dụng CGRectInset () cho một cái gì đó như thế này, thay vì tự lăn. Nó cũng trông gọn gàng hơn một chút: trả về CGRectInset (giới hạn, 10, 8);
Dennis Munsie

1
@shashwat có, bạn có thể chỉ định bất kỳ phần đệm nào bạn muốn
Ege Akpinar

1
Khi tôi thêm điều này 4 năm trước, mọi thứ đã khác với iOS và tôi đồng ý rằng bây giờ tốt nhất là tạo một lớp con. Tuy nhiên, nếu bạn chỉ muốn một cách nhanh chóng và bẩn thỉu để kiểm tra trực quan khoảng cách pixel của mình, thì điều này sẽ làm được;) Vì vậy, mọi người cứ bình chọn !!
Nate Flink

139

Phiên bản Swift 3 cho Xcode> 6, trong đó bạn có thể chỉnh sửa giá trị chèn trong Trình tạo giao diện / Bảng phân cảnh.

import UIKit

@IBDesignable
class FormTextField: UITextField {

    @IBInspectable var inset: CGFloat = 0

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return textRect(forBounds: bounds)
    }

}

nhập mô tả hình ảnh ở đây


1
Tôi không thấy trường văn bản mẫu của tôi.
okysabeni

2
Tôi cần thêm dòng nàyoverride func placeholderRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, inset, inset) }
Michael

2
Câu trả lời này sẽ hữu ích hơn với một lời giải thích hoặc liên kết đến lời giải thích về những gì @IBDesignable@IBInspectablelàm, tức là bài đăng này tại nshipster
Russell Austin

1
Nếu bạn đang dựa vào bất kỳ chế độ xem phụ kiện nào (chẳng hạn như chức năng nút xóa trên UITextField) thì return super.textRectForBounds(CGRectInset(bounds, inset, inset))sẽ xử lý phần bù từ chế độ xem phụ kiện đúng cách.
Mike Fay

@okysabeni bạn cần nhấp vào trường văn bản của mình và thay đổi Class thành FormTextField
Gustavo Barbosa

77

Chỉnh sửa: Vẫn hoạt động trong iOS 11.3.1

Trong iOS 6 myTextField.leftView = paddingView;đang gây ra sự cố

Điều này giải quyết vấn đề

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0)

Đối với trường văn bản căn chỉnh phù hợp, sử dụng CATransform3DMakeTranslation(-5, 0, 0)như được đề cập bởi latenitecoder trong các bình luận


1
Thật tuyệt, tôi đã phải đặt phần đệm vào tất cả các trường văn bản của ứng dụng, tôi đã tạo một danh mục UITextField và đặt mã này vào bên trong - (void) awakeFromNib {} và điều này đã giải quyết vấn đề của tôi
Teena nath Paul

Quá đơn giản! Thx :) Tôi có một câu hỏi làm thế nào tôi có thể tạo một mã đơn giản để tạo tất cả UITextField thay vì viết mã nhiều lần?
Luai Kalkatawi

1
Tất cả các ý kiến ​​khác cho rằng bạn muốn đệm một UITextField từ bên trái. Phân lớp là rất nhiều chi phí để thêm một số id khoảng cách thay vì chỉ thêm một số ký tự trống nhưng giải pháp này là giải pháp. Một dòng bằng chứng trong tương lai. Nếu bạn đang làm việc với một trường văn bản được căn chỉnh đúng văn bản, hãy sử dụng giá trị âm (-5,0,0) Cảm ơn Inder
latenitecoder

1
Sau 4 năm tôi đã tìm thấy câu trả lời của riêng mình: D, @latenitecoder bình luận của bạn là những gì cần thiết. Cập nhật câu trả lời
Inder Kumar Rathore

1
Tôi có thể làm gì nếu tôi muốn cả đệm phải và trái ??
Mina Hanna

70

Một cách tiếp cận tốt để thêm phần đệm vào UITextField là phân lớp và thêm thuộc tính edgeInsets. Sau đó, bạn đặt edgeInsets và UITextField sẽ được vẽ tương ứng. Điều này cũng sẽ hoạt động chính xác với một tập hợp leftView hoặc rightView tùy chỉnh.

OSTextField.h

#import <UIKit/UIKit.h>

@interface OSTextField : UITextField

@property (nonatomic, assign) UIEdgeInsets edgeInsets;

@end

OSTextField.m

#import "OSTextField.h"

@implementation OSTextField

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.edgeInsets = UIEdgeInsetsZero;
    }
    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if(self){
        self.edgeInsets = UIEdgeInsetsZero;
    }
    return self;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

@end

Điều này nên được chấp nhận câu trả lời. Nó cũng hoạt động cho các chế độ xem phải và trái ..
NSPratik

25

Chỉ cần phân lớp UITextField như thế này:

@implementation DFTextField


- (CGRect)textRectForBounds:(CGRect)bounds
{
    return CGRectInset(bounds, 10.0f, 0);
}

- (CGRect)editingRectForBounds:(CGRect)bounds
{
    return [self textRectForBounds:bounds];
}


@end

Điều này thêm phần đệm ngang 10 điểm ở hai bên.


21

Mã C khách quan

MyTextField.h

#import <UIKit/UIKit.h>

@interface MyTextField : UITextField

@property (nonatomic) IBInspectable CGFloat padding;

@end

MyTextField.m

#import "MyTextField.h"

IB_DESIGNABLE
@implementation MyTextField

@synthesize padding;

-(CGRect)textRectForBounds:(CGRect)bounds{
    return CGRectInset(bounds, padding, padding);
}

-(CGRect)editingRectForBounds:(CGRect)bounds{
    return [self textRectForBounds:bounds];
}

@end

nhập mô tả hình ảnh ở đây



20
  1. Tạo một trường văn bản

PaddingTextField.swift

import UIKit
class PaddingTextField: UITextField {

@IBInspectable var paddingLeft: CGFloat = 0
@IBInspectable var paddingRight: CGFloat = 0

override func textRectForBounds(bounds: CGRect) -> CGRect {
    return CGRectMake(bounds.origin.x + paddingLeft, bounds.origin.y,
        bounds.size.width - paddingLeft - paddingRight, bounds.size.height);
}

override func editingRectForBounds(bounds: CGRect) -> CGRect {
    return textRectForBounds(bounds)
}}
  1. Đặt lớp trường văn bản của bạn là PaddingTextField và tùy chỉnh phần đệm của bạn theo ý muốn nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

  2. Tận hưởng nó

sau cùng


19

Dựa trên câu trả lời của Evil Trout, bạn có thể muốn tạo một danh mục để giúp sử dụng dễ dàng hơn trên nhiều ứng dụng.

Tập tin tiêu đề:

@interface UITextField (PaddingText)

-(void) setLeftPadding:(int) paddingValue;

-(void) setRightPadding:(int) paddingValue;
@end

Hồ sơ thực hiện:

#import "UITextField+PaddingText.h"

@implementation UITextField (PaddingText)

-(void) setLeftPadding:(int) paddingValue
{
    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, paddingValue, self.frame.size.height)];
    self.leftView = paddingView;
    self.leftViewMode = UITextFieldViewModeAlways;
}

-(void) setRightPadding:(int) paddingValue
{
    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, paddingValue, self.frame.size.height)];
    self.rightView = paddingView;
    self.rightViewMode = UITextFieldViewModeAlways;
}

@end

Ví dụ sử dụng

#import "UITextField+PaddingText.h"

[self.YourTextField setLeftPadding:20.0f];

Hy vọng nó sẽ giúp bạn ra ngoài

Chúc mừng


14

Phiên bản Swift:

extension UITextField {
    @IBInspectable var padding_left: CGFloat {
        get {
            LF.log("WARNING no getter for UITextField.padding_left")
            return 0
        }
        set (f) {
            layer.sublayerTransform = CATransform3DMakeTranslation(f, 0, 0)
        }
    }
}

Để bạn có thể gán giá trị trong IB

Cài đặt IBInspectable được trình bày trong Trình tạo giao diện


IBInspectablecho phép bạn áp dụng mã setter khi chạy, vì vậy chỉ cần đặt số của bạn vào Interface Buildervà nó sẽ hoạt động.
superarts.org

Điều này sẽ không hoạt động khi bạn có Clear Button. Nút xóa của bạn sẽ không hiển thị nếu áp dụng giải pháp này.
Bhavin_m

11

Bạn không thể đặt đệm. Thay vào đó có một UIViewhình ảnh nền của bạn và UITextFieldbên trong của nó. Đặt UITextFieldchiều rộng là UIViewWidth-(paddingSize x 2)và chiều cao tương tự và sau đó đặt nó tại điểm paddingSize,paddingSize.


10

Chỉ cần phân lớp UITextField như thế này ( phiên bản Swift ):

import UIKit

class CustomTextField: UITextField {

    override func textRectForBounds(bounds: CGRect) -> CGRect {
       return CGRectInset(bounds, 25.0, 0)
    }

    override func editingRectForBounds(bounds: CGRect) -> CGRect {
       return self.textRectForBounds(bounds)
    }

}

Điều này thêm phần đệm ngang 25,0 điểm ở hai bên.


8

Tôi đã dựa trên giải pháp của Nate, nhưng sau đó tôi thấy rằng điều này gây ra vấn đề khi bạn sử dụng các thuộc tính leftView / rightView, vì vậy nó sẽ điều chỉnh tốt hơn việc triển khai của siêu, bởi vì nó sẽ tính đến chế độ xem trái / phải.

- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect ret = [super textRectForBounds:bounds];
    ret.origin.x = ret.origin.x + 5;
    ret.size.width = ret.size.width - 10;
    return ret;
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self textRectForBounds:bounds];
}

6

Phiên bản cập nhật cho Swift 3:

@IBDesignable
class FormTextField: UITextField {

    @IBInspectable var paddingLeft: CGFloat = 0
    @IBInspectable var paddingRight: CGFloat = 0

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(x: bounds.origin.x + paddingLeft, y: bounds.origin.y, width: bounds.size.width - paddingLeft - paddingRight, height: bounds.size.height)
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return textRect(forBounds: bounds)
    }
}

6

Đặt phần đệm cho UITextField với UITextBorderStyleNone: Swift

Dựa trên câu trả lời được bình chọn nhiều nhất của @Evil Trout, tôi đã tạo một phương thức tùy chỉnh trong lớp ViewContoder của mình, như được hiển thị dưới đây:

- (void) modifyTextField:(UITextField *)textField
{
    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
    textField.leftView = paddingView;
    textField.leftViewMode = UITextFieldViewModeAlways;
    textField.rightView = paddingView;
    textField.rightViewMode = UITextFieldViewModeAlways;

    [textField setBackgroundColor:[UIColor whiteColor]];
    [textField setTextColor:[UIColor blackColor]];
}

Bây giờ tôi có thể gọi phương thức đó bên trong (phương thức viewDidLoad) và gửi bất kỳ TextField nào của tôi đến phương thức đó và thêm phần đệm cho cả bên phải và bên trái, và đưa ra màu văn bản và màu nền bằng cách chỉ viết một dòng mã, như sau:

[self modifyTextField:self.firstNameTxtFld];

Điều này đã hoạt động hoàn hảo trên iOS 7! Tôi biết rằng việc thêm quá nhiều Lượt xem có thể khiến lớp này nặng hơn một chút. Nhưng khi lo ngại về sự khó khăn trong các giải pháp khác, tôi thấy mình thiên vị hơn với phương pháp này và linh hoạt hơn khi sử dụng cách này. ;)

Cảm ơn Hack "Evil Trout"! (cây cung)

Tôi nghĩ rằng tôi nên cập nhật đoạn mã câu trả lời này với Swift:

Vì Swift cho phép chúng ta viết các phần mở rộng cho các lớp hiện có, hãy viết nó theo cách đó.

extension UITextField {
    func addPaddingToTextField() {
        let paddingView: UIView = UIView.init(frame: CGRectMake(0, 0, 8, 20))
        self.leftView = paddingView;
        self.leftViewMode = .Always;
        self.rightView = paddingView;
        self.rightViewMode = .Always;


        self.backgroundColor = UIColor.whiteColor()
        self.textColor = UIColor.blackColor()
    }
}

Sử dụng:

self.firstNameTxtFld.addPaddingToTextField()

Hy vọng điều này sẽ hữu ích cho người khác ngoài kia!
Chúc mừng!


5

Đây là cách để đạt được điều này trong SWIFT

@IBOutlet weak var yourTextField: UITextField!

override func viewDidLoad() {
super.viewDidLoad()
let paddingView = UIView(frame: CGRectMake(0, 0, 10, self.yourTextField.frame.height))
yourTextField.leftView = paddingView
yourTextField.leftViewMode = UITextFieldViewMode.Always
}
}

Nguồn


5

Phiên bản Swift 2.0:

let paddingView: UIView = UIView(frame: CGRectMake(0, 0, 5, 20))
textField.leftView = paddingView
textField.leftViewMode = UITextFieldViewMode.Always;

4

^ những đề xuất này rất tốt cho những người lập trình tạo giao diện.

Nhưng có hai CÁCH DỄ DÀNG LAZY cho những người trong chúng ta sử dụng trình tạo giao diện Xcode:

  • dễ dàng hơn: đặt UIImageView phía sau trường văn bản

  • dễ nhất: thay đổi kiểu viền trên hình vuông màu đen đơn giản (tùy chọn thứ hai từ bên trái), sau đó thêm hình ảnh của bạn làm hình nền. Hình ảnh được ưu tiên hơn hình vuông, vì vậy bạn vẫn có được phần đệm cần thiết cho nền hình ảnh bình thường, mà không có hình vuông thực sự được vẽ trên đó.

EDIT: bạn cũng có thể sử dụng hình cầu màu đen (tùy chọn thứ ba từ bên trái khi chọn UITextBox trong IB), nó không hoạt động với kiểu "hình cầu đồ họa" ở bên phải.


Giải pháp dễ dàng hơn của bạn thực sự là một lựa chọn hợp lệ trong một số trường hợp, nhưng giải pháp đơn giản nhất của bạn là hack, cũng không hoạt động nếu các pixel cạnh của hình ảnh của bạn có biến alpha (chưa kể Apple có thể thay đổi cách triển khai của chúng trong bản phát hành iOS trong tương lai).
jmdecombe 4/2/2015

Tôi không đồng ý với bạn - đó là lý do tại sao tôi đặt "cách dễ dàng lười biếng" trong tất cả các chữ cái mũ. Nó làm việc tốt cho tôi cho đến nay.
woody121

4

Nếu bất cứ ai đang tìm kiếm Swift 4.0phiên bản thì dưới đây extensionlà công việc. Nó có cả hai LeftRightđệm cho UITextField. Thực sự nó làIBInspectable cho cấu hình cốt truyện. Bạn có thể đặt giá trị trực tiếp từ Trình tạo giao diện / Bảng phân cảnh. Đây là mã được thử nghiệm trong phiên bản Swift 4.0 và Xcode 9.0

Hãy nhớ rằng nếu bạn muốn bật Clear Buttontương tự UITextFieldthì bạn phải giữ Quyền đệm trống.

import UIKit

extension UITextField {

    @IBInspectable var paddingLeft: CGFloat {
        get {
            return leftView!.frame.size.width
        }
        set {
            let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
            leftView = paddingView
            leftViewMode = .always
        }
    }

    @IBInspectable var paddingRight: CGFloat {
        get {
            return rightView!.frame.size.width
        }
        set {
            let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
            rightView = paddingView
            rightViewMode = .always     
        }
    }
}  

3

Cách tốt nhất để làm điều này chỉ đơn giản là tạo một lớp bằng cách sử dụng lớp con của UITextField và trong tệp .m

 #import "CustomTextField.h"
 #import <QuartzCore/QuartzCore.h>
 @implementation CustomTextField


- (id)initWithCoder:(NSCoder*)coder 
 {
  self = [super initWithCoder:coder];

  if (self) {

//self.clipsToBounds = YES;
//[self setRightViewMode:UITextFieldViewModeUnlessEditing];

self.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,15,46)];
self.leftViewMode=UITextFieldViewModeAlways;
   }

  return self;

 }

bằng cách này, hãy vào bảng phân cảnh hoặc xib của bạn và nhấp vào trình kiểm tra danh tính và thay thế UITextfield bằng tùy chọn "CustomTextField" của riêng bạn trong tùy chọn lớp.

Lưu ý: Nếu bạn chỉ đơn giản cung cấp phần đệm với bố cục tự động cho trường văn bản thì ứng dụng của bạn sẽ không chạy và chỉ hiển thị màn hình trống.


3

Phiên bản Swift 3:

class CustomTextField:UITextField{

    required init?(coder aDecoder: NSCoder){
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect.init(x: bounds.origin.x + 8, y: bounds.origin.y, width: bounds.width, height: bounds.height)
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return self.textRect(forBounds:bounds)
    }
}

2

Câu trả lời của Nate Flink là sở thích của tôi, nhưng đừng quên quan điểm phải / trái. Ví dụ: cho UITextFieldlớp con:

override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
    let rightViewBounds = super.rightViewRectForBounds(bounds)

    return CGRectMake(CGRectGetMinX(rightViewBounds) - 10, CGRectGetMinY(rightViewBounds), CGRectGetWidth(rightViewBounds), CGRectGetHeight(rightViewBounds))
}

Mã ở trên đệm đúng thiết lập cho rightViewcác UITextField.


2

Giải pháp Swift 3

class CustomTextField: UITextField {

 override func textRect(forBounds bounds: CGRect) -> CGRect {
  return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y + 8, width: bounds.size.width - 20, height: bounds.size.height - 16)
 }

 override func editingRect(forBounds bounds: CGRect) -> CGRect {
  return self.textRect(forBounds: bounds)
 }
}

2

Đây là mã Swift để cung cấp phần đệm trong UITextfield

 func txtPaddingVw(txt:UITextField) {
     let paddingView = UIView(frame: CGRectMake(0, 0, 10, 10))
     txt.leftViewMode = .Always
     txt.leftView = paddingView
 }

và gọi bằng cách sử dụng

self.txtPaddingVw(txtPin)

2

bạn có thể sử dụng thể loại. đặt đệm sang trái và phải

UITextField + Padding.h

@interface UITextField (Padding)
@property (nonatomic, assign) CGFloat paddingValue;
@property (nonatomic, assign) CGFloat leftPadding;
@property (nonatomic, assign) CGFloat rightPadding;

//overwrite
-(CGRect)textRectForBounds:(CGRect)bounds;
-(CGRect)editingRectForBounds:(CGRect)bounds;
@end

UITextField + Padding.m

#import "UITextField+Padding.h"
#import <objc/runtime.h>

static char TAG_LeftPaddingKey;
static char TAG_RightPaddingKey;
static char TAG_Left_RightPaddingKey;

@implementation UITextField (Padding)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
-(CGRect)textRectForBounds:(CGRect)bounds {

CGFloat offset_Left=0;
CGFloat offset_Right=0;
if (self.paddingValue>0) {
    offset_Left=self.paddingValue;
    offset_Right=offset_Left;
}else{
    if (self.leftPadding>0){
        offset_Left=self.leftPadding;
    }
    if (self.rightPadding>0){
        offset_Right=self.rightPadding;
    }
}

if (offset_Left>0||offset_Right>0) {
    return CGRectMake(bounds.origin.x+ offset_Left ,bounds.origin.y ,
                      bounds.size.width- (offset_Left+offset_Right), bounds.size.height-2 );
 }else{
    return bounds;
 }
}



-(CGRect)editingRectForBounds:(CGRect)bounds {
    return [self textRectForBounds:bounds];
}
#pragma clang diagnostic pop


#pragma maek -setter&&getter
- (CGFloat)paddingValue
{
    return [objc_getAssociatedObject(self,&TAG_Left_RightPaddingKey) floatValue];
}
-(void)setPaddingValue:(CGFloat)paddingValue
{
    objc_setAssociatedObject(self, &TAG_Left_RightPaddingKey, @(paddingValue), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(CGFloat)leftPadding
{
    return [objc_getAssociatedObject(self,&TAG_LeftPaddingKey) floatValue];
}

-(void)setLeftPadding:(CGFloat)leftPadding
{
    objc_setAssociatedObject(self, &TAG_LeftPaddingKey, @(leftPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(CGFloat)rightPadding
{
    return [objc_getAssociatedObject(self,&TAG_RightPaddingKey) floatValue];
}

-(void)setRightPadding:(CGFloat)rightPadding
{
    objc_setAssociatedObject(self, &TAG_RightPaddingKey, @(rightPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

bạn có thể đặt phần đệm như thế này.phoneNumTF.paddingValue = 10.f; hoặc tự.phoneNumTF.leftPadding = 10.f;


1

Câu trả lời của @Evil là tuyệt vời. Tôi đã sử dụng phương pháp này khá lâu rồi. Điều duy nhất nó thiếu là "xử lý nhiều trường văn bản". Tôi đã thử các cách tiếp cận khác nhưng dường như không hiệu quả.

Phân lớp UITextField chỉ để thêm phần đệm không có ý nghĩa gì với tôi. Vì vậy, tôi đã lặp lại tất cả các UITextField để thêm phần đệm.

-(void) addPaddingToAllTextFields:(UIView*)view {

    for(id currentView in [view subviews]){
        if([currentView isKindOfClass:[UITextField class]]) {
            // Change value of CGRectMake to fit ur need
            [currentView setLeftView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)]];
            [currentView setLeftViewMode:UITextFieldViewModeAlways];
        }

        if([currentView respondsToSelector:@selector(subviews)]){
            [textfieldarray addObjectsFromArray:[self addPaddingToAllTextFields:currentView]];
        }
    }
}

phương thức có thể được gọi bởi [self addPaddingTo ALLTextFields: [self view]];
Kishor Kundan

textfieldarraykhông được xác định trong ifkhối thứ hai , tôi đã sử dụng đoạn trích này (cảm ơn!) Thành công sau khi thay thế nội dung của khối thứ hai ifbằngfor(id subSubView in [view subviews]){[self addPaddingToAllTextFields:subSubView];}
adamup

1

Giải pháp của Brody làm việc hoàn hảo cho tôi. Tôi đã phải thêm các khung nhìn bên trên một trường văn bản và thêm phần đệm bổ sung. Vì vậy, bằng cách triển khai thuộc tính UIEdgeInsets tùy chỉnh cho lớp con UITextField, tôi đã quản lý để đạt được nhiệm vụ. Tôi sẽ sử dụng lớp con mới này trong tất cả các dự án của tôi.


1

Giải pháp tốt nhất tôi tìm thấy cho đến nay là một thể loại. Đó là cách tôi thêm phần đệm 5 điểm vào bên trái và bên phải:

@implementation UITextField (Padding)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectMake(bounds.origin.x + 5, bounds.origin.y,
                      bounds.size.width - 10, bounds.size.height);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self textRectForBounds:bounds];
}
#pragma clang diagnostic pop

@end

Các # pragma chỉ để xóa các cảnh báo gây phiền nhiễu


Điều với quá tải phương thức trong các danh mục là, nó sẽ được đánh dấu là không được sử dụng trong AppCode, thực tế nó là như vậy. Ý tưởng tốt, nhưng không an toàn lắm vì nó dễ dàng bị xóa khi bạn chạy "Tối ưu hóa nhập khẩu" (không có vấn đề gì với người dùng Xcode, nhưng tất cả chúng ta đều biết các tính năng tập trung vào mã giới hạn)
Sebastian Wramba

1
Đây có phải là một danh mục đơn giản sẽ áp dụng phần đệm cho tất cả các trường văn bản trong ứng dụng không?
Ben Sinclair

@Andy không chỉ áp dụng khi bạn nhập nó, bạn sẽ cần tạo một lớp UITextField + Padding và nhập nó trong trình điều khiển khung nhìn hoặc lớp bạn có một trường văn bản với phần đệm
Mongi Zaidi

@MongiZaidi: bạn sai rồi. Nó được liên kết vào thực thi, cho dù được nhập khẩu là không liên quan.
Zsolt Szatmari

1
textField.layer.borderWidth = 3;

sẽ thêm đường viền, làm việc như đệm cho tôi.


0

Một cân nhắc khác là, nếu bạn có nhiều hơn một UITextFieldnơi bạn đang thêm phần đệm, là tạo một phần riêng UIViewcho từng trường văn bản - bởi vì chúng không thể được chia sẻ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.