简体   繁体   English

Swift 在 UITextField 中添加图标/图像

[英]Swift add icon/image in UITextField

I would like to add icon/image in UITextField.我想在 UITextField 中添加图标/图像。 The icon/image should be left to placeholder.图标/图像应留给占位符。

在此处输入图像描述

I tried this:我试过这个:

var imageView = UIImageView();
var image = UIImage(named: "email.png");
imageView.image = image;
emailField.leftView = imageView;

Thanks.谢谢。

Sahil has a great answer and I wanted to take that and expand it into an @IBDesignable so developers can add images to their UITextFields on the Storyboard. Sahil 有一个很好的答案,我想将其扩展为 @IBDesignable,以便开发人员可以将图像添加到 Storyboard 上的 UITextField 中。

Swift 4.2斯威夫特 4.2

import UIKit

@IBDesignable
class DesignableUITextField: UITextField {
    
    // Provides left padding for images
    override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
        var textRect = super.leftViewRect(forBounds: bounds)
        textRect.origin.x += leftPadding
        return textRect
    }
    
    @IBInspectable var leftImage: UIImage? {
        didSet {
            updateView()
        }
    }
    
    @IBInspectable var leftPadding: CGFloat = 0
    
    @IBInspectable var color: UIColor = UIColor.lightGray {
        didSet {
            updateView()
        }
    }
    
    func updateView() {
        if let image = leftImage {
            leftViewMode = UITextField.ViewMode.always
            let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
            imageView.contentMode = .scaleAspectFit
            imageView.image = image
            // Note: In order for your image to use the tint color, you have to select the image in the Assets.xcassets and change the "Render As" property to "Template Image".
            imageView.tintColor = color
            leftView = imageView
        } else {
            leftViewMode = UITextField.ViewMode.never
            leftView = nil
        }
        
        // Placeholder text color
        attributedPlaceholder = NSAttributedString(string: placeholder != nil ?  placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: color])
    }
}

What is happening here?这里发生了什么?

This designable allows you to:这个可设计允许您:

  • Set an image on the left在左侧设置图像
  • Add padding between the left edge of the UITextField and the image在 UITextField 的左边缘和图像之间添加填充
  • Set a color so the image and the Placeholder text matches设置颜色以使图像和占位符文本匹配

Notes笔记

  • For image color to change you have to follow that note in the comment in the code要更改图像颜色,您必须遵循代码注释中的注释
  • The image color will not change in the Storyboard.故事板中的图像颜色不会改变。 You have to run the project to see the color in the Simulator/device.您必须运行项目才能看到模拟器/设备中的颜色。

Designable in the Storyboard可在情节提要中设计故事板

At Runtime在运行时运行

Try adding emailField.leftViewMode = UITextFieldViewMode.Always尝试添加emailField.leftViewMode = UITextFieldViewMode.Always

(Default leftViewMode is Never ) (默认leftViewModeNever

Updated Answer for Swift 4 Swift 4的更新答案

emailField.leftViewMode = UITextFieldViewMode.always

emailField.leftViewMode = .always

I Just want to add some more thing here:我只想在这里添加更多内容:

If you want to add the image on UITextField on left side use leftView property of UITextField如果要在左侧的UITextField上添加图像,请使用UITextFieldleftView属性

NOTE: Don't forget to set leftViewMode to UITextFieldViewMode.Always and for right rightViewMode to UITextFieldViewMode.Always and default is UITextFieldViewModeNever注意:不要忘记将leftViewMode设置为UITextFieldViewMode.Always ,将rightViewMode设置为UITextFieldViewMode.Always and默认为UITextFieldViewModeNever

for eg例如

For adding an image on left side用于在左侧添加图像

textField.leftViewMode = UITextFieldViewMode.Always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
let image = UIImage(named: imageName)
imageView.image = image
textField.leftView = imageView

For adding an image on right side用于在右侧添加图像

textField.rightViewMode = UITextFieldViewMode.Always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
let image = UIImage(named: imageName)
imageView.image = image
textField.rightView = imageView

NOTE: some things you need to take care while adding an image on UITextField either on the left side or right side.注意:在左侧或右侧的UITextField上添加图像时需要注意一些事项。

  • Don't forget to give a frame of ImageView which are you going to add on UITextField不要忘记给你要添加到UITextField上的ImageView框架

    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))让 imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))

  • if your image background is white then image won't visible on UITextField如果您的图像背景是白色的,则图像在UITextField上不可见

  • if you want to add an image to the specific position you need to add ImageView as the subview of UITextField .如果要将图像添加到特定位置,则需要将ImageView添加为UITextField的子视图。

