ios - 如何创建具有 placeHolder、多行和垂直居中的 UITextView 或 UITextField?

标签 ios iphone swift

我想要的是一个非常直观的东西,但令人惊讶的是它没有包含在 Xcode 中: 我想要的是一个 textView 或一个 textField 将有

1- 占位符
2- 几行(像 UITextView 中的 ScrollView )。
3- 文本或占位符应始终在 textBoxArea 中垂直和水平居中。

我看过类似的问题,例如:
Center text vertically in a UITextView
Center the text in a UITextView, vertically and horizontally
Aligning text vertically center in UITextView

对于 placeHolder,我使用以下库:
https://github.com/devxoul/UITextView-Placeholder 这解决了第一个要求,但即使上面的链接中给出了答案,我也无法满足其他 2 个要求

我正在使用 swift 3.1,部署目标 iOS9,Xcode 8.3.2

最佳答案

不幸的是 UITextViewUITextField 都非常有限。如此多的开发人员已多次完成同样的事情。

我通常做的只是创建一个新的 UIView 子类,然后有 2 个 subview ;内容的占位符和居中 TextView 的标签。

您可以在 xib 中执行此操作并使用界面构建器,我建议您这样做。然后您可以公开 TextView 和占位符,您实际上可以设置几乎任何您需要的东西。

但要在代码中执行它,它看起来像下面这样:

@IBDesignable class CustomTextView: UIView {

    private(set) var textView: UITextView = UITextView(frame: CGRect.zero)
    private(set) var placeholderLabel: UILabel = UILabel(frame: CGRect.zero)

    @IBInspectable var placeholder: String? {
        didSet {
            placeholderLabel.text = placeholder
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    private func setup() {
        textView.delegate = self
        addSubview(textView)
        textView.backgroundColor = UIColor.clear
        textView.textAlignment = .center

        addSubview(placeholderLabel)
        placeholderLabel.textAlignment = .center
        placeholderLabel.numberOfLines = 0

        addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap)))
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        refreshViews()
    }

    fileprivate func refreshViews() {
        UIView.performWithoutAnimation {
            textView.frame = self.bounds

            let optimalSize = textView.sizeThatFits(bounds.size)
            textView.frame = CGRect(x: 0.0, y: max((bounds.size.height-optimalSize.height)*0.5, 0.0), width: bounds.width, height: min(optimalSize.height, bounds.size.height))
            placeholderLabel.frame = bounds
            placeholderLabel.backgroundColor = UIColor.clear

            if textView.text.isEmpty && textView.isFirstResponder == false {
                placeholderLabel.text = placeholder
                placeholderLabel.isHidden = false
                textView.isHidden = true
            } else {
                placeholderLabel.isHidden = true
                textView.isHidden = false
            }
        }
    }

    @objc private func onTap() {
        if !textView.isFirstResponder {
            textView.becomeFirstResponder()
        }
    }

}

extension CustomTextView: UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        refreshViews()
    }

    func textViewDidBeginEditing(_ textView: UITextView) {
        refreshViews()
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        refreshViews()
    }

}

不过还是有一些缺点:

  1. View 本身需要 TextView 的委托(delegate)。因此,如果您在某些 View Controller 中调用 myView.textView.delegate = self,您将破坏内部逻辑。如果您需要它,我建议您在此 View 上创建一个自定义委托(delegate)并公开您需要的方法,而不是标准的 UITextViewDelegate
  2. 尽管类是可设计的,但您不能有太多可检查的字段。所以在界面生成器中设置任何属性有点困难。您可以公开诸如“文本”之类的属性,并将 setter 和 getter 指向 TextView 。可以对文本颜色做同样的事情......但最大的问题是你不能将字体标记为可检查的(我想苹果哭了)。
  3. 在某些情况下,文本在进入换行符时会跳动一点。我想您需要稍微尝试一下才能完善它。约束可能会解决这个问题,所以如果你在 xib 中制作它,这就可以解决它。

虽然您可以从代码中执行几乎所有操作,但这是一件好事。多行或属性字符串占位符、对齐方式、颜色、字体...

关于ios - 如何创建具有 placeHolder、多行和垂直居中的 UITextView 或 UITextField?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44260747/

相关文章:

ios - Swift 中的多个选择器 View

ios - 自定义 UITableViewCell 元素不仅仅出现在 iPad 上

iphone - 从 CGAffineTransform 中查找比例值

ios - 对于特定对象,使一个数组等于另一个数组

iphone - 用于 webkit 的 CSS/HTML 文本换行

当从链接安装应用程序时,iOS 应用程序传递特定的 ID

swift - Core Graphics 不绘制某些线条

swift - “ fatal error :在展开可选值时意外发现nil”是什么意思?

ios - 如何在 Swift 中显示当前 PDF 页码并将该页码保存为书签?

ios - 将数组中的闭包/ block 作为参数传递 iOS