UITextfield leftView / rightView відступ на iOS7


94

Подання leftView та rightView UITextField на iOS7 дуже близькі до межі текстового поля.

Як я можу додати трохи (горизонтальних) відступів до цих елементів?

Я спробував змінити кадр, але не вдалося

uint padding = 10;//padding for iOS7
UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);
textField.leftView = iconImageView;

Зверніть увагу, що я не зацікавлений додавати відступ до тексту текстового поля, наприклад, цей Встановити відступ для UITextField за допомогою UITextBorderStyleNone


можливий дублікат вставки тексту для UITextField?
Zorayr

1
Ні, це питання про відступ зображення, яке відображається як лівий перегляд у текстовому полі. Не відступаючи сам текст. Спробуйте його код, і ви побачите, що параметр leftView для зображення розміщує це зображення до лівого краю текстового поля, без відступів. Це виглядає потворно.
камінь

Відповіді:


90

Я просто працював над цим і використовував таке рішення:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

    CGRect textRect = [super rightViewRectForBounds:bounds];
    textRect.origin.x -= 10;
    return textRect;
}

Це перемістить зображення праворуч на 10, замість того, щоб його стискати до краю в iOS 7.

Крім того, це було в підкласі UITextField, який можна створити:

  1. Створіть новий файл, який є підкласом UITextFieldзамість типовогоNSObject
  2. Додайте новий метод з іменем - (id)initWithCoder:(NSCoder*)coderдля встановлення зображення

    - (id)initWithCoder:(NSCoder*)coder {
        self = [super initWithCoder:coder];
    
        if (self) {
    
            self.clipsToBounds = YES;
            [self setRightViewMode:UITextFieldViewModeUnlessEditing];
    
            self.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"textfield_edit_icon.png"]];
        }
    
        return self;
    }
  3. Можливо, доведеться імпортувати #import <QuartzCore/QuartzCore.h>

  4. Додайте rightViewRectForBoundsметод вище

  5. У Interface Builder клацніть на поле TextField, яке ви хочете зробити підкласом, і змініть атрибут класу на ім'я цього нового підкласу


як використовувати IBDesignable для цього самого?
riddhi

для останньої версії або , якщо ви читаєте це в 2020 р по адресою: stackoverflow.com/a/55041786/6596443
AKINNUBI Абіола Сильвестра

167

Набагато простіше рішення, яке використовує contentMode:

    arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"down_arrow"]];
    arrow.frame = CGRectMake(0.0, 0.0, arrow.image.size.width+10.0, arrow.image.size.height);
    arrow.contentMode = UIViewContentModeCenter;

    textField.rightView = arrow;
    textField.rightViewMode = UITextFieldViewModeAlways;

У Swift 3,

    let arrow = UIImageView(image: UIImage(named: "arrowDrop"))
    if let size = arrow.image?.size {
        arrow.frame = CGRect(x: 0.0, y: 0.0, width: size.width + 10.0, height: size.height)
    }
    arrow.contentMode = UIViewContentMode.center
    self.textField.rightView = arrow
    self.textField.rightViewMode = UITextFieldViewMode.always

1
Ви також можете використовувати ScaleAspectFit замість центру ... якщо розмір зображення не відповідає точному кадру.
Mihir Mehta,

Я використав ваш приклад для UIButton (замість UIImageView), тоді як його тип InfoLight.
OhadM

Я виявив, що ".right" замість ".center" робить його більш схожим на вбудований рядок пошуку, такий як той, що знаходиться в додатку Контакти. Чудове рішення щодо цього, дякую за розміщення.
Джеймс Тумі

Або якщо вам потрібно бути точним у дизайні, розмістіть зображення вліво, а потім збільште ширину, щоб досягти точного заповнення
jovanjovanovic

4
Здається, це вже не працює з iOS 13 та Xcode 11 Beta 7. Хоча це добре працює на iOS 11/12.
PatrickDotStar

49

Найпростіший спосіб - додати UIView до leftView / righView та додати ImageView до UIView, відрегулювати походження ImageView всередині UIView де завгодно, це спрацювало для мене як заклинання. Для цього потрібно лише кілька рядків коду

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 26, 26)];
imgView.image = [UIImage imageNamed:@"img.png"];

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[paddingView addSubview:imgView];
[txtField setLeftViewMode:UITextFieldViewModeAlways];
[txtField setLeftView:paddingView];

