2022-09-02

iOS: 悬浮窗+hit...


Github代码在此

VC里有一个customview,是悬浮窗,并且要扩大响应范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class ViewController: UIViewController {

let customView = CustomView()
let resetButton: UIButton = {
let btn = UIButton()
btn.titleLabel?.text = "reset"
btn.titleLabel?.textColor = .systemBlue
btn.backgroundColor = .gray
return btn
}()

override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(customView)
customView.parentView = self.view
self.view.addSubview(resetButton)
resetButton.addTarget(self, action: #selector(didTapReset), for: .touchUpInside)
}

@objc func didTapReset() {
customView.center = self.view.center
}

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
customView.frame = CGRect(x: self.view.frame.width / 2 - 50, y: self.view.frame.height / 2 - 50, width: 100, height: 100)
resetButton.frame = CGRect(x: self.view.frame.width / 2 - 50, y: 80, width: 100, height: 44)
}
}

hitTest是判断点击的point和当前view是否有contains关系,返回可选性的UIView
point同理,范围Bool,是否有点击,事件传递就是通过这俩方法判断当先View是否可以为响应者

1
2
open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
open func point(inside point: CGPoint, with event: UIEvent?) -> Bool

然后我们重写下hittest方法就可以了
要实现悬浮,可以加手势识别器
为了计算下一个偏移坐标,touchBegin里存一下CGPoint作为上一次的坐标;当然你要在touchEnd计算也行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class CustomView: UIView {

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

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

private var _parentView: UIView!

var parentView: UIView {
set {
_parentView = newValue
}
get {
return _parentView
}
}

var lastTranslation = CGPoint(x: 0, y: 0)

func config() {
backgroundColor = .orange
isUserInteractionEnabled = true
let gesture = UIPanGestureRecognizer(target: self, action: #selector(didDrag(gesture:)))
addGestureRecognizer(gesture)
}

@objc func didDrag(gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: parentView)
center = CGPoint(x: lastTranslation.x + translation.x, y: lastTranslation.y + translation.y)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
lastTranslation = self.center
}

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// print(point)
// return super.hitTest(point, with: event)
let frame = self.bounds.insetBy(dx: -50, dy: -50)
return frame.contains(point) ? self : nil
}

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return super.point(inside: point, with: event)
}
}