Вставка тексту для UITextField?


Відповіді:


628

Переопределення -textRectForBounds:змінить лише вставку тексту-заповнювача. Щоб змінити вставку тексту, який можна редагувати, вам також потрібно переозначити-editingRectForBounds:

// placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

// text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

10
Це рішення працювало для мене, хоча я використовував зворотне значення CGRectInset (межі, 9, 0); Мені також потрібно було встановити це значення для textRectForBounds, editingRectForBounds та placeholderRectForBounds.
RyJ

2
Це рішення не грає добре з ClearButton. Текст всередині кнопки накладки TextField.
Пьотр

Я думаю, що переосмислення вищезазначених методів призведе до повільної прокрутки, якщо UITextFieldвона знаходиться в межах UIScrollView.
Бхарат Додея

2
Для розміщення ClearButton: - (CGRect)clearButtonRectForBounds:(CGRect)bounds { return CGRectMake(x, y, w, h); } Знайдено тут: stackoverflow.com/questions/5361369/…
Miros

22
Пропоную зателефонувати [super textRectForBounds: bunds] та [super editingRectForBounds: bounds] перед тим, як викликати CGRectInset (границі, 10, 10). Це вирішить проблему з накладанням кнопки очищення.
mrvincenzo

294

Я зміг це зробити через:

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

Звичайно, пам’ятайте, що імпортувати QuartzCore, а також додати Framework до свого проекту.


38
+1 для творчості, але це трохи проблематично, він також рухається кнопкою видалення всередині текстового поля
Микита

2
ви можете зробити myTextField.layer.sublayers, який є масивом усіх підшарів ... і якщо його UIImageView <- я припускаю, що X - це зображення .. або, можливо, UIButton ... або ви можете зациклитися на кожному з них і побачити до якого підгрупу належить ... але myfield.layer.sublayerПереформувати всі підшари і, таким чином, кнопка X переміщується ..
chuthan20

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

2
Це найкраще рішення без підкласифікації і не вимагає розміщення зайвих, зайвих поглядів на екрані! +1!
Рамбатіно

1
@ jeet.chanchawat Кнопка X праворуч на цій фотографії. developer.apple.com/library/content/documentation/…
chuthan20

169

Якщо вам потрібен лише лівий запас, ви можете спробувати це:

UItextField *textField = [[UITextField alloc] initWithFrame:...];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, textField.frame.size.height)];
leftView.backgroundColor = textField.backgroundColor;
textField.leftView = leftView;
textField.leftViewMode = UITextFieldViewModeAlways;

Це працює для мене. Я сподіваюся, що це може допомогти.


17
Це набагато простіше, ніж підкласифікація лише для отримання вставки, і дозволяє додати будь-який довільний вигляд зліва (ви можете також використовувати rightView, щоб помістити щось праворуч). Краще, ніж прийнята відповідь ІМХО.
Кенні Грант

4
+1 простий, не підкласифікований і розроблений для роботи із властивостями текстового поля (а не "злому").
Так над цим

Третій рядок повинен бути leftView.backgroundColor = textField.backgroundColor;... Окрім цього чудового рішення ... Спасибі (:
Aviel Gross

Не настільки елегантний / ретельний, як відповідь azdev, але чудове рішення для звичайного і простого випадку!
Рембрандт Q. Ейнштейн

1
Підкласифікація допоможе вам заощадити багато часу над цією відповіддю, якщо тільки у вас немає одного текстового поля для цього.
Crake

168

У класі, отриманому з UITextField, замініть принаймні ці два методи:

- (CGRect)textRectForBounds:(CGRect)bounds;
- (CGRect)editingRectForBounds:(CGRect)bounds;

Це може бути таким же простим, якщо у вас немає додаткового вмісту:

return CGRectInset(bounds , 10, 10);

UITextField надає кілька методів позиціонування, які ви можете перекрити.


2
так, якщо ви не змінюєте редагуванняRectForBounds, ви отримуєте текст під час редагування у верхньому лівому куті текстового поля. - (CGRect) редагуванняRectForBounds: (CGRect) межі {повернути CGRectInset (межі, 10, 10); }
Марк Ш

1
Щойно відредаговано відповідь, щоб інтегрувати метод редагуванняRectForBounds в
1414

5
Мені це здається жахливим злом - вам також потрібно буде переосмислити- (CGRect)borderRectForBounds:(CGRect)bounds; - (CGRect)placeholderRectForBounds:(CGRect)bounds; - (CGRect)clearButtonRectForBounds:(CGRect)bounds; - (CGRect)leftViewRectForBounds:(CGRect)bounds; - (CGRect)rightViewRectForBounds:(CGRect)bounds;
Zorayr

97

Як щодо @IBInspectable, @IBDesignableстрімкий клас.

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }
    @IBInspectable var insetY: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }
}