UIViewContentMode не працює, але ця відповідь працює як шарм!
nigong

14

Це чудово працює для Свіфта:

let imageView = UIImageView(image: UIImage(named: "image.png"))
imageView.contentMode = UIViewContentMode.Center
imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 20.0, imageView.image!.size.height)
textField.rightViewMode = UITextFieldViewMode.Always
textField.rightView = imageView

не вдається перетворити значення типу "рядок" у очікуваний тип аргументу "UIImage?"

7

Це працює для мене

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

Нехай це допоможе вам.


6

Мені подобається це рішення, оскільки воно вирішує проблему одним рядком коду

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10.0f, 0.0f, 0.0f);

Примітка: .. або 2, якщо ви розглядаєте можливість включення рядка QuartzCore :)


1
Це також
зміщує

1
але не вирішує проблему з правим заповненням лише проблему з лівим заповненням
carmen_munich

1
Я мав кращий результат, використовуючи rightView.layer.sublayerTransform = CATransform3DMakeTranslation (-10.0f, 0.0f, 0.0f), але +1 для методу
Тібо Девід

Майте на увазі, це також змістить кнопку "очистити" текстове поле праворуч, що може пересунути його за край текстового поля. Якщо вам не потрібна кнопка очищення, це чудовий підхід, інакше, можливо, ні.
Том Гаррінгтон,

4

Найкращий спосіб зробити це - просто створити клас, використовуючи підклас UITextField та файл .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;

}

виконавши це, перейдіть до своєї розкадровки або xib і натисніть на інспектор ідентифікації та замініть UITextfield на свій власний "CustomTextField" у варіанті класу.

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


4

Замість маніпуляції imageView або image ми можемо замінити метод, наданий apple для rightView.

class CustomTextField : UITextField { 

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
    let offset = 5
    let width  = 20
    let height = width
    let x = Int(bounds.width) - width - offset
    let y = offset
    let rightViewBounds = CGRect(x: x, y: y, width: width, height: height)
    return rightViewBounds
}}

і так само ми можемо замінити функцію нижче для функції лівого виду.

override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
    /*return as per requirement*/

}

3

Я знайшов це десь ...

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

[self addSubview:itemDescription];

4
Це просто додає доповнення тексту, що не те, що шукач шукає. Він не хоче чіткого лівого перегляду. Він хоче, щоб зображення відображалося як leftView.
камінь

Ви можете просто додати зображення в paddingView.
Матеус Вебер

3

Стрімкий 5

class CustomTextField: UITextField {
    func invalidate() {
        let errorImage =  UIImageView(image: UIImage(named: "errorImage"))
        errorImage.frame = CGRect(x: 8, y: 8, width: 16, height: 16)
        rightView = UIView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
        rightView?.addSubview(errorImage)
        rightViewMode = .always
    }
}

Ви захочете:

  • Підклас UITextField
  • Напишіть недійсний метод у текстовому полі підкласу
  • За допомогою методу недійсності створіть файл UIView більше, ніж ваше
  • Помістіть своє зображення всередину виду
  • Призначити вид UITextField.rightView

2

Ось одне із рішень:

 UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want 
 txtfield.leftView = paddingTxtfieldView;
 txtfield.leftViewMode = UITextFieldViewModeAlways;

1

Створіть власний клас UITextField і використовуйте цей клас замість UITextField. Замінити - (CGRect) textRectForBounds: (CGRect) межі, щоб встановити потрібний вам прямокутник

Приклад

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

1

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

Всередині UITextFieldпідкласу:

static CGFloat const kLeftViewHorizontalPadding = 10.0f;

@implementation TextFieldWithLeftIcon
{
  UIImage *_image;
  UIImageView *_imageView;
}

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)image
{
  self = [super initWithFrame:frame];
  if (self) {
    if (image) {
      _image = image;
      _imageView = [[UIImageView alloc] initWithImage:image];
      _imageView.contentMode = UIViewContentModeCenter;
      self.leftViewMode = UITextFieldViewModeAlways;
      self.leftView = _imageView;
    }
  }
  return self;
}

#pragma mark - Layout 

- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
  CGFloat widthWithPadding = _image.size.width + kLeftViewHorizontalPadding * 2.0f;
  return CGRectMake(0, 0, widthWithPadding, CGRectGetHeight(bounds));
}

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


1
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
    return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}

Якщо UITextFieldвбудовано в a UISearchBar, як сказати UISearchBarкористуватися своїм UITextFieldпідкласом?
crishoj

1

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

UIImageView *emailRightView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
emailRightView.contentMode = UIViewContentModeScaleAspectFill;
emailRightView.image = [UIImage imageNamed:@"icon_email.png"];
emailTextfield.rightViewMode = UITextFieldViewModeAlways;
emailTextfield.rightView = emailRightView;

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


1

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

Я просто змінив своє зображення у форматі PNG, щоб додати прозоре заповнення 10 пікселів, і воно працює добре, без кодування взагалі!


1

Якщо ви використовуєте UIImageView як leftView, тоді вам доведеться використовувати цей код:

Увага: Не використовуйте внутрішній viewWillAppear або viewDidAppear

-(UIView*)paddingViewWithImage:(UIImageView*)imageView andPadding:(float)padding
{
    float height = CGRectGetHeight(imageView.frame);
    float width =  CGRectGetWidth(imageView.frame) + padding;

    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    [paddingView addSubview:imageView];

    return paddingView;
}

1

Я створив власний метод у своєму класі ViewController, як показано нижче:

- (void) modifyTextField:(UITextField *)textField
{
    // Prepare the imageView with the required image
    uint padding = 10;//padding for iOS7
    UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
    iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);

    // Set the imageView to the left of the given text field.
    textField.leftView = iconImageView;
    textField.leftViewMode = UITextFieldViewModeAlways;
}

Тепер я можу зателефонувати до цього методу всередині ( viewDidLoadmethod) і надіслати будь-який зі своїхTextFields до цього методу та додати відступи як праворуч, так і ліворуч, і надати кольори тексту та фону, написавши лише один рядок коду, наступним чином:

[self modifyTextField:self.firstNameTxtFld];

Це чудово працювало на iOS 7! Сподіваюся, це все ще працює на iOS 8 та 9!

Я знаю, що додавання занадто великої кількості переглядів може зробити цей об’єкт трохи важчим для завантаження. Але коли мене хвилювали труднощі в інших рішеннях, я виявив себе більш упередженим до цього методу та більш гнучким із використанням цього способу. ;)

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

Ура!


1

Це працює для мене так само, як я шукаю:

func addImageViewInsideMyTextField() {
    let someView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 24))
    let imageView = UIImageView(image: UIImage(named: "accountImage"))
    imageView.frame = CGRect(x: 16, y: 0, width: 24, height: 24)
    imageView.contentMode = .scaleAspectFit
    someView.addSubview(imageView)

    self.myTextField.leftView = someView
    self.myTextField.leftViewMode = .always
}

1

З iOS 13 та Xcode 11 це єдине рішення, яке працює для нас.

// Init of custom UITextField
override init(frame: CGRect) {
    super.init(frame: frame)

    if let size = myButton.imageView?.image?.size {
        myButton.frame = CGRect(x:0, y: 0, width: size.width, height: size.height)

        let padding: CGFloat = 5
        let container = UIView(frame: CGRect(x:0, y: 0, width: size.width + padding, height: size.height))
        container.addSubview(myButton)

        myButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            myButton.topAnchor.constraint(equalTo: container.topAnchor),
            myButton.leftAnchor.constraint(equalTo: container.leftAnchor),
            myButton.bottomAnchor.constraint(equalTo: container.bottomAnchor),
            myButton.rightAnchor.constraint(equalTo: container.rightAnchor, constant: -padding),
        ])

        textField.rightViewMode = .always
        textField.rightView = container
    }
}

відповіді вище не працюють для мене, ця працює.
Марк Ділан Б Меркадо

1

// Встановіть Rightview UITextField, швидко 4.2TxtPass.rightViewMode = UITextField.ViewMode.always let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 18, height: 18)) imageView.contentMode = UIView.ContentMode.scaleAspectFit let image = UIImage(named: "hidepass") imageView.image = image let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 18)) rightView.addSubview(imageView) rightView.contentMode = UIView.ContentMode.left TxtPass.rightView = rightView


0