Update For Swift 3.0更新 Swift 3.0

@Mark Moeykens Beautifully expended it and make it @IBDesignable . @Mark Moeykens 精美地使用它并使其成为@IBDesignable

I modified and added some more features (add Bottom Line and padding for right image) in this.我在此修改并添加了更多功能(为右图添加底线和填充)。

NOTE if you want to add an image on the right side you can select the Force Right-to-Left option in semantic in interface builder(But for right image padding won't work until you will override rightViewRect method ).注意如果您想在右侧添加图像,您可以在界面构建器的semantic中选择Force Right-to-Left选项(但对于右图像填充将不起作用,直到您将覆盖 rightViewRect 方法)。

在此处输入图像描述

I have modified this and can download the source from here ImageTextField我已经修改了这个,可以从这里ImageTextField下载源代码

在此处输入图像描述

带图像的 UITextField(左或右)

Another way, inspired from previous posts to make an extension.另一种方式,灵感来自以前的帖子进行扩展。

We can put the image on the right or on the left我们可以把图像放在右边或左边

extension UITextField {

enum Direction {
    case Left
    case Right
}

// add image to textfield
func withImage(direction: Direction, image: UIImage, colorSeparator: UIColor, colorBorder: UIColor){
    let mainView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 45))
    mainView.layer.cornerRadius = 5

    let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 45))
    view.backgroundColor = .white
    view.clipsToBounds = true
    view.layer.cornerRadius = 5
    view.layer.borderWidth = CGFloat(0.5)
    view.layer.borderColor = colorBorder.cgColor
    mainView.addSubview(view)

    let imageView = UIImageView(image: image)
    imageView.contentMode = .scaleAspectFit
    imageView.frame = CGRect(x: 12.0, y: 10.0, width: 24.0, height: 24.0)
    view.addSubview(imageView)

    let seperatorView = UIView()
    seperatorView.backgroundColor = colorSeparator
    mainView.addSubview(seperatorView)

    if(Direction.Left == direction){ // image left
        seperatorView.frame = CGRect(x: 45, y: 0, width: 5, height: 45)
        self.leftViewMode = .always
        self.leftView = mainView
    } else { // image right
        seperatorView.frame = CGRect(x: 0, y: 0, width: 5, height: 45)
        self.rightViewMode = .always
        self.rightView = mainView
    }

    self.layer.borderColor = colorBorder.cgColor
    self.layer.borderWidth = CGFloat(0.5)
    self.layer.cornerRadius = 5
}

}

Use :利用 :

if let myImage = UIImage(named: "my_image"){
    textfield.withImage(direction: .Left, image: myImage, colorSeparator: UIColor.orange, colorBorder: UIColor.black)
}

Enjoy :)享受 :)

To create padding, I like to place the image inside of a container view.为了创建填充,我喜欢将图像放置在容器视图中。 You can remove the background color once you are happy with the icon placement.一旦您对图标位置感到满意,您就可以删除背景颜色。

在此处输入图像描述

let imageView = UIImageView(frame: CGRect(x: 8.0, y: 8.0, width: 24.0, height: 24.0))
let image = UIImage(named: "my_icon")
imageView.image = image
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = UIColor.red

let view = UIView(frame: CGRect(x: 0, y: 0, width: 32, height: 40))
view.addSubview(imageView)
view.backgroundColor = .green
textField.leftViewMode = UITextFieldViewMode.always
textField.leftView = view

for Swift 3.0 add image on leftside of textField对于 Swift 3.0 在 textField 的左侧添加图像

textField.leftView = UIImageView(image: "small-calendar")
textField.leftView?.frame = CGRect(x: 0, y: 5, width: 20 , height:20)
textField.leftViewMode = .always

Swift 5斯威夫特 5

@IBOutlet weak var paswd: UITextField! {
    didSet{
      paswd.setLeftView(image: UIImage.init(named: "password")!)
      paswd.tintColor = .darkGray
      paswd.isSecureTextEntry = true
    }   
 }

I have created extension我创建了扩展

extension UITextField {
  func setLeftView(image: UIImage) {
    let iconView = UIImageView(frame: CGRect(x: 10, y: 10, width: 25, height: 25)) // set your Own size
    iconView.image = image
    let iconContainerView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 45))
    iconContainerView.addSubview(iconView)
    leftView = iconContainerView
    leftViewMode = .always
    self.tintColor = .lightGray
  }
}

Result结果

在此处输入图像描述

2020 - reasonable solution 2020 - 合理的解决方案

Regarding this insanity from Apple.关于苹果的这种精神错乱。

Here is perhaps the "clearest", simplest, way to do it:这也许是“最清晰”、最简单的方法:

在此处输入图像描述

First, you must correctly move the text.首先,您必须正确移动文本。

Note this critical QA: https://stackoverflow.com/a/27066764/294884请注意这个关键的 QA: https ://stackoverflow.com/a/27066764/294884

class TidyTextField: UITextField {
    
    @IBInspectable var leftImage: UIImage? = nil
    @IBInspectable var leftPadding: CGFloat = 0
    @IBInspectable var gapPadding: CGFloat = 0
    
    private var textPadding: UIEdgeInsets {
        let p: CGFloat = leftPadding + gapPadding + (leftView?.frame.width ?? 0)
        return UIEdgeInsets(top: 0, left: p, bottom: 0, right: 5)
    }
    
    override open func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textPadding)
    }
    
    override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textPadding)
    }
    
    override open func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.inset(by: textPadding)
    }
    

continuing, we now have to make and move the left image:继续,我们现在必须制作并移动左侧图像:

    override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
        var r = super.leftViewRect(forBounds: bounds)
        r.origin.x += leftPadding
        return r
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    
    private func setup() {
        if let image = leftImage {
            if leftView != nil { return } // critical!
            
            let im = UIImageView()
            im.contentMode = .scaleAspectFit
            im.image = image
            
            leftViewMode = UITextField.ViewMode.always
            leftView = im
            
        } else {
            leftViewMode = UITextField.ViewMode.never
            leftView = nil
        }
    }
}

This seems to be about the clearest, most reliable way to do it.这似乎是最清晰、最可靠的方法。

Using the extension in Swift4, We can easily put the image on the right or on the left with padding to TextField.使用 Swift4 中的扩展,我们可以轻松地将图像放在右侧或左侧,并为 TextField 提供填充。

extension UITextField {

    //MARK:- Set Image on the right of text fields

  func setupRightImage(imageName:String){
    let imageView = UIImageView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
    imageView.image = UIImage(named: imageName)
    let imageContainerView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 55, height: 40))
    imageContainerView.addSubview(imageView)
    rightView = imageContainerView
    rightViewMode = .always
    self.tintColor = .lightGray
}

 //MARK:- Set Image on left of text fields

    func setupLeftImage(imageName:String){
       let imageView = UIImageView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
       imageView.image = UIImage(named: imageName)
       let imageContainerView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 55, height: 40))
       imageContainerView.addSubview(imageView)
       leftView = imageContainerView
       leftViewMode = .always
       self.tintColor = .lightGray
     }

  }