Ви побачите це на своїй розповіді.

введіть тут опис зображення

Оновлення - Swift 3

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 0
    @IBInspectable var insetY: CGFloat = 0

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }
}

1
Я вважав, що вплив на Y небажаний, я не хочу зменшувати пряму частину тексту, а підсунути її до базової лінії поля. Я скоригував реалізацію доlet rect = CGRect(x: bounds.minX, y: bounds.minY + insetY, width: bounds.width, height: bounds.height) return CGRectInset(rect , insetX , 0)
Chris Wagner

1
І додайте це також, якщо ви використовуєте заповнювач `override func placeholderRectForBounds (межі: CGRect) -> CGRect {return CGRectInset (межі, insetX, insetY)}`
RameshVel

Як не дивно, це (встановлення вставки в textRect/ в editingRect) впливає на продуктивність прокрутки (принаймні на iOS 12), коли текст переповнює видиму пряму. З вставкою 15 він навіть перестає прокручуватися.
Ixx

29

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

Отже, щоб переконатися, що текст не перекриває кнопку очищення, давайте superспочатку отримаємо значення "за замовчуванням" , а потім відрегулюємо за необхідності.

Цей код додасть вставки 10 пікселів у верхній, лівій і нижній частині текстового поля:

@interface InsetTextField : UITextField

@end


@implementation InsetTextField

// Placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect rect = [super textRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
    CGRect rect = [super editingRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Clear button position
- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    CGRect rect = [super clearButtonRectForBounds:bounds];

    return CGRectOffset(rect, -5, 0);
}

@end

Примітка: UIEdgeInsetsMake приймає параметри в порядку: верх , ліворуч , знизу , праворуч .


Використання textRectForBounds:та editingRectForBounds:методи без clearButtonRectForBounds: iOS 7+ працювали на мене.
оглушення

clearButtonRectForBounds:просто допомагає трохи натиснути кнопку очищення зліва. Можливо, ви хочете залишити це. Моє текстове поле було на темному тлі, і кнопка очищення потребувала трохи додаткової накладки праворуч.
Кріс Нолет

Дивно це впливає на продуктивність прокрутки (принаймні, на iOS 12), коли текст переповнює видиму пряму. З вставкою 15 він навіть перестає прокручуватися.
Ixx

22

Думав, що я поставлю швидке рішення

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    override func placeholderRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds, inset, inset) 
    }
}

Швидкий 3+

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

    // text position
    override func editingRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

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

2
Не забувайте override func placeholderRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, inset, inset) }
Євген Брагінець

В Swift 3 ви повинні використовувати 'CGRect.insetBy ()' метод
Den

1
Принаймні, в iOS 11, якщо ви перекриєте textRectForBounds, це також впливає на заповнення заповнювача, тож додавання заповнення заповнення вводить вставку ще на 10 пунктів. Якщо це те, що ви шукаєте, 👍🏼, але якщо ні, то це добре знати.
призначенийNerd

Дивно це впливає на продуктивність прокрутки (принаймні, на iOS 12), коли текст переповнює видиму пряму. З вставкою 15 він навіть перестає прокручуватися.
Іх

14

Використання textRectForBounds: - це правильний підхід. Я зафіксував це у своєму підкласі, щоб ви могли просто використовувати textEdgeInsets. Див. SSTextField .


Такий підхід, поряд із використанням какаоподів для імпорту стручка SSToolkit, чудово працює - я думаю, що це найменший шлях.
Кріс

Дякую Крис! Радий, що ти вважаєш це корисним.
Сем Софф

14

Швидкий

 class TextField: UITextField {

    let inset: CGFloat = 8

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

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }
}

Дивно це впливає на продуктивність прокрутки (принаймні, на iOS 12), коли текст переповнює видиму пряму. З вставкою 15 він навіть перестає прокручуватися.
Ixx

