6、悬浮窗的封装

因为之前做游戏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


3249841-b4702615b8a7d618.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容