android 仿ios悬浮窗,iOS仿微信悬浮窗

仿微信悬浮窗,可直接协议加入悬浮窗或者直接调用方法注册,可自定义转场动画

演示

myFloat.gif

用法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

UIImageView *image = imageArr[i];

NSDictionary *frameDic = config[i];

image.frame = [frameDic[@"frame"] CGRectValue];

if (frameDic[@"cornerRadius"]) {

image.layer.cornerRadius = [frameDic[@"cornerRadius"] floatValue];

}

if (frameDic[@"pathAngle"]) {

CGPoint point = [frameDic[@"controlPoint"] CGPointValue];

CAShapeLayer *layer = [CAShapeLayer layer];

layer.path = [self getPathWithRadius:image.frame.size.height/2 center:CGPointMake(image.frame.size.width/2, image.frame.size.height/2) angle:[frameDic[@"pathAngle"] doubleValue] controlPoint:point].CGPath;

layer.frame = image.bounds;

if (frameDic[@"toValue"]) {

double toValue = [frameDic[@"toValue"] doubleValue];

double fromValue = [frameDic[@"fromValue"] doubleValue];

[layer addAnimation:[self getAnimationWithValue:toValue fromValue:fromValue duration:time] forKey:nil];

}

image.layer.mask = layer;

}

}

Github地址(WMZFloatView)

有什么问题欢迎给我提issue,欢迎star

你可能感兴趣的:(android,仿ios悬浮窗)