UITextfield отступы leftView/rightView на iOS7
Виды 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
28 ответов
Просто работал над этим сам и использовал это решение:
- (CGRect) rightViewRectForBounds:(CGRect)bounds {
CGRect textRect = [super rightViewRectForBounds:bounds];
textRect.origin.x -= 10;
return textRect;
}
Это переместит изображение справа на 10 вместо того, чтобы изображение сжималось по краю в iOS 7.
Кроме того, это было в подклассе UITextField
, который может быть создан:
- Создайте новый файл, который является подклассом
UITextField
вместо по умолчаниюNSObject
Добавить новый метод с именем
- (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; }
Возможно, вам придется импортировать
#import <QuartzCore/QuartzCore.h>
Добавить
rightViewRectForBounds
метод вышеВ Интерфейсном Разработчике щелкните TextField, который вы хотите создать в подклассе, и измените атрибут класса на имя этого нового подкласса.
Гораздо более простое решение, которое использует преимущества 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 2,
let arrow = UIImageView(image: UIImage(named: "down_arrow"))
arrow.frame = CGRectMake(0.0, 0.0, arrow.image.size.width+10.0, arrow.image.size.height);
arrow.contentMode = UIViewContentMode.Center
self.textField.rightView = arrow
self.textField.rightViewMode = UITextFieldViewMode.Always
В Свифте 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
Самый простой способ - добавить UIView в leftView/rightView и добавить 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];
Это прекрасно работает для 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
Это работает для меня
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
self.passwordTF.leftView = paddingView;
self.passwordTF.leftViewMode = UITextFieldViewModeAlways;
Пусть это поможет вам.
Мне нравится это решение, потому что оно решает проблему с одной строкой кода
myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10.0f, 0.0f, 0.0f);
Примечание: .. или 2, если вы планируете включить QuartzCore строку:)
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
Вместо манипулирования 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
}}
и таким же образом мы можем переопределить ниже func для левого обзора.
override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
/*return as per requirement*/
}
Лучший способ сделать это - просто создать класс, используя подкласс 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" в опции класса.
Примечание: если вы просто дадите отступ с автоматическим макетом для текстового поля, тогда ваше приложение не запустится и покажет только пустой экран.
Начиная с 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
}
}
Возможно, вы могли бы настроить пустое представление и встроить свое представление в качестве подпредставления:
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50.0, height: 50.0))
imageView.contentMode = .center
imageView.image = UIImage(named: "ic_dropdown")
let emptyView = UIView(frame: CGRect(x: 0, y: 0, width: 50.0, height: 50.0))
emptyView.backgroundColor = .clear
emptyView.addSubview(imageView)
self.documentTypeTextLabel.rightView = emptyView
self.documentTypeTextLabel.rightViewMode = .always
Удачного кодирования
Я нашел это где-то...
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
paddingView.backgroundColor = [UIColor clearColor];
itemDescription.leftView = paddingView;
itemDescription.leftViewMode = UITextFieldViewModeAlways;
[self addSubview:itemDescription];
Вот одно из решений:
UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want
txtfield.leftView = paddingTxtfieldView;
txtfield.leftViewMode = UITextFieldViewModeAlways;
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}
Создайте пользовательский класс UITextField и используйте этот класс вместо UITextField. Переопределить - (CGRect) textRectForBounds:(CGRect) границы, чтобы установить нужный вам прямоугольник
пример
- (CGRect)textRectForBounds:(CGRect)bounds{
CGRect textRect = [super textRectForBounds:bounds];
textRect.origin.x += 10;
textRect.size.width -= 10;
return textRect;
}
Если вы используете 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;
}
Я сам столкнулся с этой проблемой, и, безусловно, самое простое решение - это изменить свое изображение, просто добавив отступы с каждой стороны изображения!
Я просто изменил свое изображение в формате png, добавив прозрачное заполнение 10 пикселей, и оно работает хорошо, без какого-либо кодирования!
// Устанавливаем 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
Ниже приведен пример добавления горизонтального отступа к левому виду, который является значком - вы можете использовать аналогичный подход для добавления отступов к любому 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
здесь, я считаю, что это самый чистый подход.
Я создал собственный метод в своем классе 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;
}
Теперь я могу вызвать этот метод внутри (viewDidLoad
метод) и отправить любой из моих TextFields
к этому методу и добавьте отступы для правого и левого, а также задайте цвета текста и фона, написав всего одну строку кода, как показано ниже:
[self modifyTextField:self.firstNameTxtFld];
Это отлично работало на iOS 7! Надеюсь, что это все еще работает на iOS 8 и 9 тоже!
Я знаю, что добавление слишком большого количества представлений может сделать этот объект более тяжелым для загрузки. Но когда меня беспокоили трудности других решений, я обнаружил, что более склонен к этому методу и более гибок в использовании этого способа.;)
Надеюсь, что этот ответ может быть полезным или полезным, чтобы найти другое решение для кого-то еще.
Ура!
Это работает для меня так же, как я ищу:
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
}
Спасибо вам, ребята, за ваши ответы, к моему удивлению, ни один из них действительно не поместил правильное изображение в моё текстовое поле, в то же время предоставляя необходимые отступы. Затем я подумал об использовании режима 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 в рамке моего imageview представляет высоту моего поля emailTextfield, не стесняйтесь настроить его под свои нужды.
Самый простой способ - просто изменить Textfield на RoundRect вместо Custom и увидеть магию.:)
Для 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
...
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...
Один трюк: добавьте 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;
Я понимаю, что это старый пост, и этот ответ немного специфичен для моего варианта использования, но я опубликовал его на случай, если другие ищут аналогичное решение. Я хочу переместить 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()
}
//------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------
Простой подход:
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
Примечание. Высота должна быть меньше ширины, чтобы обеспечить горизонтальное заполнение.