Reputation: 4570
I am facing a spacing issue with a right view of UITextField in IOS 13, See my following code and screenshot of ios 13 and ios 12.4
In IOS 12.4 simulator display proper space in the right view (UIButton)of UITextField
In IOS 13.0 simulator has a spacing issue in the right view (UIButton)of UITextField
let dropdownButton = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: txtField.frame.height))
dropdownButton.backgroundColor = UIColor.clear
dropdownButton.setImage(UIImage(named: "ic_DownArrow"), for: UIControl.State())
txtField.rightView = dropdownButton
txtField.rightViewMode = .always
Upvotes: 26
Views: 12948
Reputation: 39
you can change right padding and left padding from the extension which I made ........... you can use IBDesignable or not as you see
import UIKit
@IBDesignable
extension UITextField {
@IBInspectable var paddingLeftCustom: CGFloat {
get {
return leftView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
if leftView == nil {
leftView = paddingView
leftViewMode = .always
}
}
}
@IBInspectable var paddingRightCustom: CGFloat {
get {
return rightView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
if rightView == nil {
rightView = paddingView
rightViewMode = .always
}
}
}
}
Upvotes: 0
Reputation: 868
Another solution I came across for this is to set translatesAutoresizingMaskIntoConstraints
to true
for the view you are assigning to leftView
for iOS 13+ and false
otherwise.
Upvotes: 0
Reputation: 61
This worked for me and it also solves the issue that happens in iPhone X/11, when the rightView takes up full width of the textField:
txtField.rightView = dropdownButton
txtField.translatesAutoresizingMaskIntoConstraints = false
txtField.rightView?.widthAnchor.constraint(equalToConstant: 50).isActive = true
Upvotes: 6
Reputation: 6676
Set the width constraint for the leftView or rightView you're adding.
leftImageView.widthAnchor.set(to: 30.0)
textField.leftView = leftImageView
textField.leftViewMode = .always
Here's the extension I use to set the width constraint:
extension NSLayoutDimension {
@discardableResult
func set(
to constant: CGFloat,
priority: UILayoutPriority = .required
) -> NSLayoutConstraint {
let cons = constraint(equalToConstant: constant)
cons.priority = priority
cons.isActive = true
return cons
}
}
Upvotes: 14
Reputation: 1
I resove the same problem by set this:
override textField rightViewRectForBounds:
method,
- (CGRect)rightViewRectForBounds:(CGRect)bounds {
if (self.rightView) {
CGRect rightFrame = self.rightView.frame;
return CGRectMake(bounds.size.width - rightFrame.size.width, 0, rightFrame.size.width, bounds.size.height);
}
return CGRectZero;
}
Upvotes: 0
Reputation: 461
Apparently this was a change in the way rightViewRect(forBounds:) behaves in iOS 13 Beta 5.
From the iOS & iPadOS 13 Developer Beta 5 Release Notes:
UIKit - Resolved Issues
Prior to iOS 13, UITextField assumed that the frames of its leftView and rightView were correctly set when assigned and would never change. Starting in iOS 13, the implementation of leftViewRect(forBounds:) and rightViewRect(forBounds:) now ask the view for its systemLayoutSizeFitting(:). To achieve the previous behavior when linking against and running on iOS 13, add explicit sizing constraints on the view, wrap it in a plain UIView, or subclass the view and implement systemLayoutSizeFitting(:). (51787798)
So Add Auto-Layout constraints to your custom view that you added to the rightView
Example:-
override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.width - 30, y: 0, width: 20 , height: bounds.height)
}
Upvotes: 33
Reputation: 1378
I got it to work using Bruno's method.
1) Create a container view and set its width and height using auto layout. Width and height should include the subview's size + required spacing.
2) Create the subview you want to show in the text field. Set the width, height, and layout using auto layout. Add it to the container view.
3) Add the container view to the text field
You can see my container matches the height of the text field. The width is the width of the button (44), plus the spacing I want (16). When I add my subview I'll align it to the left of the container. That will give me 16px spacing between the right of the button and the edge of the text field.
let forgotButtonContainer = UIView()
forgotButtonContainer.translatesAutoresizingMaskIntoConstraints = false
forgotButtonContainer.widthAnchor.constraint(equalToConstant: 44.0 + 16.0).isActive = true
forgotButtonContainer.heightAnchor.constraint(equalToConstant: 48.0).isActive = true
forgotButton = PFSecondaryButton(link: "Forgot?")
forgotButton.translatesAutoresizingMaskIntoConstraints = false
forgotButtonContainer.addSubview(forgotButton)
forgotButton.topAnchor.constraint(equalTo: forgotButtonContainer.topAnchor).isActive = true
forgotButton.leftAnchor.constraint(equalTo: forgotButtonContainer.leftAnchor).isActive = true
forgotButton.bottomAnchor.constraint(equalTo: forgotButtonContainer.bottomAnchor).isActive = true
passwordField.rightView = forgotButtonContainer
Upvotes: 2
Reputation: 2876
Probably your image is smaller than width: 50, height: txtField.frame.height
, so your button is reduced.
You can try add some container:
let dropdownButton = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: txtField.frame.height))
dropdownButton.backgroundColor = .clear
dropdownButton.setImage(UIImage(named: "ic_DownArrow"), for: UIControl.State())
let container = UIView(frame: dropdownButton.frame)
container.backgroundColor = .clear
container.addSubview(dropdownButton)
txtField.rightView = container
txtField.rightViewMode = .always
Upvotes: 4