How to display clear button in left side of UITextField? - ios

I'm developing an app in Arabic language and I have UITextField with textAlignment right. Now I want to show the clear button of the textField in left side. Is it possible to do this without adding a custom button?
Current position
Desired position

Use below category and make sure your text alignment should be right :)
#interface UICrossButtonTextField:UITextField
- (CGRect)clearButtonRectForBounds:(CGRect)bounds;
#end
#implementation UICrossButtonTextField
- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
CGRect originalRect = [super clearButtonRectForBounds:bounds];
return CGRectOffset(originalRect, -originalRect.origin.x+5, 0); }
- (CGRect)editingRectForBounds:(CGRect)bounds {
CGRect originalRect = [super clearButtonRectForBounds:bounds];
bounds = CGRectMake(originalRect.size.width, bounds.origin.y, bounds.size.width-originalRect.size.width, bounds.size.height);
return CGRectInset(bounds, 13, 3);
}
#end

Although I would recommend to check this answer for handling Left-to-Right App languages, as a workaround you could follow userar's answer, the following code snippet is a Swift 3 version of his answer:
Create a custom UITextField class, as follows:
class CustomTextField: UITextField {
private var originalRect = CGRect.zero
override func awakeFromNib() {
super.awakeFromNib()
originalRect = super.clearButtonRect(forBounds: bounds)
clearButtonMode = .whileEditing
textAlignment = .right
}
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
return originalRect.offsetBy(dx: -originalRect.origin.x + 5, dy: 0)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
let bounds = CGRect(x: originalRect.size.width, y: bounds.origin.y, width: bounds.size.width-originalRect.size.width, height: bounds.size.height)
return bounds.insetBy(dx: 13, dy: 3)
}
}
The output would be:

SWIFT 3 syntax:
class TextFields: UITextField {
// You will need this
private var firstPlace = CGRect.zero
override func awakeFromNib() {
super.awakeFromNib()
firstPlace = super.clearButtonRect(forBounds: bounds) // to access clear button properties
/* uncomment these following lines if you want but you can change them in main.storyboard too
clearButtonMode = .whileEditing // to show the clear button only when typing starts
textAlignment = .right // to put the text to right side
*/
}
// Function to change the clear button
override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
return firstPlace.offsetBy(dx: -firstPlace.origin.x + 5, dy: 0)
}
}
hope it works

Related

Increase UISlider height in Swift 3 without using transform [duplicate]

I've been searching for a way to make the UISlider progress bar taller, like increasing the height of the slider but couldn't find anything. I don't want to use a custom image or anything, just make it taller, so the UISlider doesn't look so thin. Is there an easy way to do this that I'm missing?
The accepted answer will undesirably change the slider's width in some cases, like if you're using a minimumValueImage and maximumValueImage. If you only want to change the height and leave everything else alone, then use this code:
override func trackRect(forBounds bounds: CGRect) -> CGRect {
var newBounds = super.trackRect(forBounds: bounds)
newBounds.size.height = 12
return newBounds
}
Here's my recent swifty implementation, building on CularBytes's ...
open class CustomSlider : UISlider {
#IBInspectable open var trackWidth:CGFloat = 2 {
didSet {setNeedsDisplay()}
}
override open func trackRect(forBounds bounds: CGRect) -> CGRect {
let defaultBounds = super.trackRect(forBounds: bounds)
return CGRect(
x: defaultBounds.origin.x,
y: defaultBounds.origin.y + defaultBounds.size.height/2 - trackWidth/2,
width: defaultBounds.size.width,
height: trackWidth
)
}
}
Use this on a UISlider in a storyboard by setting its custom class
The IBInspectable allows you to set the height from the storyboard
For those that would like to see some working code for changing the track size.
class CustomUISlider : UISlider {
override func trackRect(forBounds bounds: CGRect) -> CGRect {
//keeps original origin and width, changes height, you get the idea
let customBounds = CGRect(origin: bounds.origin, size: CGSize(width: bounds.size.width, height: 5.0))
super.trackRect(forBounds: customBounds)
return customBounds
}
//while we are here, why not change the image here as well? (bonus material)
override func awakeFromNib() {
self.setThumbImage(UIImage(named: "customThumb"), for: .normal)
super.awakeFromNib()
}
}
Only thing left is changing the class inside the storyboard:
You can keep using your seekbar action and outlet to the object type UISlider, unless you want to add some more custom stuff to your slider.
I found what I was looking for. The following method just needs to be edited in a subclass.
override func trackRect(forBounds bounds: CGRect) -> CGRect {
var customBounds = super.trackRect(forBounds: bounds)
customBounds.size.height = ...
return customBounds
}
You could play with this, see what happens:
slider.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 2.0);

