美文网首页
iOS 贴边浮窗

iOS 贴边浮窗

作者: 刘明洋 | 来源:发表于2019-11-08 14:47 被阅读0次

    可以拖动并且可以指定贴左还是贴右边, 直接上代码。

    LMYHomeServicesButton.h

    //
    //  LMYHomeServicesButton.h
    //  LMY
    //
    //  Created by 刘明洋 on 2018/1/28.
    //  Copyright © 2018年 lmy. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    typedef NS_ENUM(NSInteger, LMYAssistiveTouchType)
    {
        LMYAssistiveTypeNone = 0,   //自动识别贴边
        LMYAssistiveTypeNearLeft,   //拖动停止之后,自动向左贴边
        LMYAssistiveTypeNearRight,  //拖动停止之后,自动向右贴边
    };
    
    @interface LMYHomeServicesButton : UIButton
    
    
    typedef void (^floatBtnClick)(UIButton *sender);
    
    //任何模式都显示floatBtn
    + (void)show;
    
    //移除
    + (void)hidden;
    
    //按钮点击事件
    @property (nonatomic, copy)floatBtnClick btnClick;
    
    @end
    

    LMYHomeServicesButton.m

    //
    //  LMYHomeServicesButton.m
    //  LMY
    //
    //  Created by 刘明洋 on 2018/1/28.
    //  Copyright © 2018年 lmy. All rights reserved.
    //
    
    #import "LMYHomeServicesButton.h"
    
    @interface LMYHomeServicesButton()
    
    @property (nonatomic, assign, getter=isBuildShowDate) BOOL buildShowDate;
    
    //Build号
    @property(nonatomic, copy)NSString *buildStr;
    
    @property(nonatomic, assign)BOOL isShow;
    @end
    
    @implementation LMYHomeServicesButton{
        
        LMYAssistiveTouchType  _type;
        //拖动按钮的起始坐标点
        CGPoint _touchPoint;
        
        //起始按钮的x,y值
        CGFloat _touchBtnX;
        CGFloat _touchBtnY;
    
    }
    
    static LMYHomeServicesButton *_floatBtn;
    
    static CGFloat floatBtnW = 120;
    static CGFloat floatBtnH = 49;
    
    #define screenW  [UIScreen mainScreen].bounds.size.width
    #define screenH  [UIScreen mainScreen].bounds.size.height
    
    //系统默认build
    #define MNFloatBtnSystemBuild [[[NSBundle mainBundle]infoDictionary]valueForKey:@"CFBundleVersion"]
    //系统默认version
    #define MNFloatBtnSystemVersion [[[NSBundle mainBundle]infoDictionary]valueForKey:@"CFBundleShortVersionString"]
    
    #pragma mark - lazy
    - (NSString *)buildStr{
        if (!_buildStr) {
            _buildStr = MNFloatBtnSystemBuild;
        }
        return _buildStr;
    }
    
    #pragma mark - private Method
    + (void)show{
        [self showWithType:LMYAssistiveTypeNone];
    }
    
    + (void)hidden{
        [_floatBtn removeFromSuperview];
    }
    
    + (void)showWithType:(LMYAssistiveTouchType)type{
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            LMYHomeServicesButton * floatBtn = [[self alloc]initWithType:LMYAssistiveTypeNearRight frame:CGRectMake(10, 300, floatBtnW, floatBtnH)];
            [[UIApplication sharedApplication].keyWindow addSubview:floatBtn];
            //让floatBtn在最上层(即便以后还有keywindow add subView,也会在 floatBtn下)
            [[UIApplication sharedApplication].keyWindow bringSubviewToFront:floatBtn];
        });
    }
    
    
    - (instancetype)initWithType:(LMYAssistiveTouchType)type
                           frame:(CGRect)frame{
        NSString *title = [NSString stringWithFormat:@"Ver:%@ \nBuild:%@\n查看更多",MNFloatBtnSystemVersion, self.buildStr];
    
    
        if (self = [super initWithFrame:frame]) {
            _type = type;
    
            //UIbutton的换行显示
            self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
            self.backgroundColor = [UIColor redColor];
            self.titleLabel.font = [UIFont systemFontOfSize:13];
            [self setTitle:title forState:UIControlStateNormal];
    
            [self addTarget:self action:@selector(p_clickBtn:) forControlEvents:UIControlEventTouchUpInside];
    
        }
        return self;
    }
    
    
    - (void)p_clickBtn:(UIButton *)sender{
        
        if (_btnClick) {
            _btnClick(sender);
        }
    }
    
    
    #pragma mark - button move
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        
        [super touchesBegan:touches withEvent:event];
        
        //按钮刚按下的时候,获取此时的起始坐标
        UITouch *touch = [touches anyObject];
        _touchPoint = [touch locationInView:self];
        
        _touchBtnX = self.frame.origin.x;
        _touchBtnY = self.frame.origin.y;
    }
    
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        UITouch *touch = [touches anyObject];
        CGPoint currentPosition = [touch locationInView:self];
        
        //偏移量(当前坐标 - 起始坐标 = 偏移量)
        CGFloat offsetX = currentPosition.x - _touchPoint.x;
        CGFloat offsetY = currentPosition.y - _touchPoint.y;
        
        //移动后的按钮中心坐标
        CGFloat centerX = self.center.x + offsetX;
        CGFloat centerY = self.center.y + offsetY;
        self.center = CGPointMake(centerX, centerY);
        
        //父试图的宽高
        CGFloat superViewWidth = self.superview.frame.size.width;
        CGFloat superViewHeight = self.superview.frame.size.height;
        CGFloat btnX = self.frame.origin.x;
        CGFloat btnY = self.frame.origin.y;
        CGFloat btnW = self.frame.size.width;
        CGFloat btnH = self.frame.size.height;
        
        //x轴左右极限坐标
        if (btnX > superViewWidth){
            //按钮右侧越界
            CGFloat centerX = superViewWidth - btnW/2;
            self.center = CGPointMake(centerX, centerY);
        }else if (btnX < 0){
            //按钮左侧越界
            CGFloat centerX = btnW * 0.5;
            self.center = CGPointMake(centerX, centerY);
        }
        
        //默认都是有导航条的,有导航条的,父试图高度就要被导航条占据,固高度不够
        CGFloat defaultNaviHeight = 64;
        CGFloat judgeSuperViewHeight = superViewHeight - defaultNaviHeight;
        
        //y轴上下极限坐标
        if (btnY <= 0){
            //按钮顶部越界
            centerY = btnH * 0.7;
            self.center = CGPointMake(centerX, centerY);
        }
        else if (btnY > judgeSuperViewHeight){
            //按钮底部越界
            CGFloat y = superViewHeight - btnH * 0.5;
            self.center = CGPointMake(btnX, y);
        }
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        
        CGFloat btnWidth = self.frame.size.width;
        CGFloat btnHeight = self.frame.size.height;
        CGFloat btnY = self.frame.origin.y;
        CGFloat btnX = self.frame.origin.x;
        
        CGFloat minDistance = 2;
        
        //结束move的时候,计算移动的距离是>最低要求,如果没有,就调用按钮点击事件
        BOOL isOverX = fabs(btnX - _touchBtnX) > minDistance;
        BOOL isOverY = fabs(btnY - _touchBtnY) > minDistance;
        
        if (isOverX || isOverY) {
            //超过移动范围就不响应点击 - 只做移动操作
            [self touchesCancelled:touches withEvent:event];
        }else{
            [super touchesEnded:touches withEvent:event];
        }
        
        //按钮靠近右侧
        switch (_type) {
                
            case LMYAssistiveTypeNone:{
                
                //自动识别贴边
                if (self.center.x >= self.superview.frame.size.width/2) {
                    
                    [UIView animateWithDuration:0.5 animations:^{
                        //按钮靠右自动吸边
                        CGFloat btnX = self.superview.frame.size.width - btnWidth;
                        self.frame = CGRectMake(btnX, btnY, btnWidth, btnHeight);
                    }];
                }else{
                    
                    [UIView animateWithDuration:0.5 animations:^{
                        //按钮靠左吸边
                        CGFloat btnX = 0;
                        self.frame = CGRectMake(btnX, btnY, btnWidth, btnHeight);
                    }];
                }
                break;
            }
            case LMYAssistiveTypeNearLeft:{
                [UIView animateWithDuration:0.5 animations:^{
                    //按钮靠左吸边
                    CGFloat btnX = 0;
                    self.frame = CGRectMake(btnX, btnY, btnWidth, btnHeight);
                }];
                break;
            }
            case LMYAssistiveTypeNearRight:{
                [UIView animateWithDuration:0.5 animations:^{
                    //按钮靠右自动吸边
                    CGFloat btnX = self.superview.frame.size.width - btnWidth;
                    self.frame = CGRectMake(btnX, btnY, btnWidth, btnHeight);
                }];
            }
        }
    }
    
    
    @end
    
    

    使用

    //
    //  ViewController.m
    //  lmy
    //
    //  Created by lmy on 2019/10/27.
    //  Copyright © 2019 lmy. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "LMYHomeServicesButton.h"
    
    
    @interface ViewController ()
    @property(nonatomic,strong)UIImage * objImage;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
    }
    
    - (void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];
    
        [LMYHomeServicesButton show];
    }
    @end
    

    相关文章

      网友评论

          本文标题:iOS 贴边浮窗

          本文链接:https://www.haomeiwen.com/subject/qoribctx.html