因为之前做游戏SDK的开发,主要是集成登录、注册、充值以及最重要的悬浮窗的制作;封装成一个类,方便自己以后使用😄;
我的Demo地址:https://github.com/hongbaoshi/LZWFloatWindow
参考地址:https://github.com/search?utf8=%E2%9C%93&q=DYYFloatWindow
创建引入:
- (void)viewDidLoad {
[super viewDidLoad];
//防止与主window冲突,延迟执行;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
[self creatFloatWindow];
});
}
-(void)creatFloatWindow
{
_change_floatWindow = [[LZWFloatWindow alloc] initWithFrame:CGRectMake(100, 100, 50,50) andWithMainImageName:@"z" andWithTitleDic:@{@"ddd":@"用户中心",@"eee":@"退出登录",@"fff":@"客服中心"} andWithStartBtnTag:100 andWithAnimationColor:[UIColor purpleColor]];
_change_floatWindow.backBlock = ^(NSInteger tag){
NSLog(@"点击第%ld个按钮",tag);
};
}
具体实现:
#import <UIKit/UIKit.h>
typedef void(^MyBlock)(NSInteger tag);
@interface LZWFloatWindow : UIWindow
@property(nonatomic,strong)MyBlock backBlock;
-(id)initWithFrame:(CGRect)frame andWithMainImageName:(NSString *)bgName andWithTitleDic:(NSDictionary *)titleDic andWithStartBtnTag:(int)startTag andWithAnimationColor:(UIColor *)color;
@end
#import "LZWFloatWindow.h"
#import <CoreMotion/CoreMotion.h>
#define LZW_WIDTH [[UIApplication sharedApplication].windows firstObject].bounds.size.width
#define WZFlashInnerCircleInitialRaius 20
@interface LZWFloatWindow()
@property(nonatomic,strong)UIButton *mainBtn;
@property(nonatomic,assign)BOOL isShowDetail;//是否展开悬浮窗,默认不展开;
@property(nonatomic,assign)CGRect startFrame;//悬浮窗初始显示位置
@property(nonatomic,assign)NSInteger btnWidth;//各个按钮的宽;
@property(nonatomic,strong)UIView *contentView;//点击btn展示的详情界面;
@property(nonatomic,strong)NSDictionary *titleDic;//保存详情页面标题的字典;
@property(nonatomic,assign)int btnTag;//详情每个按钮的tag值;
@property(nonatomic,strong)UIPanGestureRecognizer *movePan;//悬浮窗移动手势
@property(nonatomic,strong)CMMotionManager *motionManager;//添加重力感应器
@property(assign, nonatomic) NSTimeInterval gyroUpdateInterval;
@property(nonatomic,assign)double accZ; //z轴方向的偏移量;
@property(nonatomic,assign)BOOL isHide;
@property(nonatomic,strong)CAAnimationGroup *animationGroup;
@property(nonatomic,strong)CAShapeLayer *circleShape;
@property(nonatomic,strong)UIColor *animationColor;
@end
@implementation LZWFloatWindow
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
-(id)initWithFrame:(CGRect)frame andWithMainImageName:(NSString *)bgName andWithTitleDic:(NSDictionary *)titleDic andWithStartBtnTag:(int)startTag andWithAnimationColor:(UIColor *)color;
{
if (self = [super initWithFrame:frame])
{
//初始化属性
_startFrame = frame;
_btnWidth = frame.size.width;
_titleDic = titleDic;
_btnTag = startTag;
_animationColor = color;
_isShowDetail = NO;
_isHide = NO;
//UI
self.backgroundColor = [UIColor clearColor];
self.rootViewController = [UIViewController new];
self.rootViewController.view.backgroundColor = [UIColor blackColor];
self.windowLevel = UIWindowLevelAlert + 1;
self.alpha = 0.8;
self.layer.cornerRadius = 26;
self.layer.masksToBounds = YES;
self.layer.borderColor = [UIColor colorWithRed:0.94 green:0.61 blue:0.30 alpha:1.00].CGColor;
self.layer.borderWidth = 1;
[self makeKeyAndVisible];
_mainBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_mainBtn.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
[_mainBtn setImage:[UIImage imageNamed:bgName] forState:UIControlStateNormal];
[_mainBtn addTarget:self action:@selector(mainBtnClick) forControlEvents:UIControlEventTouchUpInside];
if (_animationColor) {
//5---添加长按雷达效果;
// [_mainBtn addTarget:self action:@selector(mainBtnTouchDown) forControlEvents:UIControlEventTouchDown];
}
[self.rootViewController.view addSubview:_mainBtn];
_contentView = [UIView new];
_contentView.backgroundColor = [UIColor blackColor];
_contentView.frame = CGRectMake(_btnWidth, 0, _titleDic.count*(_btnWidth+5), _btnWidth);
[self.rootViewController.view addSubview:_contentView];
//1---给contentView添加按钮
[self setContentViewBtns];
//2---添加手势
_movePan = [[UIPanGestureRecognizer alloc] init];
[_movePan addTarget:self action:@selector(locationChange:)];
_movePan.delaysTouchesBegan = YES;
[self addGestureRecognizer:_movePan];
//3---设备旋转的时候收回详情界面
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
//4---添加翻转隐藏悬浮窗;
//开启陀螺仪感应器;
//重力感应的设置
[self accelerotionDataMethod];
}
return self;
}
-(void)mainBtnClick
{
_isShowDetail = !_isShowDetail;
if (self.center.x == LZW_WIDTH+5)
{
_mainBtn.frame = CGRectMake(0, 0, 50, 50);
[_mainBtn setImage:[UIImage imageNamed:@"z"] forState:UIControlStateNormal];
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _btnWidth+(5+_btnWidth)*_titleDic.count, _btnWidth);
self.center = CGPointMake(LZW_WIDTH-(_btnWidth+(5+_btnWidth)*_titleDic.count)/2, self.center.y);
return;
}
if (_isShowDetail)
{
[UIView animateWithDuration:0.5 animations:^{
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _btnWidth+(5+_btnWidth)*_titleDic.count, _btnWidth);
}];
}else
{
[UIView animateWithDuration:0.5 animations:^{
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _btnWidth, _btnWidth);
}];
}
}
-(void)setContentViewBtns
{
int i = 0;
for (NSString *key in _titleDic)
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(i*_btnWidth, 0, _btnWidth, _btnWidth);
[btn setTitle:_titleDic[key] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:key] forState:UIControlStateNormal];
btn.tag = _btnTag;
// 则默认image在左,title在右
// 改成image在上,title在下
btn.titleEdgeInsets = UIEdgeInsetsMake(self.btnWidth/2 , -[UIImage imageNamed:key].size.width, 0.0, 0.0);
btn.imageEdgeInsets = UIEdgeInsetsMake(2.0, 8.0, 16.0, -
btn.titleLabel.bounds.size.width + 8);
btn.titleLabel.font = [UIFont systemFontOfSize: self.btnWidth/5];
[btn addTarget:self action:@selector(itemsClick:) forControlEvents:UIControlEventTouchUpInside];
[_contentView addSubview:btn];
i++;
_btnTag++;
}
}
-(void)locationChange:(UIPanGestureRecognizer *)p
{
//获取停止的位置坐标
CGPoint panPoint = [p locationInView:[[UIApplication sharedApplication].windows firstObject]];
if(p.state == UIGestureRecognizerStateBegan)
{
}
else if (p.state == UIGestureRecognizerStateEnded)
{
CGPoint velocity = [p velocityInView:[[UIApplication sharedApplication].windows firstObject]];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
CGFloat slideMult = magnitude / 300;
float slideFactor = 0.1 * slideMult;
// NSLog(@"%f %f %f %f %f",panPoint.x,panPoint.y,velocity.x,velocity.y,slideMult);
CGPoint finalPoint = CGPointMake(p.view.center.x + (velocity.x * slideFactor),
p.view.center.y + (velocity.y * slideFactor));
if (!_isShowDetail)
{
//限制下最小、最大坐标,防止停靠在角落;
finalPoint.x = MIN(MAX(finalPoint.x, 25), [[UIApplication sharedApplication].windows firstObject].bounds.size.width-25);
finalPoint.y = MIN(MAX(finalPoint.y, 70), [[UIApplication sharedApplication].windows firstObject].bounds.size.height-70);
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
p.view.center = finalPoint;
if (self.center.x == 25)
{
[self performSelector:@selector(yinCanLeftFloat) withObject:nil afterDelay:0.3];
}else if(self.center.x == [[UIApplication sharedApplication].windows firstObject].bounds.size.width-25)
{
[self performSelector:@selector(yinCanRightFloat) withObject:nil afterDelay:0.3];
}
} completion:nil];
}else
{
//限制下最小、最大坐标,防止停靠在角落;
finalPoint.x = MIN(MAX(finalPoint.x, (_btnWidth+(5+_btnWidth)*_titleDic.count)/2), [[UIApplication sharedApplication].windows firstObject].bounds.size.width-(_btnWidth+(5+_btnWidth)*_titleDic.count)/2);
finalPoint.y = MIN(MAX(finalPoint.y, 70), [[UIApplication sharedApplication].windows firstObject].bounds.size.height-70);
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
p.view.center = finalPoint;
} completion:nil];
}
}
else if(p.state == UIGestureRecognizerStateChanged)
{
self.center = CGPointMake(panPoint.x, panPoint.y);
if (self.center.x >25)
{
_mainBtn.userInteractionEnabled = YES;
_mainBtn.frame = CGRectMake(0, 0, 50, 50);
[_mainBtn setImage:[UIImage imageNamed:@"z"] forState:UIControlStateNormal];
}else if(self.center.x < [[UIApplication sharedApplication].windows firstObject].bounds.size.width-25)
{
_mainBtn.userInteractionEnabled = YES;
_mainBtn.frame = CGRectMake(0, 0, 50, 50);
[_mainBtn setImage:[UIImage imageNamed:@"z"] forState:UIControlStateNormal];
}
}
}
-(void)yinCanLeftFloat
{
[UIView animateWithDuration:0.6 animations:^{
self.center = CGPointMake(-50, self.center.y);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
self.center = CGPointMake(-5, self.center.y);
_mainBtn.frame = CGRectMake(30, 0, 20, 50);
[_mainBtn setImage:[UIImage imageNamed:@"left_float.png"] forState:UIControlStateNormal];
}];
}];
}
-(void)yinCanRightFloat
{
[UIView animateWithDuration:0.6 animations:^{
self.center = CGPointMake([[UIApplication sharedApplication].windows firstObject].bounds.size.width+50, self.center.y);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
self.center = CGPointMake([[UIApplication sharedApplication].windows firstObject].bounds.size.width+5, self.center.y);
_mainBtn.frame = CGRectMake(0, 0, 20, 50);
[_mainBtn setImage:[UIImage imageNamed:@"right_float.png"] forState:UIControlStateNormal];
}];
}];
}
-(void)orientChange:(NSNotification *)notification
{
self.frame = CGRectMake(self.startFrame.origin.x, self.startFrame.origin.y, _btnWidth, _btnWidth);
}
-(void)accelerotionDataMethod
{
self.motionManager = [[CMMotionManager alloc] init];
self.gyroUpdateInterval = 0.2;
self.motionManager.accelerometerUpdateInterval = self.gyroUpdateInterval;
__weak LZWFloatWindow *weakself = self;
[self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[weakself outputAccelertionData:accelerometerData.acceleration];
if(error){
NSLog(@"%@", error);
}
}];
[self.motionManager startGyroUpdates];
}
-(void)outputAccelertionData:(CMAcceleration)acceleration
{
self.accZ = acceleration.z;
if (self.accZ >= 0.2)
{
[self.motionManager stopAccelerometerUpdates];
_isHide = !_isHide;
self.hidden = _isHide;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(),^{
[self accelerotionDataMethod];
});
}
}
-(void)itemsClick:(id)sender
{
UIButton *btn = (UIButton *)sender;
self.backBlock(btn.tag);
}
@end