ios: how to start cursor at specific position?

I want cursor at specific position.
I show my requirement in image.
let arbitraryValue: Int = 5
if let newPosition = txtroutine.position(from: txtroutine.beginningOfDocument, offset: arbitraryValue) {
txtroutine.selectedTextRange = txtroutine.textRange(from: newPosition, to: newPosition)
}
I have something like this but my code is in obj-c hope you can make it in swift,
Get the current position of cursor
- (NSInteger)cursorPosition
{
UITextRange *selectedRange = self.selectedTextRange;
UITextPosition *textPosition = selectedRange.start;
return [self offsetFromPosition:self.beginningOfDocument toPosition:textPosition];
}
// set cursor at your specfic location
- (void)setCursorPosition:(NSInteger)position
{
UITextPosition *textPosition = [self positionFromPosition:self.beginningOfDocument offset:position];
[self setSelectedTextRange:[self textRangeFromPosition:textPosition toPosition:textPosition]];
}
You can achieve this by overriding -textRectForBounds:. It will only change the inset of text i.e in your case it's cursor.
You need to subclass UITextField for that.
class PaddedTextfield: UITextField {
var horizontalInsetValue: CGFloat = 0
var verticalInsetValue: CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: horizontalInsetValue, dy: verticalInsetValue)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: horizontalInsetValue , dy: verticalInsetValue)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: horizontalInsetValue, dy: verticalInsetValue)
}
}
You can use this textfield wherever you want.
you can use leftView property of UITextField to set position as per your requirement :
//add a 12pt padding to the textField
Swift 3.0 :
textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: 0))
textField.leftViewMode = .always
Try this , feel free to comment .
my problem is solved by adding this simple line in viewdidload()
self.txtroutine.layer.sublayerTransform = CATransform3DMakeTranslation(15, 0, 0);

Bottom Border Width on Swift TextField in TableView

i builded a static tableview with more Rowes than the screen has, so the user has to scroll to see all cell.
Every cell has a textfield with the following class to add a bottom border:
class TextFieldWithBottomBorder: UITextField {
let border = CALayer()
let width = CGFloat(1.0)
func addBottomBorder(color: UIColor){
self.border.borderColor = color.cgColor
self.border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height:self.frame.size.height)
self.border.borderWidth = self.width
self.layer.addSublayer(self.border)
self.layer.masksToBounds = true
}
func changeBorderColor(color: UIColor){
self.border.borderColor = color.cgColor
}
}
And i call the method after receiving some data from the server e. g.
self.firstnameTextField.text = firstNameFromDB
self.firstnameTextField.addBottomBorder(color: .blue)
This works fine for every cell is currently displayed. But the cells which are out of the current view the with is shorter than the textfield.
See this screenshot, for "Vorname", means firstName everything looks good, but for email, password etc. the border is to short.
http://share-your-photo.com/34b5e80253
Looks like the size of the UITextField is being resized after you have called addBottomBorder and so the UIView being used at the line is now not wide enough. It's difficult to say why this would be without seeing more code but there are several methods you could use to overcome it.
1) Switch to a UIView instead of a CALayer and use auto layout to keep the view in the correction position.
2) Override layoutSubviews to update the frame of the bottom line.
The simplest for you is probably option 2 (although I would go option 1) and it would look like this:
override func layoutSubviews() {
super.layoutSubviews()
self.border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height:self.frame.size.height)
}
Now whenever the frame/size of the text field changes the frame/size of the border line CALayer will be updated appropriately.
Use this class for bottom line text field
#IBDesignable class BottomTextField: UITextField {
var lineView = UIView()
#IBInspectable var lineViewBgColor:UIColor = UIColor.gray{
didSet {
if !isFirstResponder {
lineView.backgroundColor = lineViewBgColor
}
}
}
required init?(coder aDecoder:NSCoder) {
super.init(coder:aDecoder)!
setup()
}
override init(frame:CGRect) {
super.init(frame:frame)
setup()
}
// MARK:- Private Methods
private func setup() {
lineView.frame = CGRect(x:CGFloat(0), y:self.frame.size.height-2, width:self.frame.size.width, height:CGFloat(1))
lineView.backgroundColor = lineViewBgColor
self.addSubview(lineView)
}
}

