簡體   English   中英

如何創建一個具有placeHolder,多行和垂直居中的UITextView或UITextField?

[英]How to create a UITextView or a UITextField that has a placeHolder, multiline and vertically centered?

我想要的是一個非常直觀的東西,但是令人驚訝的是它沒有包含在Xcode中:我想要的是一個textView或textField,它將具有

1-占位符
2-幾行(具有類似UITextView的滾動視圖)。
3-文本或占位符應始終在textBoxArea中垂直和水平居中。

我看過類似的問題,例如:
在UITextView中垂直居中放置文本
將文本在UITextView中垂直和水平居中
在UITextView中垂直居中對齊文本

對於placeHolder,我正在使用以下庫:
https://github.com/devxoul/UITextView-Placeholder解決了第一個要求,但是即使上面的鏈接給出了答案,我也無法滿足其他兩個要求

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

不幸的是, UITextViewUITextField是如此有限。 許多開發人員已經做過很多次相同的事情。

我通常要做的就是創建一個新的UIView子類,然后該子類具有2個子視圖。 占位符的標簽和內容的居中文本視圖。

您可以在xib中進行操作,並使用界面構建器,建議您這樣做。 然后,您可以同時顯示文本視圖和占位符,並且實際上可以設置幾乎所需的任何內容。

但是要在代碼中執行此操作,將類似於以下內容:

@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. 文本視圖的委托是視圖本身所需的。 因此,如果您在某些視圖控制器中調用myView.textView.delegate = self ,則會破壞內部的邏輯。 如果需要,建議您在此視圖上創建一個自定義委托,並公開所需的方法,而不是標准的UITextViewDelegate
  2. 盡管該類是可設計的,但是您不能有許多可檢查的字段。 因此,很難在界面生成器中設置任何屬性。 您可以公開諸如“文本”之類的屬性,並將setter和getter指向文本視圖。 可以為文本顏色做同樣的事情……但是最大的問題是您不能將字體標記為可檢查的(我想是對蘋果的哭泣)。
  3. 在某些情況下,進入換行符時文本會跳一些。 我想您需要花一點時間來完善它。 可能是約束條件可以解決此問題,因此,如果您在xib中完成此操作,則可以解決該問題。

幸運的是,您可以從代碼中執行幾乎所有操作。 多行或屬性字符串占位符,對齊方式,顏色,字體...

實際上我有點傻,因為答案一直都在我的眼前。

對於PlaceHolder,我將僅使用該庫:我的問題中提到的https://github.com/devxoul/UITextView-Placeholder

然后在UIViewController類中執行以下操作:

class myClass: UIViewController {

      @IBOutlet weak var myTextView: UITextView!

      override func viewDidLoad() {
          super.viewDidLoad()
          // Set the textView to the Delegate 
          myTextView.delegate = self
          // Initialize the textView text Position and accordingly the
          //   placeholder position 
          myTextView.contentInset.top = max(0, (tv_comment.bounds.size.height - tv_comment.contentSize.height * tv_comment.zoomScale) / 2)

      }

       extension myClass: UITextViewDelegate {
              func textViewDidChange(_ textView: UITextView) {
                   // do the same adjustment again every time the textView changes
                   textView.contentInset.top = max(0, (textView.bounds.size.height - textView.contentSize.height * textView.zoomScale) / 2)
              }
       }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM