需求:
项目中要求做一个类似于iOS中AssistiveTouch的悬浮按钮,用于给用户展示广告。不同于AssistiveTouch的地方是我们的TouchView不会悬浮在上面或者下面,只会悬浮在左边或者右边。
实现:
新建一个TouchView,通过传入的maxEdge参数设置TouchView的移动范围。
@property(nonatomic, assign)UIEdgeInsets maxEdge;//设置TouchView可以移动的最大范围
- (instancetype)initWithMaxEdge:(UIEdgeInsets)maxEdge;
初始化方法中保存maxEdge
- (instancetype)initWithMaxEdge:(UIEdgeInsets)maxEdge {
self = [super init];
if (self) {
self.maxEdge = maxEdge;
}
return self;
}
触摸时开始移动时TouchView跟随手指位置移动
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//求偏移量 = 手指当前点的X - 手指上一个点的X
CGPoint currentPoint = [touch locationInView:self];
CGPoint prePoint = [touch previousLocationInView:self];
CGFloat offSetX = currentPoint.x - prePoint.x;
CGFloat offSetY = currentPoint.y - prePoint.y;
//平移
self.transform = CGAffineTransformTranslate(self.transform, offSetX, offSetY);
}
当手指离开屏幕时,判断TouchView需要偏移的位置
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//处理当前UIView越界的情况
CGFloat halfWidth = self.bounds.size.width/2.0;
CGFloat maxWidth = self.maxEdge.right - self.maxEdge.left;
CGPoint centerPoint = [self convertPoint:self.center toView:self.superview];
CGFloat centerX = centerPoint.x;
CGFloat centerY = centerPoint.y;
CGFloat minY = centerPoint.y - halfWidth;
CGFloat maxY = centerPoint.y + halfWidth;
CGFloat newCenterX = 0;
CGFloat newCenterY = 0;
CGFloat offSetY = 0;
CGFloat offSetX = 0;
if (minY < self.maxEdge.top) {//上下偏移
newCenterY = self.maxEdge.top + halfWidth;
offSetY = newCenterY - centerY;
} else if(maxY > self.maxEdge.bottom) {
newCenterY = self.maxEdge.bottom - halfWidth;
offSetY = newCenterY - centerY;
}
if(centerX > maxWidth/2.0) {//左右偏移
newCenterX = maxWidth - halfWidth + self.maxEdge.left;
}else {
newCenterX = halfWidth + self.maxEdge.left;
}
offSetX = newCenterX - centerX;
[UIView animateWithDuration:0.3 animations:^{
self.transform = CGAffineTransformTranslate(self.transform, offSetX, offSetY);
}];
}
使用:
设置TouchView并添加到当前的view上
UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
bgView.center = self.view.center;
bgView.layer.borderWidth = 1;
bgView.layer.borderColor = UIColor.redColor.CGColor;
[self.view addSubview:bgView];
TouchView *touchView = [[TouchView alloc] initWithMaxEdge:UIEdgeInsetsMake(CGRectGetMinY(bgView.frame), CGRectGetMinX(bgView.frame), CGRectGetMaxY(bgView.frame), CGRectGetMaxX(bgView.frame))];
touchView.frame = CGRectMake(0, 0, 60, 60);
touchView.transform = CGAffineTransformTranslate(touchView.transform, 100, 300);//初始位置
touchView.tag = 1001;
touchView.backgroundColor = UIColor.orangeColor;
touchView.layer.cornerRadius = touchView.frame.size.width/2;
touchView.layer.masksToBounds = YES;
[self.view addSubview:touchView];
效果:
下面红框是限制的范围,TouchView超出范围会反弹回来,如果移动到中间位置,会自动偏左或者偏右。