实现效果:小窗口拖动,注意是仅当拖动小窗口时候才移动,触摸小窗口外部不移动
hitTest: 方法同样接受一个CGPoint类型参数,而不是BOOL类型,它返回图层本身,或者包含这个坐标点的叶子节点图层。直接获得位于点击事件响应链条最前沿的子图层或自身,不需要一层一层用-conrainsPoint:去判断
如果说小窗口视图没有非常复杂的视图的结构的话,采用以下的方法
触摸事件开始,主要做点击区域判断
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
CALayer *touchedLayer = [self.view.layer hitTest:point];
if(touchedLayer == self.smallView.layer){
self.isMoving = YES;
}
}
拖动过程,计算偏移
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
if(!self.isMoving){
return;
}
UITouch *touch = [touches anyObject];
CGPoint current = [touch locationInView:self.view];
CGPoint previous = [touch previousLocationInView:self.view];
CGPoint center = self.smallView.center;
CGPoint offset = CGPointMake(current.x - previous.x, current.y - previous.y);
self.smallView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
}
拖动结束
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesEnded:touches withEvent:event];
self.isMoving = NO;
}
相对而言的,如果说小窗口有比较复杂的视图结构,比如说有多级子视图,这时候上面的方法久不合适了
原因:-touchesBegan:方法中CALayer *touchedLayer = [self.view.layer hitTest:point];
会直接获取顶层的图层,也就是位于响应链最前沿的视图的图层,所以这时候再进行图层判断if(touchedLayer == self.smallView.layer){
就不合适了!
-containsPoint:
接受一个在本图层坐标系下的CGPoint,如果这个点在图层frame范围内就返回YES
这时候就就应该采用如下的方式
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
//Converts the point from the specified layer’s coordinate system to the receiver’s coordinate system.
point = [self.catEarView.layer convertPoint:point fromLayer:self.view.layer];
if([self.catEarView.layer containsPoint:point]){
self.isMoving = YES;
}
}