I add two view on screen. One is the blue view, other is orange view.
And I use CADisplayLink
to change orange view 's frame according to the blueView.layer.presentation.frame
As expected, the orange view should cover the blue view completely, but we can see a gap and we can see a little part of blue view during keyboard animation. Here is demo code:
class SecondViewController: UIViewController {
let textField = UITextField()
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.textField.resignFirstResponder()
}
lazy var displayLink = CADisplayLink(target: self, selector: #selector(self.onDisplayLink))
@objc private func onDisplayLink () {
self.realBox.frame = CGRect(x: self.realBox.frame.origin.x, y: self.blueBox.layer.presentation()!.frame.origin.y, width: self.view.bounds.width, height: 100)
}
let blueBox = UIView()
let realBox = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
textField.frame = .init(x: 100, y: 100, width: 100, height: 100)
textField.backgroundColor = .red
self.view.addSubview(textField)
realBox.backgroundColor = .orange
blueBox.backgroundColor = .blue
blueBox.frame = .init(x: 0, y: self.view.bounds.height - 100, width: self.view.bounds.width, height: 100)
self.view.addSubview(blueBox)
self.view.addSubview(realBox)
realBox.frame = .init(x: 0, y:self.view.bounds.height - 100 , width: self.view.bounds.width, height: 100)
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: .main) { noti in
let userInfo = noti.userInfo!
let endFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
let isOpen = endFrame.intersects(self.view.bounds)
self.blueBox.frame = .init(x: 0, y: isOpen ? self.view.bounds.height - 100 - endFrame.height : self.view.bounds.height - 100, width: self.view.bounds.width, height: 100)
}
if #available(iOS 15.0, *) {
self.displayLink.preferredFrameRateRange = .init(minimum: 60, maximum: 120, preferred: 120)
} else {
self.displayLink.preferredFramesPerSecond = 120
}
self.displayLink.add(to: .main, forMode: .common)
}
}
So how to get an accurate value of the layer currently displayed on screen?
Here is the video: https://github.com/luckysmg/daily_images/blob/main/RPReplay_Final1661168764.mov?raw=true