I can add a button to a textfield on the right hand side of the UITextField using the right view however, the text overlaps on the button. Below is the code for right view butto
use the rightView property of the UITextField. Basically, there are two properties (this one and leftView accordingly) that allow you to place custom views/controls inside the UITextField. You can control whether those views are shown or not by means of rightViewMode/leftViewMode properties:
textField.rightView = btnColor
textField.rightViewMode = .unlessEditing
for e.g
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "send.png"), for: .normal)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -16, 0, 0)
button.frame = CGRect(x: CGFloat(txt.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
button.addTarget(self, action: #selector(self.refresh), for: .touchUpInside)
textField.rightView = button
textField.rightViewMode = .always
and call the action as
@IBAction func refresh(_ sender: Any) {
}
You can achieve same as shown below:
@IBOutlet weak var textField: UITextField!
var textFieldBtn: UIButton {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "image.png"), for: .normal)
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
button.frame = CGRect(x: CGFloat(textField.frame.size.width - 40), y: CGFloat(5), width: CGFloat(40), height: CGFloat(30))
button.backgroundColor = UIColor.darkGray
button.addTarget(self, action: #selector(self.refreshContent), for: .touchUpInside)
return button
}
func refreshContent() {
// Add your code here to handle button.
}
Add to textField.
textField.rightView = textFieldBtn
textField.rightViewMode = .always
Correct answer Swift3+
If you just override the methods, the text may overlap the right view. This code completely solves this problem.
You UITextField subclass:
//...
private func setInsets(forBounds bounds: CGRect) -> CGRect {
var totalInsets = insets //property in you subClass
if let leftView = leftView { totalInsets.left += leftView.frame.origin.x }
if let rightView = rightView { totalInsets.right += rightView.bounds.size.width }
return UIEdgeInsetsInsetRect(bounds, totalInsets)
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return setInsets(forBounds: bounds)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return setInsets(forBounds: bounds)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return setInsets(forBounds: bounds)
}
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
var rect = super.rightViewRect(forBounds: bounds)
rect.origin.x -= insets.right
return rect
}
override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
var rect = super.leftViewRect(forBounds: bounds)
rect.origin.x += insets.left
return rect
}
you can assign button at right view of textfield
var btnColor = UIButton(type: .Custom)
btnColor.addTarget(self, action: #selector(self.openEmoji), forControlEvents: .TouchUpInside)
btnColor.frame = CGRect(x: CGFloat(textField.frame.size.width - 25), y: CGFloat(5), width: CGFloat(25), height: CGFloat(25))
btnColor.setBackgroundImage(UIImage(named: "send.png"), forState: .Normal)
textField.rightView = btnColor
Create UITextField extension and add below method in it and you can change UIButton code as per your requirement.
func setRightViewIcon(icon: UIImage) {
let btnView = UIButton(frame: CGRect(x: 0, y: 0, width: ((self.frame.height) * 0.70), height: ((self.frame.height) * 0.70)))
btnView.setImage(icon, for: .normal)
btnView.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 3)
self.rightViewMode = .always
self.rightView = btnView
}
For Swift4
func setupUI() {
let imgSearch = UIImageView();
let imgSearch = UIImage(named: "search");
// set frame on image before adding it to the uitextfield
imgSearch.image = imagePassword;
imgSearch.frame = CGRect(x: txtSearchField.frame.size.width - 40 , y: 5, width: 22, height: 22)
txtSearchField.rightView = imgSearch
txtSearchField.rightViewMode = .always
}
Call function like this
// MARK: View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.setupUI()
}