ios - 当 z-index 设置为非零值时,未在视图上调用触摸代理
问题描述
我正在实现聊天气泡功能。我希望聊天气泡位于所有视图控制器之上,并且不受屏幕转换的影响。所以我决定将它作为子视图添加到UIWindow
到目前为止它看起来像
这很好用,但是如果我呈现视图控制器而不是推送,那么聊天头会落后于呈现的视图控制器。为了避免它,我设置了聊天头层的 ZIndex 属性
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let window = UIApplication.shared.keyWindow {
window.addSubview(chatHead)
chatHead.layer.zPosition = 1
}
}
但是现在虽然聊天头出现在呈现的视图控制器的顶部,它的触摸代表像touchesBegan
, ,当聊天头在呈现的 ViewController 之上时touchesMoved
,什么都不会被调用touchesEnded
添加聊天头的代码(这个问题可能不需要很多代码,但如果有人想尝试就发布它)
class ChatHeadView: UIView {
let headerWidth: CGFloat = 80.0
let headerHeight: CGFloat = 80.0
let sideInset: CGFloat = 10.0
let bottomInset: CGFloat = 10.0
var cancellationWindowShown = false
lazy var cancellationContainerRect: CGRect = {
var rect = self.cancelChatView.convert(self.cancelChatView.frame, to: nil)
rect.origin.x = rect.origin.x + 30
rect.size.height = 100
return rect
}()
lazy var cancellationThreshold: CGFloat = {
return self.keywindow.frame.maxY - (self.keywindow.frame.maxY / 3)
}()
lazy var keywindow: UIWindow = {
let window = UIApplication.shared.keyWindow ?? UIWindow()
return window
}()
lazy var cancelChatView: CancelChatView = {
if let cancelView = Bundle.main.loadNibNamed("CancelChatView", owner: nil, options: [:])?.first as? CancelChatView {
return cancelView
}
fatalError("Couldnt load")
}()
init() {
super.init(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
self.layer.masksToBounds = true
self.layer.cornerRadius = 40
self.layer.backgroundColor = UIColor.red.cgColor
self.cancelChatView.frame = CGRect(x: 0, y: self.keywindow.frame.maxY - 140, width: self.keywindow.frame.width, height: 140)
self.cancelChatView.layer.opacity = 0.0
self.keywindow.addSubview(self.cancelChatView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
debugPrint("Touch started")
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self.keywindow)
if location.y >= cancellationThreshold {
self.showCancellationWindow()
}
else {
removeCancellationView()
debugPrint("Removing Cancellation window")
}
self.center = location
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self.keywindow)
self.center = location
self.snap(to: location)
self.removeCancellationView()
}
}
private func snap(to point: CGPoint) {
var finalPoint:CGPoint = self.frame.origin
if self.cancellationContainerRect.intersects(self.convert(self.frame, to: nil)) {
self.removeFromSuperview()
}
else {
if finalPoint.x <= self.keywindow.center.x {
finalPoint.x = self.keywindow.frame.minX + sideInset
}
else if finalPoint.x > self.keywindow.center.x {
finalPoint.x = self.keywindow.frame.maxX - (sideInset + self.headerWidth)
}
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.6, options: .curveEaseInOut, animations: {
self.frame.origin = finalPoint
}, completion: nil)
}
}
private func showCancellationWindow() {
if cancellationWindowShown == false {
let animation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
animation.fromValue = 0.0
animation.toValue = 0.6
animation.duration = 0.1
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
self.cancelChatView.layer.add(animation, forKey: "reveal")
self.cancellationWindowShown = true
}
}
private func removeCancellationView() {
if cancellationWindowShown == true {
let animation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
animation.toValue = 0.0
animation.duration = 0.1
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
self.cancelChatView.layer.add(animation, forKey: "hide")
cancellationWindowShown = false
}
}
}
问题 Gif(触摸不起作用):
正如马特询问我如何呈现 ViewController 的详细信息,添加故事板 segue 配置的屏幕截图
解决方案
推荐阅读
- python - 请求过多的链接会破坏 Selenium 的网站吗
- python - 关于 Graph2GO main.py
- javascript - Tableau JS 扩展:window.open()
- postgresql - 如何为PostgreSQL创建一个恢复时不失败的只读备份用户
- usb - HID 报告描述符中的 ReportID
- kubernetes - 在 Kubernetes 容器中找不到从 ConfigMap 挂载的脚本
- python - 如何制作一个在按下时显示另一个 InlineKeyboard 的 InlinekeyboardButton
- php - jquery 数据表不过滤来自 ssp 格式字段的行。例如
- python - 如何对 Python zeep 进行单元测试
- python - tkinter 的条目和按钮的不同宽度