Make UISlider height larger?

I've been searching for a way to make the UISlider progress bar taller, like increasing the height of the slider but couldn't find anything. I don't want to use a custom image or anything, just make it taller, so the UISlider doesn't look so thin. Is there an easy way to do this that I'm missing?
The accepted answer will undesirably change the slider's width in some cases, like if you're using a minimumValueImage and maximumValueImage. If you only want to change the height and leave everything else alone, then use this code:
override func trackRect(forBounds bounds: CGRect) -> CGRect {
var newBounds = super.trackRect(forBounds: bounds)
newBounds.size.height = 12
return newBounds
}
Here's my recent swifty implementation, building on CularBytes's ...
open class CustomSlider : UISlider {
#IBInspectable open var trackWidth:CGFloat = 2 {
didSet {setNeedsDisplay()}
}
override open func trackRect(forBounds bounds: CGRect) -> CGRect {
let defaultBounds = super.trackRect(forBounds: bounds)
return CGRect(
x: defaultBounds.origin.x,
y: defaultBounds.origin.y + defaultBounds.size.height/2 - trackWidth/2,
width: defaultBounds.size.width,
height: trackWidth
)
}
}
Use this on a UISlider in a storyboard by setting its custom class
The IBInspectable allows you to set the height from the storyboard
For those that would like to see some working code for changing the track size.
class CustomUISlider : UISlider {
override func trackRect(forBounds bounds: CGRect) -> CGRect {
//keeps original origin and width, changes height, you get the idea
let customBounds = CGRect(origin: bounds.origin, size: CGSize(width: bounds.size.width, height: 5.0))
super.trackRect(forBounds: customBounds)
return customBounds
}
//while we are here, why not change the image here as well? (bonus material)
override func awakeFromNib() {
self.setThumbImage(UIImage(named: "customThumb"), for: .normal)
super.awakeFromNib()
}
}
Only thing left is changing the class inside the storyboard:
You can keep using your seekbar action and outlet to the object type UISlider, unless you want to add some more custom stuff to your slider.
I found what I was looking for. The following method just needs to be edited in a subclass.
override func trackRect(forBounds bounds: CGRect) -> CGRect {
var customBounds = super.trackRect(forBounds: bounds)
customBounds.size.height = ...
return customBounds
}
You could play with this, see what happens:
slider.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 2.0);

Set padding for UITextField with UITextBorderStyleNone

