仿微信悬浮窗,可直接协议加入悬浮窗或者直接调用方法注册,可自定义转场动画
Github地址(WMZFloatView)
演示
用法1 在Appdelegate中注册 传入对应控制器的className
//只带控制器的className
[[WMZFloatManage shareInstance] registerControllers:@[@"ViewController"]];
//带其他配置(标题和图片)
[[WMZFloatManage shareInstance] registerControllers:@[@{@"controllerName":@"ViewController",@"icon":@"float_circle_full"}]];
用法2 实现协议 WMZFloatViewProtocol 即可
//可选实现协议的方法 传入标题和图片
- (NSDictionary *)floatViewConfig{
return @{@"name":@"实际显示在悬浮窗的标题",@"icon":@"float_image"};
}
用法3 改变转场动画 传入继承UIViewControllerAnimatedTransitioning协议的类即可
//自定义push动画
@property(nonatomic,strong)NSObject *pushAnimal;
//自定义pop动画
@property(nonatomic,strong)NSObject *popAnimal;
依赖
无任何依赖
讲解
来说下我的实现思路
1 浮动框
1 实现一个悬浮窗的单例管理器,继承UINavigationControllerDelegate,UIGestureRecognizerDelegate
2 监听侧滑手势是否开始
//监听侧滑手势开始
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]&&self.nowVC.navigationController.viewControllers.count>1) {
//判断是否实现了协议 加入可悬浮
BOOL isConform = [self.nowVC conformsToProtocol:@protocol(WMZFloatViewProtocol)];
NSString *tmpName = NSStringFromClass([self.nowVC class]);
if (isConform) {
if ([self.reginerVCName indexOfObject:tmpName] == NSNotFound) {
NSMutableDictionary *mdic = [NSMutableDictionary new];
[mdic setObject:tmpName forKey:@"controllerName"];
//实现了配置的协议 加入配置
if ([self.nowVC respondsToSelector:@selector(floatViewConfig)]) {
NSDictionary *dic = [self.nowVC performSelector:@selector(floatViewConfig)];
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[mdic setObject:obj forKey:key];
}];
}
[self.reginerVCName addObject:tmpName];
[self.reginerVCConfig setObject:mdic forKey:tmpName];
}
}
//达到可悬浮的条件
if ([self.reginerVCName indexOfObject:tmpName] != NSNotFound && [self.cacheKey indexOfObject:[self getKey:self.nowVC]] == NSNotFound){
self.edge = (UIScreenEdgePanGestureRecognizer *) gestureRecognizer;
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[faloatWindow addSubview:self.floatView];
self.normalRect = self.floatView.frame;
CGRect rect = self.floatView.frame;
rect.origin.x = FloatWidth;
rect.origin.y = FloatHeight;
self.floatView.frame = rect;
self.floatView.full = (self.cacheKey.count>=5);
}
}
return YES;
}
3 监听侧滑触碰点是否碰到悬浮窗
//圆心到点的距离>?半径
+ (BOOL)point:(CGPoint)point inCircleRect:(CGRect)rect {
CGFloat radius = rect.size.height;
CGPoint center = CGPointMake(rect.origin.x + radius, rect.origin.y + radius);
double dx = fabs(point.x - center.x);
double dy = fabs(point.y - center.y);
double dis = hypot(dx, dy);
return dis <= radius;
}
2 悬浮窗图案 1~5
NSDictionary *dic = @{
@(1):@[
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize*0.15, panSize*0.15, width, height)],
@"cornerRadius":@(height/2)
}
],
@(2):@[
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize*scale-panSize/6, panSize*scale , width, height)],
@"pathAngle":@(M_PI_4)
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize*scale-panSize/6+panSize*scale-4, panSize*scale , width, height)],
@"cornerRadius":@(height/2)
}
],
@(3):@[
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale/2, panSize*scale, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI_2+M_PI_4)
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize*scale,panSize*scale + height -4, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI*2),
@"fromValue":@(M_PI)
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize*scale +width -2, panSize*scale + height -4, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(-M_PI_2-M_PI_4)
},
],
@(4):@[
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale/2, panSize*scale , width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI_2+M_PI_4)
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale,panSize*scale + height-5, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI_4),
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale + width +2, panSize*scale + height-7, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(-M_PI_2-M_PI_4)
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale/2+2, panSize*scale + height*2 -7-5, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(-M_PI_4)
},
],
@(5):@[
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale/2, panSize*scale, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI_2+M_PI_4),
@"controlPoint":[NSValue valueWithCGPoint:CGPointMake(width/3, height/3)]
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale/2-panSize*scale/2,panSize*scale + height -5, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(M_PI_4+M_PI_4/2),
@"controlPoint":[NSValue valueWithCGPoint:CGPointMake(width/3, height/3)]
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2 +3 ,panSize*scale + height -5 -2, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(-M_PI_2-M_PI_4),
@"controlPoint":[NSValue valueWithCGPoint:CGPointMake(width/3, height/3)]
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale+3, panSize*scale + height*2 -5 -2 -1, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(2*M_PI),
@"fromValue":@(M_PI),
@"controlPoint":[NSValue valueWithCGPoint:CGPointMake(width/3, height/3)]
},
@{
@"frame":[NSValue valueWithCGRect:CGRectMake(panSize/2-panSize*scale+3 + width -2, panSize*scale + height*2 -5 -2 -1-1, width, height)],
@"pathAngle":@(M_PI_4),
@"toValue":@(-M_PI_2/3-M_PI_4),
@"controlPoint":[NSValue valueWithCGPoint:CGPointMake(width/3, height/3)]
},
],
};
NSArray *config = dic[@(data.count)];
//创建图片
NSMutableArray *imageArr = [NSMutableArray new];
for (NSString *key in data) {
UIImageView *image = [UIImageView new];
NSDictionary *detailDic = [cache objectForKey:key];
if (detailDic[@"icon"]) {
image.image = [UIImage imageNamed:detailDic[@"icon"]];
}else{
image.backgroundColor = FloatShowColor;
}
image.layer.masksToBounds = YES;
[imageArr addObject:image];
[self addSubview:image];
[self bringSubviewToFront:image];
}
CFTimeInterval time = ((data.count == normalCount)?0.01:1);
//图片绘制图案和动画
for (int i = 0; i
Github地址(WMZFloatView)
有什么问题欢迎给我提issue,欢迎star