【问题标题】:How to add an observer for a changing height?如何为变化的高度添加观察者?
【发布时间】:2016-06-27 15:16:16
【问题描述】:

我有一个文本字段区域,它应该具有灵活的高度,随着您编写的行数增长。

我想听听它的高度变化,然后当创建新行时,这个听众会说“嗨,高度已经改变了!”。

---------- 初始高度 ----------

--------- 高度变了!!! ----------

我找不到合适的方法来做到这一点,因为 addObserver 在 swift 中需要像 keyboardWillShow 这样的 NotificationIdentifier,而这里我没有像 heightWillChange 这样的 NotificationIdentifier。

当高度改变时如何调用函数?

【问题讨论】:

  • 您是否使用UITextView 输入文本?
  • 是的,我愿意。这是一个自定义的 UITextView 类。
  • 也许这会对你有所帮助stackoverflow.com/questions/4000664/…
  • 我以前见过..但我无法覆盖layoutSubviews(),我不知道如何声明观察者。
  • 你有解决办法吗?

标签: ios swift uitextfield


【解决方案1】:

使用UITextView的委托方法

var textViewHeight: CGFloat = 0

func textViewDidChange(textView: UITextView)
{
    let newTextViewHeight = textView.frame.size.height
    if textViewHeight != newTextViewHeight
    {
        print("---------- Height has changed !!! ----------")
    }
    textViewHeight = newTextViewHeight
}

【讨论】:

  • 这里我使用了这个技术但是它会导致一个问题。事实上,我的 textView 的高度行为是由另一个类控制的,并且这个类在 textViewDidChange 之后调用。然后,对于一个变化,高度变化但为时已晚,无法被 textViewDidChange 捕捉到。
  • @Bram'in 如果是这样,您可以深入自定义类并找到所有更改结束的地方。如果是 github,您可以 fork 存储库,甚至可以使用 didChangeHeight 功能提出拉取请求。
【解决方案2】:

您可以使用 KVO。如果您从视图控制器执行此操作,您可以在 viewDidLoad 中添加观察。例如:

    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField = UITextField(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))

        self.textField.addObserver(self, forKeyPath: "frame", options: .New, context: nil)
    }

然后回复:

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "frame" && object === self.textField
        {
            print(self.textField.frame)
        }
    }

然后当你的视图控制器被取消时移除观察:

deinit {
    self.textField.removeObserver(self, forKeyPath: "frame")
}

【讨论】:

  • 感谢您的回答。我已经尝试了您的解决方案,但仍然无法正常工作。观察者注意到任何东西。我进行了一些研究,我发现观察者的声明非常复杂。这个解决方案似乎是最好的,但应该修改。明天我会看看这个。
【解决方案3】:
extension MyThing: UITextViewDelegate {
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        guard let oldText = textView.text else {
            return true
        }
        let newText = (textView.text as NSString).replacingCharacters(in: range, with: text)

        let size = CGSize(width: textView.bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let font = textView.font!

        let oldTextRect = newText.boundingRect(with: size,
                                               options: .usesLineFragmentOrigin,
                                               attributes: [.font : font],
                                               context: nil)
        let newTextRect = oldText.boundingRect(with: size,
                                               options: .usesLineFragmentOrigin,
                                               attributes: [.font : font],
                                               context: nil)
        if oldTextRect != newTextRect {
            print("Text height changed")
        } else {
            print("Text height didnt change :(")
        }
        return true
    }
}

【讨论】:

    猜你喜欢
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 2013-10-03
    • 2012-01-21
    • 1970-01-01
    相关资源
    最近更新 更多