在 UITextField 中快速添加图标/图像

我想在 UITextField 中添加图标/图像。图标/图像应该留给占位符。

enter image description here

我试过了:

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

谢谢。

149270 次浏览

试着加入 emailField.leftViewMode = UITextFieldViewMode.Always

(默认 leftViewModeNever)

更新 Swift 4的答案

emailField.leftViewMode = UITextFieldViewMode.always


emailField.leftViewMode = .always

我还想补充一些东西:

如果要在左侧的 UITextField上添加图像,请使用 UITextFieldleftView属性

NOTE: 不要忘记将 ABC0设置为 ABC1,对于右 ABC2设置为 ABC3,默认值是 UITextFieldViewModeNever

例如:

用于在左侧添加图像

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

用于在右侧添加图像

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

注意: 在 UITextField上添加左边或右边的图像时,有些事情需要注意。

  • 不要忘记给一个框架的 ImageView,你要添加到 UITextField

    Let imageView = UIImageView (画面: CGRect (x: 0,y: 0,宽度: 20,高度: 20))

  • 如果你的图像背景是白色的,那么图像将不会在 UITextField上可见

  • if you want to add an image to the specific position you need to add ImageView as the subview of UITextField.

Swift 3.0更新

@ Mark Moeykens 漂亮地利用了它,把它变成了 @ IBDesignable

我修改并添加了一些更多的功能(添加底线和右边的图像填充)。

注意 如果你想在右边添加一个图像,你可以在 Interface Builder 中选择 semantic中的 Force Right-to-Left选项(但是对于右边的图像填充不起作用,除非你覆盖右边的 ViewRect 方法)。

enter image description here

我已经修改了这一点,并可以从这里下载源 ImageTextField

enter image description here

Sahil 有一个很棒的答案,我想把它扩展成一个@IBDesignable,这样开发者就可以在情节串联板上添加图片到他们的 uitextFields 中。

Swift 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:

  • 在左边设置一个图像
  • 在 UITextField 的左边缘和图像之间添加空白
  • 设置一个颜色,使图像和占位符文本匹配

笔记

  • 要改变图像的颜色,你必须遵循代码中注释中的说明
  • 图像颜色在故事板中不会改变。您必须运行该项目以查看模拟器/设备中的颜色。

可在故事板中设计 Storyboard

在 Runtime Runtime

你为什么不用最简单的方法。对于大多数情况下,你想添加图标,如字体可怕... 只要使用字体可怕的库,它会很容易添加一个图标到一个文本字段如下:

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

你首先需要安装这个快捷库: Https://github.com/vaberer/font-awesome-swift

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


}

为 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

我创建了一个简单的 IBDesignable。使用它无论你喜欢。只要让你的 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)
}


}

可以将此函数放在全局文件或类的上方,以便在整个应用程序中访问它。 在此过程之后,您可以根据应用程序中的要求调用此函数。

        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

enter image description here
另一种设置占位符图标和填充到 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
}

UITextField with image (left or right)

另一种方式,灵感来自以前的职位,使扩展。

我们可以把图像放在右边或者左边

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
}


}

用途:

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

享受:)

这是一个修改版本的马克莫伊肯斯的答案,增加了图像和文字之间的填充和可调整的图像大小,以防有人需要它。

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

为了创建填充,我喜欢将图像放置在容器视图中。你可以删除背景颜色一旦你对图标的位置感到满意。

enter image description here

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

斯威夫特

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

我已经创建了扩展

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

结果

enter image description here

Swift 5

与@Markus 相似,但在 Swift 5中:

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

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()
)

结果

2020 - reasonable solution

关于苹果公司的疯狂举动。

Here is perhaps the "clearest", simplest, way to do it:

enter image description here

首先,您必须正确地移动文本。

注意这个关键的 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)
}
    

接下来,我们现在必须制作并移动左边的图像:

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

这似乎是最清晰、最可靠的方法。

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


}

使用代码作为左图像设置:-

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

产出:)

enter image description here

我不认为基于帧的解决方案是一个好的方法,因为在某些情况下它不能在 iPad 上使用。 理想的解决方案是在 textfield 右视图中添加 ImageView 的约束,但这并不容易。除非有必要,否则右视图不会出现在 textfield 视图层次结构中,因此您需要执行以下操作:

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

任何设备的结果都是:

TextField right view

另外,我的解决方案使用 textfield 左视图。

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

这就是我想要的。在自定义/可重用的类中。有助于在 b/w 空间的实际文本和左视图图标/图像enter image description here

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

为了摆脱@Mark Moeykens 的 回答,我做了一些小小的调整,以便修复一些我遇到的问题:

  1. 我在项目中使用的图像比图像视图大得多(因为我也在应用程序的不同部分使用它们) ,这导致图像视图的大小比必要的大得多。
  2. Gives horizontal padding even if you don't have an image
  3. 允许您设置图像和文本之间的间距

不同的值可以在 Constants枚举中进行调整。

感谢@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
}
}


要使用这个类,你可以这样做:

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

它应该提供如下图所示的内容(取决于如何在初始化器中设置文本字段)。

enter image description here