12

Для людей, які шукають більш легкого рішення.

Додайте UITextFieldвсередину a UIView. Для імітації вставки навколо текстового поля я тримаю 10 пікс ліворуч, а ширина на 20 пікселів менша, ніж перегляд. Для округлої кутової межі навколо текстового поля використовуйте рамку подання

viewBG.layer.cornerRadius = 8.0;
viewBG.layer.borderColor = [UIColor darkGrayColor].CGColor;
viewBG.layer.borderWidth = 1.0;

2
Чесно кажучи, просто поставити UIView за UITextField - це найкраще та найпростіше рішення. Зробіть поле UITextField прозорим і готовим. Я вирівняв його за допомогою UITextView - виявляється приблизно 6 пікселів. Набагато простіше, а також гнучкіше, ніж створення підкласу ...
n13,

Проблема такого підходу - місце розташування місця, де з’явиться смуга прокрутки.
Даг Амос

@DougAmos Що таке смуга прокрутки? Ви маєте на увазі UITextViewможливо?
значення-питання

12

Ви можете встановити вставку тексту для UITextField, встановивши leftView.

Подобається це:

UITextField *yourTextField = [[UITextField alloc] init];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
leftView.backgroundColor = [UIColor clearColor];
yourTextField.leftViewMode = UITextFieldViewModeAlways;
yourTextField.leftView = leftView;

1
Коли вам також потрібно використовувати лівий вигляд для піктограми, цей нахил може працювати
Жнець

@Reaper цей метод також буде працювати для зображення. додайте потрібну кількість прокладки до ширини кадру перегляду зображень і встановіть contentmode в центр. imageView.contentMode = UIViewContentMode.Center imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 16.0, imageView.image!.size.height)
Енді

це занадто хакі. вже існує метод textRectForBounds для встановлення вставки
Джеральд

12

Швидкий

    // adjust place holder text
    let paddingView = UIView(frame: CGRectMake(0, 0, 10, usernameOrEmailField.frame.height))
    usernameOrEmailField.leftView = paddingView
    usernameOrEmailField.leftViewMode = UITextFieldViewMode.Always

1
Це дійсно дешевий і простий спосіб вирішення. Дякую!
шназ

11

Хороший підхід для додавання прокладок до 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

Хороша відповідь. Постачає відсутнє майно :-)
phatmann

6

Swift 3 / Можливий у програмі для створення інтерфейсу / Окремі горизонтальні та вертикальні комахи / зручні для використання в коробці

@IBDesignable
class TextFieldWithPadding: UITextField {

@IBInspectable var horizontalInset: CGFloat = 0
@IBInspectable var verticalInset: CGFloat = 0

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

override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset , dy: verticalInset)
}

override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
}
}

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

використання

&

введіть тут опис зображення


5

Я робив це в IB, де я створив UIView За textView, який був трохи довше. Колір фонового тексту textField встановлений для очищення. введіть тут опис зображення


5

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

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

4

Ось той самий підклас UITextField, написаний у Swift 3. Він значно відрізняється від попередніх версій Swift, як ви побачите:

import UIKit

class MyTextField: UITextField
    {
    let inset: CGFloat = 10

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

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }

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

Між іншим, ви також можете зробити щось подібне, якщо ви хочете контролювати вкладку лише однієї сторони. Цей конкретний приклад коригування лише лівої вставки стане у нагоді, якщо ви розміщуєте зображення поверх UITextField, але хочете, щоб воно відображалось користувачеві в текстовому полі:

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

4

Версія Swift 4.2 :

import UIKit

class InsetTextField: UITextField {

  let inset: CGFloat = 10

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


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

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

}

Дивно це впливає на продуктивність прокрутки (принаймні, на iOS 12), коли текст переповнює видиму пряму. З вставкою 15 він навіть перестає прокручуватися.
Ixx

3

Ви можете налаштувати позиціонування тексту в текстовому полі, зробивши його підкласом UITextFieldта замінивши -textRectForBounds:метод.


3

Абсурдно, що вам належить підклас, оскільки вони UITextFieldвже реалізують методи, як вказує @Adam Waite. Ось швидке розширення, яке відкриває заводський метод, також доступне в наших категоріях repo :

private class InsetTextField: UITextField {
    var insets: UIEdgeInsets

