IOS 13:UITextField rightView 的间距问题

IOS 13: spacing Issue with UITextField rightView

我在 IOS 13 中面临 UITextField 右视图的间距问题,请参阅我的以下代码和 ios 13 和 ios 12.4

的屏幕截图

在IOS 12.4模拟器中正确显示space在UITextField的右视图(UIButton)

在 IOS 13.0 模拟器中,UITextField 的右视图 (UIButton) 存在间距问题

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

可能你的图片比width: 50, height: txtField.frame.height小,所以你的按钮缩小了。

您可以尝试添加一些容器:

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

显然这是 rightViewRect(forBounds:) 在 iOS 13 Beta 5 中的行为方式的变化。

来自 iOS 和 iPadOS 13 Developer Beta 5 发行说明:

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)

因此,将自动布局约束添加到您添加到 rightView 的自定义视图中

示例:-

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(x: bounds.width - 30, y: 0, width: 20 , height: bounds.height)
    }

我使用 Bruno 的方法让它工作。

1) 创建容器视图并使用自动布局设置其宽度和高度。宽度和高度应包括子视图的大小 + 所需间距。

2) 创建要在文本字段中显示的子视图。使用自动布局设置宽度、高度和布局。将其添加到容器视图。

3) 将容器视图添加到文本字段

您可以看到我的容器与文本字段的高度相匹配。宽度是按钮的宽度(44)加上我想要的间距(16)。当我添加我的子视图时,我会将它对齐到容器的左侧。这将使我在按钮右侧和文本字段边缘之间有 16 像素的间距。

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

我通过这样设置解决了同样的问题:

覆盖 textField rightViewRectForBounds: 方法,

- (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;
}

为您要添加的 leftView 或 rightView 设置宽度限制。

leftImageView.widthAnchor.set(to: 30.0)
textField.leftView = leftImageView
textField.leftViewMode = .always

这是我用来设置宽度限制的扩展:

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
    }
}

这对我有用,它还解决了 iPhone X/11 中发生的问题,当 rightView 占据了 textField 的整个宽度时:

txtField.rightView = dropdownButton
txtField.translatesAutoresizingMaskIntoConstraints = false
txtField.rightView?.widthAnchor.constraint(equalToConstant: 50).isActive = true

我遇到的另一种解决方案是将 translatesAutoresizingMaskIntoConstraints 设置为 true,以便为 iOS 13+ 和 [=13] 分配给 leftView 的视图=] 否则。

你可以从我做的扩展中改变右填充和左填充 ………… 你可以像你看到的那样使用或不使用 IBDesignable

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
            }
            
        }
    }
}