Відступ тексту в поле UITextField


77

Моє запитання таке ж просте, як і назва, але ось трохи більше:

У мене є UITextField, на якому я встановив фонове зображення. Проблема полягає в тому, що текст так щільно притискається до свого краю, який також є краєм зображення. Я хочу, щоб моє текстове поле виглядало як у Apple, з невеликим горизонтальним пробілом між фоновим зображенням і місцем, де текст починається.


1
Ви маєте на увазі встановити вставки тексту? Тоді спробуйте це запитання: stackoverflow.com/questions/2694411/text-inset-for-uitextfield
phi

Ви можете додати UIImageView із зображенням, додати текстове поле поверх нього та встановити відповідно ширину текстового поля ... це найпростіший спосіб рішення ...
Swapnil Luktuke

@lukya, окрім випадків, коли він хоче, щоб область текстового поля, яку можна натиснути, включала розділ із зображенням, і в цьому випадку для вашого підходу потрібен додатковий розпізнавач жестів і якийсь код для того, щоб його зламати.
Mark Amery

Відповіді:


233

Це найшвидший спосіб, який я знайшов, не виконуючи жодних підкласів:

UIView *spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
[textfield setLeftViewMode:UITextFieldViewModeAlways];
[textfield setLeftView:spacerView];

Свіфт:

let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView

18
Це чистіше, ніж підкласифікація, І ПРАВИЛЬНО ОБРОБУЄ ЯСНУ КНОПКУ. Бажаю, щоб я міг дати +2.
Рембрандт К. Ейнштейн

8
я згоден, +2, якби міг. як тільки я прочитав "підклас" у
багатоголосній

6
Чудове рішення, щойно переклав це на Свіфт: var spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10)); textfield.leftViewMode = UITextFieldViewMode.Always textfield.leftView = spacerView
juliensaad

2
@jsiodtb Я намагався використовувати це в Swift, але це перешкоджає виконанню моєї програми. Будь-яка ідея чому? Я буду називати його в viewDidLoad(). Це теж не працює viewWillAppear().
IIllIIll

1
@Arcrammer Вам не дозволено використовувати той самий вигляд, що і подвійне заповнення (що спричиняє помилку, яку ви описали)
Норман,

41

Ви повинні підклас і перевизначити textRectForBounds: і editingRectForBounds :. Ось підклас UITextfield зі спеціальним фоном та вертикальним та горизонтальним відступом:

@interface MyUITextField : UITextField 
@property (nonatomic, assign) float verticalPadding;
@property (nonatomic, assign) float horizontalPadding;
@end

#import "MyUITextField.h"
@implementation MyUITextField
@synthesize horizontalPadding, verticalPadding;
- (CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectMake(bounds.origin.x + horizontalPadding, bounds.origin.y + verticalPadding, bounds.size.width - horizontalPadding*2, bounds.size.height - verticalPadding*2);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self textRectForBounds:bounds];
}
@end

Використання:

UIImage *bg = [UIImage imageNamed:@"textfield.png"];
CGRect rect = CGRectMake(0, 0, bg.size.width, bg.size.height);
MyUITextField *textfield = [[[MyUITextField alloc] initWithFrame:rect] autorelease];
textfield.verticalPadding = 10; 
textfield.horizontalPadding = 10;
[textfield setBackground:bg];
[textfield setBorderStyle:UITextBorderStyleNone];
[self.view addSubview:textfield];

1
Це хороше рішення, але воно не враховує кнопку Clear, коли вона видима. +1 тим не менше.
jweyrich

Чудове рішення! Не можу повірити, що Apple не дозволяє встановлювати вставки для UITextField!
RPM

@RPM Оскільки iOS 6.0 UITextView має властивість attributedText, тож ви можете встановити NSAttributedString з атрибутами NSMutableParagraphStyle + firstLineHeadIndent (і tailIndent для кнопки очищення). Але так, потрібен iOS 6.
Яно

З будь-якої причини firstLineHeadIndent в NSParagraphStyle, здається, не впливає на спосіб відображення тексту в UITextField в iOS 6.
Вільям Джокуш,

26

Хорошим підходом для додавання відступів до UITextField є підклас UITextField, перевизначення методів прямокутника та додавання властивості edgeInsets. Потім ви можете встановити edgeInsets, і UITextField буде намальовано відповідно. Це також буде коректно функціонувати із спеціальним набором leftView або rightView.

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 = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if(self){
        self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    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

Хороший і чистий підхід. Просто на замітку для інших, хто читає цей коментар: є спокуса скористатися spaceView і призначити leftView для перегляду тексту, але коли у вас багато текстових полів, ви дублюєте код навколо, додаючи spaceViews до всього вашого textField? Можливо, ні, тому перейдіть до цього підкласу, якщо у вас багато текстових полів.
Центуріон

3
Акуратний розчин. +1 за використання, UIEdgeInsetsщо, безумовно, є відповідним інструментом для вирішення завдання!
t6d

Це працює, я знайшов прийняту відповідь на збій, якщо ці UITextFields використовували авторозкладку.
elliotrock

Набагато чистіше, ніж найбільш голосована відповідь, IMO. Хороша робота.
Брайан Сачетта

Я спробував інші рішення, вони також працювали, але textRectForBounds - це правильний шлях. Дякую Броді.
сейматаноглу

13

Я перетворив це на приємне маленьке розширення для використання в Раскадровках:

public extension UITextField {
    @IBInspectable public var leftSpacer:CGFloat {
        get {
            return leftView?.frame.size.width ?? 0
        } set {
            leftViewMode = .Always
            leftView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
        }
    }
}

1
Цей працює чудово. Якщо ви використовуєте його з @IBDesignable, ви можете побачити його в розкадруванні
anasaitali

4

Мої 2 центи:

class PaddedTextField : UITextField {
    var insets = UIEdgeInsets.zero
    var verticalPadding:CGFloat = 0
    var horizontalPadding:CGFloat = 0

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(x: bounds.origin.x + insets.left, y: bounds.origin.y + insets.top, width: bounds.size.width - (insets.left + insets.right), height: bounds.size.height - (insets.top + insets.bottom));
    }

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

1

Я пропоную перетворити ваш UITextFieldна a UITextViewта встановити contentInset. Наприклад, щоб зробити відступ на 10 пробілів:

textview.contentInset=UIEdgeInsetsMake(0, 10, 0, 0);

це насправді хороше рішення, не впевнене, чому воно було проти.
Jeremie D

2
@Jeremie це тому, що це не відповідає на питання. UITextField та UITextView поводяться по-різному, і вам доведеться суттєво змінити текстовий вигляд, щоб він поводився як текстове поле
Кріс,

0

Іноді leftView of the textField - це зображення лупи Apple. Якщо так, ви можете встановити такий відступ:

    UIView *leftView = textField.leftView;
    if (leftView && [leftView isKindOfClass:[UIImageView class]]) {
        leftView.contentMode = UIViewContentModeCenter;
        leftView.width = 20.0f;  //the space you want indented.
    }

0

Якщо ви не хочете створювати @ IBOutlet's, можете просто підклас (відповідь у Swift):

class PaddedTextField: UITextField {

  override func awakeFromNib() {
      super.awakeFromNib()

      let spacerView = UIView(frame:CGRect(x: 0, y: 0, width: 10, height: 10))
      leftViewMode = .always
      leftView = spacerView
   }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.