Use code as for left image setup:-使用代码作为左图像设置:-

   self.password_text_field.setupLeftImage(imageName: "unlock")

Output :)输出 :)

在此处输入图像描述

Swift 3.1斯威夫特 3.1

extension UITextField
{
    enum Direction
    {
        case Left
        case Right
    }

    func AddImage(direction:Direction,imageName:String,Frame:CGRect,backgroundColor:UIColor)
    {
        let View = UIView(frame: Frame)
        View.backgroundColor = backgroundColor

        let imageView = UIImageView(frame: Frame)
        imageView.image = UIImage(named: imageName)

        View.addSubview(imageView)

        if Direction.Left == direction
        {
            self.leftViewMode = .always
            self.leftView = View
        }
        else
        {
            self.rightViewMode = .always
            self.rightView = View
        }
    }

}

I created a simple IBDesignable.我创建了一个简单的 IBDesignable。 Use it however u like.随心所欲地使用它。 Just make your UITextField confirm to this class.只需让您的 UITextField 确认此类。

import UIKit

@IBDesignable
class RoundTextField : UITextField {
    @IBInspectable var cornerRadius : CGFloat = 0{
        didSet{
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }

    @IBInspectable var borderWidth : CGFloat = 0 {
        didSet{
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var borderColor : UIColor? {
        didSet {
            layer.borderColor = borderColor?.cgColor
        }
    }

    @IBInspectable var bgColor : UIColor? {
        didSet {
            backgroundColor = bgColor
        }
    }

    @IBInspectable var leftImage : UIImage? {
        didSet {
            if let image = leftImage{
                leftViewMode = .always
                let imageView = UIImageView(frame: CGRect(x: 20, y: 0, width: 20, height: 20))
                imageView.image = image
                imageView.tintColor = tintColor
                let view = UIView(frame : CGRect(x: 0, y: 0, width: 25, height: 20))
                view.addSubview(imageView)
                leftView = view
            }else {
                leftViewMode = .never
            }

        }
    }

    @IBInspectable var placeholderColor : UIColor? {
        didSet {
            let rawString = attributedPlaceholder?.string != nil ? attributedPlaceholder!.string : ""
            let str = NSAttributedString(string: rawString, attributes: [NSForegroundColorAttributeName : placeholderColor!])
            attributedPlaceholder = str
        }
    }

    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: 50, dy: 5)
    }

    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: 50, dy: 5)
    }

}

在此处输入图像描述
Another way to set placeholder icon & set padding to TextField.另一种设置占位符图标并将填充设置为 TextField 的方法。

let userIcon = UIImage(named: "ImageName") 
setPaddingWithImage(image: userIcon, textField: txtUsername)

func setPaddingWithImage(image: UIImage, textField: UITextField){
    let imageView = UIImageView(image: image)
    imageView.contentMode = .scaleAspectFit
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: 50))
    imageView.frame = CGRect(x: 13.0, y: 13.0, width: 24.0, height: 24.0)
    //For Setting extra padding other than Icon.
    let seperatorView = UIView(frame: CGRect(x: 50, y: 0, width: 10, height: 50))
    seperatorview.backgroundColor = UIColor(red: 80/255, green: 89/255, blue: 94/255, alpha: 1)
    view.addSubview(seperatorView)
    textField.leftViewMode = .always
    view.addSubview(imageView)
    view.backgroundColor = .darkGray
    textField.leftViewMode = UITextFieldViewMode.always
    textField.leftView = view
}

You can put this function your global file or above your class so you can access it in entire application.您可以将此函数放在您的全局文件或您的类之上,以便您可以在整个应用程序中访问它。 After this procedure you can call this function as per your requirement in application.在此过程之后,您可以根据应用程序的要求调用此函数。

        func SetLeftSIDEImage(TextField: UITextField, ImageName: String){

                let leftImageView = UIImageView()
                leftImageView.contentMode = .scaleAspectFit

                let leftView = UIView()

                leftView.frame = CGRect(x: 20, y: 0, width: 30, height: 20)
                leftImageView.frame = CGRect(x: 13, y: 0, width: 15, height: 20)
                TextField.leftViewMode = .always
                TextField.leftView = leftView

                let image = UIImage(named: ImageName)?.withRenderingMode(.alwaysTemplate)
                leftImageView.image = image
                leftImageView.tintColor = UIColor(red: 106/255, green: 79/255, blue: 131/255, alpha: 1.0)
                leftImageView.tintColorDidChange()

                leftView.addSubview(leftImageView)
            }

            SetLeftSIDEImage(TextField: Your_textField, ImageName: “YourImageName”) // call function

Why don't you go for the easiest approach.你为什么不选择最简单的方法。 For most cases you want to add icons like font awesome... Just use font awesome library and it would be as easy to add an icon to an text field as this:在大多数情况下,您想添加像 font awesome 之类的图标...只需使用 font awesome 库,就可以很容易地将图标添加到文本字段,如下所示:

myTextField.setLeftViewFAIcon(icon: .FAPlus, leftViewMode: .always, textColor: .red, backgroundColor: .clear, size: nil)

You would need to install first this swift library: https://github.com/Vaberer/Font-Awesome-Swift您需要先安装这个 swift 库: https ://github.com/Vaberer/Font-Awesome-Swift

This is a modified version of Mark Moeykens' answer with added padding between image and text and adjustable image size in case somebody needs it.这是 Mark Moeykens 答案的修改版本,在图像和文本之间添加了填充,并在有人需要时可调整图像大小。

Swift 4斯威夫特 4

    import UIKit

    @IBDesignable
    class TextFieldWithImage: UITextField {

        override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
            return super.leftViewRect(forBounds: bounds)
        }

        @IBInspectable var leftImage: UIImage? {
            didSet {
                updateView()
            }
        }
        @IBInspectable var leftPadding: CGFloat = 0 {
            didSet {
                updateView()
            }
        }
        @IBInspectable var rightPadding: CGFloat = 0 {
            didSet {
                updateView()
            }
        }
        @IBInspectable var imageMaxHeight: CGFloat = 0 {
            didSet {
                updateView()
            }
        }

        @IBInspectable var color: UIColor = UIColor.lightGray {
            didSet {
                updateView()
            }
        }

        func updateView() {
            if let image = leftImage {
                leftViewMode = UITextField.ViewMode.always

                let containerSize = calculateContainerViewSize(for: image)
                let containerView = UIView(frame: CGRect(x: 0, y: 0, width: containerSize.width, height: containerSize.height))

                let imageView = UIImageView(frame: .zero)
                containerView.addSubview(imageView)
                setImageViewConstraints(imageView, in: containerView)

                setImageViewProperties(imageView, image: image)

                leftView = containerView
            } else {
                leftViewMode = UITextField.ViewMode.never
                leftView = nil
            }

            attributedPlaceholder = NSAttributedString(string: placeholder != nil ? placeholder! : "",
                    attributes: [NSAttributedString.Key.foregroundColor: color])
        }

        private func calculateContainerViewSize(for image: UIImage) -> CGSize {
            let imageRatio = image.size.height / image.size.width
            let adjustedImageMaxHeight = imageMaxHeight > self.frame.height ? self.frame.height : imageMaxHeight

            var imageSize = CGSize()
            if image.size.height > adjustedImageMaxHeight {
                imageSize.height = adjustedImageMaxHeight
                imageSize.width = imageSize.height / imageRatio
            }

            let paddingWidth = leftPadding + rightPadding

            let containerSize = CGSize(width: imageSize.width + paddingWidth, height: imageSize.height)
            return containerSize
        }

        private func setImageViewConstraints(_ imageView: UIImageView, in containerView: UIView) {
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
            imageView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
            imageView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -rightPadding).isActive = true
            imageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: leftPadding).isActive = true
        }

        private func setImageViewProperties(_ imageView: UIImageView, image: UIImage) {
            imageView.contentMode = .scaleAspectFit
            imageView.image = image
            imageView.tintColor = color
        }
    }