    init(insets: UIEdgeInsets) {
        self.insets = insets
        super.init(frame: CGRectZero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("not intended for use from a NIB")
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return super.editingRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }
}

extension UITextField {

    class func textFieldWithInsets(insets: UIEdgeInsets) -> UITextField {
        return InsetTextField(insets: insets)
    }

}

Посилання у вашій відповіді мертве, чи можете ви її оновити?
WendiKidd

Виправлена ​​URL @WendiKidd
Крістофер Пікслі

2

Я підкласив UITextField, щоб вирішити це, що підтримує лівий, верхній, правий і нижній вставки, а також чітке позиціонування кнопок.

MRDInsetTextField.h

#import <UIKit/UIKit.h>

@interface MRDInsetTextField : UITextField

@property (nonatomic, assign) CGRect inset;

@end

MRDInsetTextField.m

#import "MRDInsetTextField.h"

@implementation MRDInsetTextField

- (id)init
{
    self = [super init];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (void)setInset:(CGRect)inset {
    _inset = inset;

    [self setNeedsLayout];
}

- (CGRect)getRectForBounds:(CGRect)bounds withInset:(CGRect)inset {

    CGRect newRect = CGRectMake(
                         bounds.origin.x + inset.origin.x,
                         bounds.origin.y + inset.origin.y,
                         bounds.origin.x + bounds.size.width - inset.origin.x - inset.size.width,
                         bounds.origin.y + bounds.size.height - inset.origin.y - inset.size.height
                         );

    return newRect;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super textRectForBounds:bounds] withInset:_inset];
}

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:bounds withInset:_inset];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super editingRectForBounds:bounds] withInset:_inset];
}

- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    return CGRectOffset([super clearButtonRectForBounds:bounds], -_inset.size.width, _inset.origin.y/2 - _inset.size.height/2);
}

@end

Приклад використання, коли * _someTextField * походить із перегляду nib / storyboard із спеціальним класом MRDInsetTextField

[(MRDInsetTextField*)_someTextField setInset:CGRectMake(5, 0, 5, 0)]; // left, top, right, bottom inset

Дякую. Одна пропозиція до вашого коду - чому ви використовували CGRect для вставки, а не UIEdgeInsets?
sha

2

Це не так коротко, як інші приклади, але вимагає зовсім іншого підходу до вирішення цієї проблеми. Зауважте, карета все ще почне переходити на лівий край, але текст буде належним чином з відступом при введенні / відображенні. Це працює без підкласифікації, якщо ви шукаєте лише лівий край і ви вже використовуєте UITextFieldDelegateдля своїх текстових полів. Потрібно встановити як текстові атрибути за замовчуванням, так і атрибути набору тексту. Ви встановлюєте текстові атрибути за замовчуванням під час створення текстового поля. Атрибути набору тексту, які потрібно встановити в делегаті. Якщо ви також використовуєте заповнювач, ви також хочете встановити його на той самий запас. Вклавши це все, ви отримуєте щось подібне.

Спочатку створіть категорію на UITextFieldуроці.

//  UITextField+TextAttributes.h

#import <UIKit/UIKit.h>

@interface UITextField (TextAttributes)

- (void)setIndent:(CGFloat)indent;

@end


//  UITextField+TextAttributes.m
#import "UITextField+TextAttributes.h"

@implementation UITextField (TextAttributes)

- (void)setTextAttributes:(NSDictionary*)textAttributes indent:(CGFloat)indent
{
    if (!textAttributes) return;

    NSMutableParagraphStyle *paragraphStyle = [textAttributes objectForKey:NSParagraphStyleAttributeName];
    paragraphStyle.firstLineHeadIndent = indent;
    paragraphStyle.headIndent = indent;
}

- (void)setIndent:(CGFloat)indent
{
   [self setTextAttributes:self.defaultTextAttributes indent:indent];
   [self setTextAttributes:self.typingAttributes indent:indent];
}

@end

Потім, якщо ви використовуєте розміщені власники, переконайтеся, що ви користуєтесь атрибутивним заповнювачем місця, встановивши той самий відступ. Створіть словник, призначений за замовчуванням, з відповідними атрибутами, приблизно таким:

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.firstLineHeadIndent = 7;
paragraphStyle.headIndent = 7;
NSDictionary *placeholderAttributes = [NSDictionary dictionaryWithObjectsAndKeys: paragraphStyle, NSParagraphStyleAttributeName, nil];

Потім імпортуйте вищевказану категорію та щоразу, коли ви створюєте текстове поле, встановіть відступ за замовчуванням, делегуйте та використовуйте атрибути заповнення за замовчуванням, визначені вище. Наприклад:

UITextField *textField = [[UITextField alloc] init];
textField.indent = 7;
textField.delegate = self;
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"Placeholder Text" attributes:placeholderAttributes];

Нарешті, в делеґаті реалізуйте textFieldDidBeginEditingметод приблизно так:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    textField.indent = 7;
}

Припущення, яке defaultTextAttributesмістить, NSMutableParagraphStyleє досить небезпечним. Я б скоріше змінявкопіювати все це.
Бен Сінклер

1

Я зазвичай намагаюся уникати підкласифікації, але це працює, якщо ви вже:

// add a property 
@property (nonatomic) UIEdgeInsets edgeInsets;

// and override:

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

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

Будь-яка причина, чому ви уникаєте підкласингу? Він є дійсним дизайн парадигми.
оглушення

1

Щоб включити інше рішення, яке не потребує підкласифікації:

UITextField *txtField = [UITextField new];
txtField.borderStyle = UITextBorderStyleRoundedRect;

// grab BG layer
CALayer *bgLayer = txtField.layer.sublayers.lastObject;
bgLayer.opacity = 0.f;

// add new bg view
UIView *bgView = [UIView new];
bgView.backgroundColor = [UIColor whiteColor];
bgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
bgView.userInteractionEnabled = NO;

[txtField addSubview: bgView];
[txtField sendSubviewToBack: bgView];

Оригінальне поле UITextField Виправлено поле UITextField

Тестовано з iOS 7 та iOS 8. Обидва працюють. Тим не менш, може виникнути шанс Apple змінити ієрархію шарів UITextField, що погано викручує речі.


1

Ось вичерпна відповідь Swift, що включає leftView (спеціальний значок) та спеціальну кнопку очищення, обидва встановлені в Interface Builder з налаштованими вставками.

import UIKit

@IBDesignable
class InsetTextField: UITextField {
@IBInspectable var leftInset:CGFloat = 0
@IBInspectable var rightInset:CGFloat = 0
@IBInspectable var icon:UIImage? { didSet {
    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 16, height: 16))
    imageView.image = icon
    self.leftView = imageView
    self.leftViewMode = .Always
} }

@IBInspectable var clearButton:UIImage? { didSet {
    let button = UIButton(type: .Custom)
    button.setImage(clearButton, forState: .Normal)
    button.addTarget(self, action: "clear", forControlEvents: UIControlEvents.TouchUpInside)
    button.frame = CGRect(x: 0, y: 0, width: 18, height: 18)
    self.rightView = button
    self.rightViewMode = .WhileEditing
} }

func clear() {
    self.text = ""
}

override func leftViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let leftView = self.leftView {
        height = leftView.bounds.height
        width = leftView.bounds.width
    }

    return CGRect(x: leftInset, y: bounds.height/2 - height/2, width: width, height: height)
}

override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let rightView = self.rightView {
        height = rightView.bounds.height
        width = rightView.bounds.width
    }

    return CGRect(x: bounds.width - width - rightInset, y: bounds.height/2 - height/2, width: width, height: height)
}

}

1

Рішення, яке фактично працює і охоплює всі випадки:

  • Слід використовувати offsetByне insetBy.
  • Також слід зателефонувати до суперфункції, щоб отримати оригінал Rect.
  • Межі несправні. вам потрібно компенсувати початкові X, Y. Штрихи мають X, Y як нулі.
  • Оригінальний x, y може бути не нульовим, наприклад, при встановленні leftView поля UITextField.

Зразок:

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return super.textRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}


override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return super.editingRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}

0

Якщо ви хочете лише змінити відступ TOP і LEFT лише тоді

// позиція заповнювача

- (CGRect)textRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

// положення тексту

- (CGRect)editingRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

-1

Швидке рішення без підкласу та також перевіряється

extension UITextField {
    @IBInspectable var textInsets: CGPoint {
            get {
                return CGPoint.zero
            }
            set {
                layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0);
            }
        }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.