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?
Зорайр
1
Нет, это спрашивает об отступе изображения, отображаемого как leftView в текстовом поле. Не делать отступы в самом тексте. Попробуйте его код, и вы увидите, что установка 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. В Интерфейсном Разработчике щелкните текстовое поле, которое вы хотите создать подкласс, и измените атрибут класса на имя этого нового подкласса.

АнджелоС
источник
как использовать IBDesignable для этого же?
Ридди
для последней версии или если вы просматриваете это в 2020 году. посетите: stackoverflow.com/a/55041786/6596443
AKINNUBI ABIOLA SYLVESTER
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
TTillage
источник
1
Вы также можете использовать ScaleAspectFit вместо center ... если размер изображения не соответствует точному кадру.
Mihir Mehta
Я использовал ваш пример для UIButton (вместо UIImageView), а его тип - InfoLight.
OhadM
Я обнаружил, что «.right» вместо «.center» делает его больше похожим на встроенную панель поиска, такую ​​как в приложении «Контакты». Отличное решение по этому поводу, спасибо за его публикацию.
Джеймс Туми
Или, если вам нужно быть точным в воссоздании дизайна, поместите изображение в левый угол, а затем увеличьте ширину, чтобы добиться точного заполнения
Йованьованович
4
Похоже, это больше не работает с iOS 13 и Xcode 11 Beta 7. А вот с iOS 11/12 работает нормально.
PatrickDotStar 02
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];
Vishal Dharankar
источник
UIViewContentMode не работает, но этот ответ работает как шарм!
nigong
14

Это отлично работает для Swift:

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
Андрей
источник
невозможно преобразовать значение типа 'string' в ожидаемый тип аргумента 'UIImage? "
8

Это работает для меня

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
Это также сдвигает границу
Softlion
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 или изображением, мы можем переопределить метод, предоставленный 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];
RegularExpression
источник
4
Это просто добавляет к тексту отступы, а это не то, что спрашивает. Он не хочет четкого левого обзора. Он хочет, чтобы изображение отображалось как leftView.
камень
Вы можете просто добавить изображение в paddingView.
Matheus Weber
3

Swift 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
  • Напишите недействительный метод внутри текстового поля с подклассом
  • В методе invalidate создайте изображение UIView размером больше вашего
  • Поместите свое изображение в представление
  • Назначьте представление UITextField.rightView
bkSwifty
источник
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);
}
carmen_munich
источник
Если UITextFieldон встроен в 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 в рамке моего изображения представляет высоту моего emailTextfield, не стесняйтесь настраивать его под свои нужды.

Карлос16196
источник
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;
}
Zeeshan
источник
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
    }
}
PatrickDotStar
источник
выше ответы не работают для меня, это работает.
Марк Дилан Б. Меркадо,
1

// Устанавливаем вид справа для UITextField, swift 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

NSurajit
источник
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

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

Мой пользовательский интерфейс требует скрыть кнопку очистки текстового поля и отобразить 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()
    }

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

}

//------------------------------------------------------------------------------
Swany
источник