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? {
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) } }
|