I wanted to use a custom background for my UITextFields. This works fine except for the fact that I have to use UITextBorderStyleNone to make it look pretty. This forces the text to stick to the left without any padding.
Can I set a padding manually so that it looks similar to UITextBorderStyleRoundedRect except for using my custom background image?
I found a neat little hack to set the left padding for this exact situation.
Basically, you set the leftView property of the UITextField to be an empty view of the size of the padding you want:
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;
Worked like a charm for me!
In Swift 3/ Swift 4, it can be done by doing that
let paddingView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 20))
textField.leftView = paddingView
textField.leftViewMode = .always
I created this category implementation and added it to the top of the .m file.
#implementation UITextField (custom)
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + 10, bounds.origin.y + 8,
bounds.size.width - 20, bounds.size.height - 16);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
#end
Based off the link Piotr Blasiak provided. It seemed simpler then creating a whole new subclass, and also simpler then adding the additional UIView. Still, it seems like something is missing to not be able to control the padding inside a text field.
Swift 4 solution:
class CustomTextField: UITextField {
struct Constants {
static let sidePadding: CGFloat = 10
static let topPadding: CGFloat = 8
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(
x: bounds.origin.x + Constants.sidePadding,
y: bounds.origin.y + Constants.topPadding,
width: bounds.size.width - Constants.sidePadding * 2,
height: bounds.size.height - Constants.topPadding * 2
)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return self.textRect(forBounds: bounds)
}
}
A Swift 3 version for Xcode >6, where you can edit the inset value in Interface Builder / Storyboard.
import UIKit
#IBDesignable
class FormTextField: UITextField {
#IBInspectable var inset: CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: inset, dy: inset)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return textRect(forBounds: bounds)
}
}
Edit: Still works in iOS 11.3.1
In iOS 6 myTextField.leftView = paddingView; is causing issue
This solves the problem
myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0)
For right aligned text field use CATransform3DMakeTranslation(-5, 0, 0) as mention by latenitecoder in comments
A good approach to add padding to UITextField is to subclass and add an edgeInsets property. You then set the edgeInsets and the UITextField will be drawn accordingly. This will also function correctly with a custom leftView or rightView set.
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 = UIEdgeInsetsZero;
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
self.edgeInsets = UIEdgeInsetsZero;
}
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
Just subclass UITextField like this:
#implementation DFTextField
- (CGRect)textRectForBounds:(CGRect)bounds
{
return CGRectInset(bounds, 10.0f, 0);
}
- (CGRect)editingRectForBounds:(CGRect)bounds
{
return [self textRectForBounds:bounds];
}
#end
This adds horizontal padding of 10 points either side.
Create a textfield Custom
PaddingTextField.swift
import UIKit
class PaddingTextField: UITextField {
#IBInspectable var paddingLeft: CGFloat = 0
#IBInspectable var paddingRight: CGFloat = 0
override func textRectForBounds(bounds: CGRect) -> CGRect {
return CGRectMake(bounds.origin.x + paddingLeft, bounds.origin.y,
bounds.size.width - paddingLeft - paddingRight, bounds.size.height);
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
return textRectForBounds(bounds)
}}
Set your textfield class is PaddingTextField and custom your padding as you want
Enjoy it
Objective C Code
MyTextField.h
#import <UIKit/UIKit.h>
#interface MyTextField : UITextField
#property (nonatomic) IBInspectable CGFloat padding;
#end
MyTextField.m
#import "MyTextField.h"
IB_DESIGNABLE
#implementation MyTextField
#synthesize padding;
-(CGRect)textRectForBounds:(CGRect)bounds{
return CGRectInset(bounds, padding, padding);
}
-(CGRect)editingRectForBounds:(CGRect)bounds{
return [self textRectForBounds:bounds];
}
#end
Based on Evil Trout's answer you might wanna create a category to make it easier to use across multiple applications.
Header file:
#interface UITextField (PaddingText)
-(void) setLeftPadding:(int) paddingValue;
-(void) setRightPadding:(int) paddingValue;
#end
Implementation file:
#import "UITextField+PaddingText.h"
#implementation UITextField (PaddingText)
-(void) setLeftPadding:(int) paddingValue
{
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, paddingValue, self.frame.size.height)];
self.leftView = paddingView;
self.leftViewMode = UITextFieldViewModeAlways;
}
-(void) setRightPadding:(int) paddingValue
{
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, paddingValue, self.frame.size.height)];
self.rightView = paddingView;
self.rightViewMode = UITextFieldViewModeAlways;
}
#end
Usage Example
#import "UITextField+PaddingText.h"
[self.YourTextField setLeftPadding:20.0f];
Hope it helps you out guys
Cheers
Swift version:
extension UITextField {
#IBInspectable var padding_left: CGFloat {
get {
LF.log("WARNING no getter for UITextField.padding_left")
return 0
}
set (f) {
layer.sublayerTransform = CATransform3DMakeTranslation(f, 0, 0)
}
}
}
So that you can assign value in IB
You can't set padding. Instead have a UIView which has your background image and the UITextField inside of it. Set the UITextField width as UIViewWidth-(paddingSize x 2) and the height similarly and then set it at point paddingSize,paddingSize.
Just subclass UITextField like this (Swift version):
import UIKit
class CustomTextField: UITextField {
override func textRectForBounds(bounds: CGRect) -> CGRect {
return CGRectInset(bounds, 25.0, 0)
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
return self.textRectForBounds(bounds)
}
}
This adds horizontal padding of 25.0 points either side.
I was based off Nate's solution, but then i found it that this causes problems when you use the leftView/rightView properties, so its better tune the super's implementation, because it will take the left/right view's into account.
- (CGRect)textRectForBounds:(CGRect)bounds {
CGRect ret = [super textRectForBounds:bounds];
ret.origin.x = ret.origin.x + 5;
ret.size.width = ret.size.width - 10;
return ret;
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
Updated version for Swift 3:
#IBDesignable
class FormTextField: UITextField {
#IBInspectable var paddingLeft: CGFloat = 0
#IBInspectable var paddingRight: CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + paddingLeft, y: bounds.origin.y, width: bounds.size.width - paddingLeft - paddingRight, height: bounds.size.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return textRect(forBounds: bounds)
}
}
Set padding for UITextField with UITextBorderStyleNone: Swift
Based on #Evil Trout's most voted answer I created a custom method in my ViewController class, like shown bellow:
- (void) modifyTextField:(UITextField *)textField
{
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;
textField.rightView = paddingView;
textField.rightViewMode = UITextFieldViewModeAlways;
[textField setBackgroundColor:[UIColor whiteColor]];
[textField setTextColor:[UIColor blackColor]];
}
Now I can call that method inside (viewDidLoad method) and send any of my TextFields to that method and add padding for both right and left, and give text and background colors by writing just one line of code, as follows:
[self modifyTextField:self.firstNameTxtFld];
This Worked perfectly on iOS 7!
I know that adding too much Views might make this a bit heavier class to be loaded. But when concerned about the difficulty in other solutions, I found myself more biased to this method and more flexible with using this way. ;)
Thanks for the Hack "Evil Trout"! (bow)
I thought I should update this answer's code snippet with Swift:
Since Swift allow us to write extensions for the existing classes, let's write it in that way.
extension UITextField {
func addPaddingToTextField() {
let paddingView: UIView = UIView.init(frame: CGRectMake(0, 0, 8, 20))
self.leftView = paddingView;
self.leftViewMode = .Always;
self.rightView = paddingView;
self.rightViewMode = .Always;
self.backgroundColor = UIColor.whiteColor()
self.textColor = UIColor.blackColor()
}
}
Usage:
self.firstNameTxtFld.addPaddingToTextField()
Hope this would be helpful to somebody else out there!
Cheers!
Here's how to achieve this in SWIFT
#IBOutlet weak var yourTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let paddingView = UIView(frame: CGRectMake(0, 0, 10, self.yourTextField.frame.height))
yourTextField.leftView = paddingView
yourTextField.leftViewMode = UITextFieldViewMode.Always
}
}
Resource
Swift 2.0 Version:
let paddingView: UIView = UIView(frame: CGRectMake(0, 0, 5, 20))
textField.leftView = paddingView
textField.leftViewMode = UITextFieldViewMode.Always;
If anyone is looking for Swift 4.0 version then below extension is work. It has both Left and Right padding for UITextField. Actually it is IBInspectable for storyboard configuration. You can set the value directly from the Interface Builder / Storyboard. This is tested code in Swift 4.0 version and Xcode 9.0
Keep in mind that if you want to enable Clear Button on the same UITextField then your have to keep Right Padding blank.
import UIKit
extension UITextField {
#IBInspectable var paddingLeft: CGFloat {
get {
return leftView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
leftView = paddingView
leftViewMode = .always
}
}
#IBInspectable var paddingRight: CGFloat {
get {
return rightView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
rightView = paddingView
rightViewMode = .always
}
}
}
^ these suggestions are great for those who are programmatically creating an interface.
But there are two LAZY EASY WAYS for those of us who use the Xcode interface builder:
easier: put a UIImageView behind a text field
easiest: change the border style on your to the simple black square (second from left option), then add your image as a background image. The image takes precedence over the square, so you still get the padding needed for a normal image background, without the square actually being drawn on.
EDIT: you can also use the black sphere (third from left option when selecting the UITextBox in IB), it does not work with the far right, "graphical sphere" style.
The best way to do this is simply make a class using subclass of UITextField and in .m file
#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;
}
by doing this go to your storyboard or xib and click on identity inspector and replace UITextfield with your own "CustomTextField" in class option.
Note: If you simply give padding with auto layout for textfield then your application will not run and show only blank screen.
Swift 3 Version:
class CustomTextField:UITextField{
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect.init(x: bounds.origin.x + 8, y: bounds.origin.y, width: bounds.width, height: bounds.height)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return self.textRect(forBounds:bounds)
}
}
Nate Flink's answer is my favourite, but don't forget about right/left views.
E.g for UITextField subclass:
override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
let rightViewBounds = super.rightViewRectForBounds(bounds)
return CGRectMake(CGRectGetMinX(rightViewBounds) - 10, CGRectGetMinY(rightViewBounds), CGRectGetWidth(rightViewBounds), CGRectGetHeight(rightViewBounds))
}
Above code set right padding for rightView of UITextField.
Swift 3 Solution
class CustomTextField: UITextField {
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + 10, y: bounds.origin.y + 8, width: bounds.size.width - 20, height: bounds.size.height - 16)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return self.textRect(forBounds: bounds)
}
}
Here is a Swift code to give padding in UITextfield
func txtPaddingVw(txt:UITextField) {
let paddingView = UIView(frame: CGRectMake(0, 0, 10, 10))
txt.leftViewMode = .Always
txt.leftView = paddingView
}
and call using
self.txtPaddingVw(txtPin)
you can use category. set padding to left and right
UITextField+Padding.h
#interface UITextField (Padding)
#property (nonatomic, assign) CGFloat paddingValue;
#property (nonatomic, assign) CGFloat leftPadding;
#property (nonatomic, assign) CGFloat rightPadding;
//overwrite
-(CGRect)textRectForBounds:(CGRect)bounds;
-(CGRect)editingRectForBounds:(CGRect)bounds;
#end
UITextField+Padding.m
#import "UITextField+Padding.h"
#import <objc/runtime.h>
static char TAG_LeftPaddingKey;
static char TAG_RightPaddingKey;
static char TAG_Left_RightPaddingKey;
#implementation UITextField (Padding)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
-(CGRect)textRectForBounds:(CGRect)bounds {
CGFloat offset_Left=0;
CGFloat offset_Right=0;
if (self.paddingValue>0) {
offset_Left=self.paddingValue;
offset_Right=offset_Left;
}else{
if (self.leftPadding>0){
offset_Left=self.leftPadding;
}
if (self.rightPadding>0){
offset_Right=self.rightPadding;
}
}
if (offset_Left>0||offset_Right>0) {
return CGRectMake(bounds.origin.x+ offset_Left ,bounds.origin.y ,
bounds.size.width- (offset_Left+offset_Right), bounds.size.height-2 );
}else{
return bounds;
}
}
-(CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
#pragma clang diagnostic pop
#pragma maek -setter&&getter
- (CGFloat)paddingValue
{
return [objc_getAssociatedObject(self,&TAG_Left_RightPaddingKey) floatValue];
}
-(void)setPaddingValue:(CGFloat)paddingValue
{
objc_setAssociatedObject(self, &TAG_Left_RightPaddingKey, #(paddingValue), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGFloat)leftPadding
{
return [objc_getAssociatedObject(self,&TAG_LeftPaddingKey) floatValue];
}
-(void)setLeftPadding:(CGFloat)leftPadding
{
objc_setAssociatedObject(self, &TAG_LeftPaddingKey, #(leftPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGFloat)rightPadding
{
return [objc_getAssociatedObject(self,&TAG_RightPaddingKey) floatValue];
}
-(void)setRightPadding:(CGFloat)rightPadding
{
objc_setAssociatedObject(self, &TAG_RightPaddingKey, #(rightPadding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
you can set padding like this
self.phoneNumTF.paddingValue=10.f;
or
self.phoneNumTF.leftPadding=10.f;
#Evil trout's answer is great. I have been using this approach for quite a some time now. The only thing it lacks is "dealing with numerous text fields". I tried other approaches but does not seem to work.
Subclassing UITextField just to add a padding didn't make any sense to me. So, I iterated over all UITextFields to add the padding.
-(void) addPaddingToAllTextFields:(UIView*)view {
for(id currentView in [view subviews]){
if([currentView isKindOfClass:[UITextField class]]) {
// Change value of CGRectMake to fit ur need
[currentView setLeftView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)]];
[currentView setLeftViewMode:UITextFieldViewModeAlways];
}
if([currentView respondsToSelector:#selector(subviews)]){
[textfieldarray addObjectsFromArray:[self addPaddingToAllTextFields:currentView]];
}
}
}
Brody's solution worked perfect for me. I have had to add side views on a textfield and add additional padding. So by implementing the custom UIEdgeInsets property to a UITextField subclass I have managed to achieve the task. I'm going to use this new subclass in all of my projects.
The best solution I found so far is a category. That's how I add a 5 points padding to left and right:
#implementation UITextField (Padding)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + 5, bounds.origin.y,
bounds.size.width - 10, bounds.size.height);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
#pragma clang diagnostic pop
#end
The #pragma's are just for removing the annoying warnings
textField.layer.borderWidth = 3;
will add border, which worked as padding for me.
I found it far easier to use a non-editable UITextView and set the contentOffset
uiTextView.contentOffset = CGPointMake(8, 7);

Resources