Пользовательское текстовое поле с заполнением, выравнивание по вертикали сверху, многострочный текст-заполнитель

#swift #uitextfield #textfield #text-alignment

#swift #uitextfield #текстовое поле #выравнивание текста

Вопрос:

введите описание изображения здесь

Я хочу создать пользовательское текстовое поле с левым правым нижним верхним заполнением. Поэтому я использую приведенный ниже код для достижения этого:

 class CustomTextField: UITextField {

let padding = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8);

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.inset(by: padding)
}

override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.inset(by: padding)
}

override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.inset(by: padding)
} }
  

Я также хочу, чтобы выравнивание текста-заполнителя было сверху, а не по центру TF. Я использую приведенный ниже код:

  textField.contentVerticalAlignment = .top
  

Однако, когда я попытался установить вертикальное выравнивание с помощью отступов, выравнивание не сработало. Только тогда, когда я удалю отступы, это будет работать. Я имел в виду, что это будет работать только с любым из них. Как я могу добиться их обоих? Кроме того, возможно ли отображать многострочный текст-заполнитель вместо отображения его в одной строке с точками в конце?

Ответ №1:

Вам нужно переопределить placeholderRect(forBounds:) , вот так

 override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    var placeholderPadding = self.padding
    placeholderPadding.top = 0

    var rect = bounds.inset(by: placeholderPadding)

    // We need to adjust placeholder in-case there is a leftView or rightView
    if rightViewMode == .always || rightViewMode == .unlessEditing, let rightViewWidth = self.rightView?.frame.width {
        rect.size.width -= rightViewWidth
    }

    if leftViewMode == .always || leftViewMode == .unlessEditing, let leftViewWidth = self.leftView?.frame.width {
        rect.size.width -= leftViewWidth
    }

    return rect
}
  

Вопрос-2: UITextField работает только на 1 строке, для этого вам нужно взглянуть на UITextView

Комментарии:

1. могу ли я узнать, какое условие для if { … } для режима просмотра справа и режима просмотра слева? потому что он показывает ошибку, когда для этого нет условия

2. опечатка, я избавился от этого

3. не работает, все так же, как на скриншоте, который я показываю выше. кстати, спасибо за ваш ответ. Я думаю, мне нужно изменить его на текстовый вид, так как мне нужно более 1 строки текста.

Ответ №2:

для первого вопроса вы можете расширить UIView общедоступным расширением UIView {

 /// SwifterSwift: Border color of view; also inspectable from Storyboard.
@IBInspectable public var borderColor: UIColor? {
    get {
        guard let color = layer.borderColor else { return nil }
        return UIColor(cgColor: color)
    }
    set {
        guard let color = newValue else {
            layer.borderColor = nil
            return
        }
        // Fix React-Native conflict issue
        guard String(describing: type(of: color)) != "__NSCFType" else { return }
        layer.borderColor = color.cgColor
    }
}

/// SwifterSwift: Border width of view; also inspectable from Storyboard.
@IBInspectable public var borderWidth: CGFloat {
    get {
        return layer.borderWidth
    }
    set {
        layer.borderWidth = newValue
    }
}

/// SwifterSwift: Corner radius of view; also inspectable from Storyboard.
@IBInspectable public var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set {
        layer.masksToBounds = true
        layer.cornerRadius = abs(CGFloat(Int(newValue * 100)) / 100)
    }
}

/// SwifterSwift: Height of view.
public var height: CGFloat {
    get {
        return frame.size.height
    }
    set {
        frame.size.height = newValue
    }
}

/// SwifterSwift: Check if view is in RTL format.
public var isRightToLeft: Bool {
    if #available(iOS 10.0, *, tvOS 10.0, *) {
        return effectiveUserInterfaceLayoutDirection == .rightToLeft
    } else {
        return false
    }
}

/// SwifterSwift: Take screenshot of view (if applicable).
public var screenshot: UIImage? {
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, 0)
    defer {
        UIGraphicsEndImageContext()
    }
    guard let context = UIGraphicsGetCurrentContext() else { return nil }
    layer.render(in: context)
    return UIGraphicsGetImageFromCurrentImageContext()
}

/// SwifterSwift: Shadow color of view; also inspectable from Storyboard.
@IBInspectable public var shadowColor: UIColor? {
    get {
        guard let color = layer.shadowColor else { return nil }
        return UIColor(cgColor: color)
    }
    set {
        layer.shadowColor = newValue?.cgColor
    }
}

/// SwifterSwift: Shadow offset of view; also inspectable from Storyboard.
@IBInspectable public var shadowOffset: CGSize {
    get {
        return layer.shadowOffset
    }
    set {
        layer.shadowOffset = newValue
    }
}

/// SwifterSwift: Shadow opacity of view; also inspectable from Storyboard.
@IBInspectable public var shadowOpacity: Float {
    get {
        return layer.shadowOpacity
    }
    set {
        layer.shadowOpacity = newValue
    }
}

/// SwifterSwift: Shadow radius of view; also inspectable from Storyboard.
@IBInspectable public var shadowRadius: CGFloat {
    get {
        return layer.shadowRadius
    }
    set {
        layer.shadowRadius = newValue
    }
}

/// SwifterSwift: Size of view.
public var size: CGSize {
    get {
        return frame.size
    }
    set {
        width = newValue.width
        height = newValue.height
    }
}

/// SwifterSwift: Get view's parent view controller
public var parentViewController: UIViewController? {
    weak var parentResponder: UIResponder? = self
    while parentResponder != nil {
        parentResponder = parentResponder!.next
        if let viewController = parentResponder as? UIViewController {
            return viewController
        }
    }
    return nil
}

/// SwifterSwift: Width of view.
public var width: CGFloat {
    get {
        return frame.size.width
    }
    set {
        frame.size.width = newValue
    }
}

// swiftlint:disable next identifier_name
/// SwifterSwift: x origin of view.
public var x: CGFloat {
    get {
        return frame.origin.x
    }
    set {
        frame.origin.x = newValue
    }
}

// swiftlint:disable next identifier_name
/// SwifterSwift: y origin of view.
public var y: CGFloat {
    get {
        return frame.origin.y
    }
    set {
        frame.origin.y = newValue
    }
}}
  

это предоставит вам эти функции в инспекторе атрибутов

введите описание изображения здесь

что касается второго вопроса, UITextField состоит всего из одной строки, поэтому попробуйте использовать UITextView