Один фокус: додайте UIView, що містить UIImageView, до UITextField як rightView. Цей UIView повинен бути більше за розміром, тепер розмістіть UIImageView ліворуч від нього. Тож буде відступ простору справа.

// Add a UIImageView to UIView and now this UIView to UITextField - txtFieldDate
UIView *viewRightIntxtFieldDate = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 30)]; 
// (Height of UITextField is 30px so height of viewRightIntxtFieldDate = 30px)
UIImageView *imgViewCalendar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 10, 10)];
[imgViewCalendar setImage:[UIImage imageNamed:@"calendar_icon.png"]];
[viewRightIntxtFieldDate addSubview:imgViewCalendar];
txtFieldDate.rightViewMode = UITextFieldViewModeAlways;
txtFieldDate.rightView = viewRightIntxtFieldDate;

0

Найпростіший спосіб - просто змінити Текстове поле на RoundRect замість Custom та побачити магію. :)


0

для Swift2, я використовую

...
        self.mSearchTextField.leftViewMode = UITextFieldViewMode.Always
        let searchImg = UIImageView(image: UIImage(named: "search.png"))
        let size = self.mSearchTextField.frame.height
        searchImg.frame = CGRectMake(0, 0, size,size)
        searchImg.contentMode = UIViewContentMode.ScaleAspectFit
        self.mSearchTextField.leftView = searchImg
...

0
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...

0

Простий підхід:

textField.rightViewMode = .always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 15))
textField.contentMode = .scaleAspectFit
imageView = UIImage(named: "imageName")
textField.rightView = imageView

Примітка: Висота повинна бути менше ширини, щоб забезпечити горизонтальне заповнення.


0

Я усвідомлюю, що це стара публікація, і ця відповідь дещо специфічна для мого випадку використання, але я опублікував її на випадок, якщо інші шукатимуть подібного рішення. Я хочу перемістити UITextField's leftView або rightView, але я не розміщую в них зображення і не хочу жодних жорстко закодованих констант.

Мій інтерфейс вимагає приховати кнопку очищення текстового поля та відобразити UIActivityIndicatorView там, де розташована кнопка очищення.

Я додаю дзигу до rightView, але з коробки (на iOS 13) вона зміщена на 20 пікселів праворуч від clearButton. Я не люблю використовувати магічні цифри, оскільки положення clearButton і rightView можуть будь-коли змінюватися Apple. Наміром дизайну інтерфейсу є "вертушка, де кнопка очищення", тому моє рішення полягало в підкласі UITextField і перевизначенні rightViewRect(forBounds).

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

    // Use clearButton's rectangle
    return self.clearButtonRect(forBounds: bounds)
}

Нижче наведено робочий приклад (без розкадрування):

//------------------------------------------------------------------------------
class myCustomTextField: UITextField {

    override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

        // Use clearButton rectangle
        return self.clearButtonRect(forBounds: bounds)
    }
}

//------------------------------------------------------------------------------
class myViewController: UIViewController {

    var activityView: UIActivityIndicatorView = {
        let activity = UIActivityIndicatorView()
        activity.startAnimating()
        return activity
    }()

    @IBOutlet weak var searchTextField: myCustomTextField!

    //------------------------------------------------------------------------------
    // MARK: - Lifecycle
    //------------------------------------------------------------------------------
    override func viewDidLoad() {

        super.viewDidLoad()

        searchTextField.rightView = activityView
        searchTextField.rightViewMode = .never // Hide spinner
        searchTextField.clearButtonMode = .never // Hide clear button

        setupUIForTextEntry()
    }

    // ...
    // More code to switch between user text entry and "search progress" 
    // by calling setupUI... functions below
    // ...

    //------------------------------------------------------------------------------
    // MARK: - UI
    //------------------------------------------------------------------------------
    func setupUIForTextEntry() {

        // Hide spinner
        searchTextField.rightViewMode = .never

        // Show clear button
        searchTextField.clearButtonMode = .whileEditing
        searchTextField.becomeFirstResponder()
    }

    //------------------------------------------------------------------------------
    func setupUIForSearching() {

        // Show spinner
        searchTextField.rightViewMode = .always

        // Hide clear button
        searchTextField.clearButtonMode = .never
        searchTextField.resignFirstResponder()
    }

    //------------------------------------------------------------------------------

}

//------------------------------------------------------------------------------
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.