Swift 5斯威夫特 5

Similar to @Markus, but in Swift 5 :类似于@Markus,但在Swift 5中:

emailTextField.leftViewMode = UITextField.ViewMode.always
emailTextField.leftViewMode = .always

SwiftUI SwiftUI

RoundedRectangle(cornerRadius: 50)
                .frame(height: 40)
                .colorInvert() // sets the background white
            .padding()
            .shadow(radius: 12) // adds shadow to the rectangle
                .overlay(
                    HStack(spacing: 20){

                        Image(systemName: "person")
                            .resizable()
                            .aspectRatio(contentMode: .fit)

                        TextField("Username ", text: $username)
                            .font(Font.custom("Arial", size: 25))


                            .font(.title)
                    }
                    .padding()
                    .padding()
                )

Results结果

I don't think that frame-based solutions are a good approach, because it won't be available on an iPad in some cases.我不认为基于框架的解决方案是一个好方法,因为在某些情况下它不会在 iPad 上可用。 The ideal solution would be to add constraints from imageView to textfield right view, but it's not that easy.理想的解决方案是将 imageView 的约束添加到文本字段右视图,但这并不容易。 The right view does not appear to be in textfield view hierarchy unless it is required, so you need to do the following:除非需要,否则右视图似乎不在文本字段视图层次结构中,因此您需要执行以下操作:

    private let countryTextField: UITextField = {
        let countryTextField = UITextField()
        countryTextField.translatesAutoresizingMaskIntoConstraints = false
        countryTextField.rightViewMode = .always
        
        let button = UIButton(type: .system)
        button.setImage(UIImage(named: "yourImageName"), for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        
        countryTextField.rightView = button
        countryTextField.setNeedsLayout() //Add rightView in textField hierarchy
        countryTextField.layoutIfNeeded() //Add rightView in textField hierarchy
        
        button.topAnchor.constraint(equalTo: countryTextField.topAnchor).isActive = true
        button.bottomAnchor.constraint(equalTo: countryTextField.bottomAnchor).isActive = true
        button.widthAnchor.constraint(equalTo: countryTextField.heightAnchor).isActive = true
        
        return countryTextField
    }()

And the result on any device is:任何设备上的结果都是:

TextField 右视图

Also, my solution works with textfield left view.此外,我的解决方案适用于文本字段左视图。

let image = UIImage(systemName: "envelope")
let textField = UITextField()
textField.leftView = UIImageView(image: image)
textField.leftView?.frame = CGRect(x: 5, y: 5, width: 20 , height:20)
textField.leftViewMode = .always

This did it for me.这为我做到了。 in a custom/reusable class.在自定义/可重用类中。 helps alot with the space in b/w the actual text and left view icon/image对黑白实际文本和左视图图标/图像的空间有很大帮助在此处输入图像描述

func currencyLeftVeiw(image litery: UIImage) {
        self.leftView = UIView(frame: CGRect(x: 10, y: 0, width: 40, height: 40))
        self.leftViewMode = .always
        let leftViewItSelf = UIImageView(frame: CGRect(x: 10, y: 10, width: 20, height: 20))
        leftViewItSelf.image = litery
        leftView?.addSubview(leftViewItSelf)
    }

To go off @Mark Moeykens's answer , I made some slight adjustments so that it fixed some issues that I was getting:为了摆脱@Mark Moeykens 的回答,我做了一些细微的调整,以解决我遇到的一些问题:

  1. The images I have in my project are much larger than the image view size (since I'm using them in different parts of the app as well), which was causing the size of the image view to be much larger than necessary.我在项目中拥有的图像比图像视图大小大得多(因为我也在应用程序的不同部分使用它们),这导致图像视图的大小比必要的大得多。
  2. Gives horizontal padding even if you don't have an image即使您没有图像,也可以提供水平填充
  3. Allows you to set spacing between the image and the text允许您设置图像和文本之间的间距

The different values can be adjusted in the Constants enum.可以在Constants枚举中调整不同的值。

Credit goes to @Mark Moeykens归功于@Mark Moeykens

import UIKit

final class PaddingWithImageTextField: UITextField {
    private enum Constants {
        static let iconLength: CGFloat = 24.0
        static let imageTextSpacing: CGFloat = 8.0
        static let horizontalPadding: CGFloat = 12.0
        static let placeholderColor = UIColor.lightGray
    }

    var leftImage: UIImage? { didSet { updateView() } }
    var rightImage: UIImage? { didSet { updateView() } }
    override var placeholder: String? {
        didSet {
            attributedPlaceholder = NSAttributedString(string: placeholder != nil ?  placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: Constants.placeholderColor])
        }
    }

    init() {
        super.init(frame: .zero)

        // Any additional setup you may need.
        /*
        layer.cornerRadius = 8.0
        clipsToBounds = true
        keyboardType = .asciiCapable
        backgroundColor = UIColor(hexString: "#F5F5F5")
        */

        updateView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func updateView() {
        leftViewMode = .always
        rightViewMode = .always
        if let image = leftImage {
            // Setting the rendering mode allows us to set the tint color and change the entire color of the image.
            let imageView = UIImageView(image: image.withRenderingMode(.alwaysTemplate))
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.widthAnchor.constraint(equalToConstant: Constants.iconLength).isActive = true
            imageView.heightAnchor.constraint(equalToConstant: Constants.iconLength).isActive = true
            imageView.contentMode = .scaleAspectFit
            imageView.tintColor = Constants.placeholderColor
            let stack = UIStackView(arrangedSubviews: [
                createHorizontalPaddingView(),
                imageView,
                createImageToTextPaddingView()
            ])
            stack.axis = .horizontal
            leftView = stack
        } else {
            leftView = createHorizontalPaddingView()
        }

        if let image = rightImage {
            // Setting the rendering mode allows us to set the tint color and change the entire color of the image.
            let imageView = UIImageView(image: image.withRenderingMode(.alwaysTemplate))
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.widthAnchor.constraint(equalToConstant: Constants.iconLength).isActive = true
            imageView.heightAnchor.constraint(equalToConstant: Constants.iconLength).isActive = true
            imageView.contentMode = .scaleAspectFit
            imageView.tintColor = Constants.placeholderColor
            let stack = UIStackView(arrangedSubviews: [
                createImageToTextPaddingView(),
                imageView,
                createHorizontalPaddingView()
            ])
            stack.axis = .horizontal
            rightView = stack
        } else {
            rightView = createHorizontalPaddingView()
        }
    }

    private func createHorizontalPaddingView() -> UIView {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.widthAnchor.constraint(equalToConstant: Constants.horizontalPadding).isActive = true
        return view
    }

    private func createImageToTextPaddingView() -> UIView {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.widthAnchor.constraint(equalToConstant: Constants.imageTextSpacing).isActive = true
        return view
    }
}

To use this class you can do something like this:要使用此类,您可以执行以下操作:

let textField = PaddingWithImageTextField()
textField.placeholder = "Code"
textField.leftImage = UIImage() // Your image here
textField.rightImage = UIImage() // Your other image here

which should give you something like the following image (depending on how you set up the text field in the initializer).这应该会给您类似下图的内容(取决于您在初始化程序中设置文本字段的方式)。

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM