[iOS]iOS开发浮动按钮实现(可拖拽)

项目链接

话不多说,直接上连接:https://github.com/pizazzsy/SYFloatingView.git

效果图

Pasted Graphic 2_副本.png

使用方法

SYFloatingView * floatView = [[SYFloatingView alloc]initWithFrame:CGRectMake(0, 50, 70, 70) delegate:self];
    [self.view addSubview:floatView];
    [floatView floatingViewRoundedRect];

-(void)floatingViewDidClickView{
    NSLog(@"点击了浮动按钮");
}

代码实现

#import 

NS_ASSUME_NONNULL_BEGIN
@protocol SYFloatingViewDelegate 

/// 点击悬浮窗回调
- (void)floatingViewDidClickView;

@end
@interface SYFloatingView : UIView
@property (nonatomic, weak) id delegate;
- (void)floatingViewRoundedRect;
- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate;
@end

NS_ASSUME_NONNULL_END
#import "SYFloatingView.h"
#import "Masonry.h"

#define Screen_Width        [UIScreen mainScreen].bounds.size.width
#define Screen_Height       [UIScreen mainScreen].bounds.size.height
#define Is_Iphone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define Is_IPhoneX (Screen_Width >=375.0f && Screen_Height >=812.0f && Is_Iphone)
#define StatusBar_Height    (Is_IPhoneX ? (44.0):(20.0))
#define Bottom_SafeHeight   (Is_IPhoneX ? (34.0):(0))


@interface SYFloatingView()

// 记录手势开始地址
@property (nonatomic, assign) CGPoint beganPoint;
// 记录当前试图开始的FrameOrigin
@property (nonatomic, assign) CGPoint beganOrigin;
@property (nonatomic, strong) UIView *bgView;
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *desLabel;

@end
@implementation SYFloatingView
- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate {
    self = [super initWithFrame:frame];
    if (self) {
        self.delegate = delegate;
        [self initSubviews];
        [self activateConstraints];
        [self bindInteraction];
    }
    return self;
}
- (void)initSubviews {
    [self addSubview:self.bgView];
    [self addSubview:self.containerView];
    [self addSubview:self.imageView];
    [self addSubview:self.desLabel];
}
- (void)activateConstraints {
    [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self);
    }];
    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.mas_equalTo(self.bgView);
        make.top.left.mas_equalTo(self.bgView).offset(8);
    }];
    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.containerView).offset(15);
        make.centerX.mas_equalTo(self.containerView);
        make.width.height.mas_equalTo(20);
    }];
    [self.desLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.width.mas_equalTo(self.containerView);
        make.bottom.mas_equalTo(self.containerView).offset(-5);
    }];
}
- (void)bindInteraction {
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    [self addGestureRecognizer:tap];
    [pan requireGestureRecognizerToFail:tap];
    [self addGestureRecognizer:pan];
}
- (void)handleTapGesture:(UITapGestureRecognizer *)tapGesture {
    if (self.delegate && [self.delegate respondsToSelector:@selector(floatingViewDidClickView)]) {
        [self.delegate floatingViewDidClickView];
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture {
    if (!panGesture || !panGesture.view) {
        return;
    }
    
    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:{
            self.beganPoint = [panGesture translationInView:panGesture.view];
            self.beganOrigin = self.frame.origin;
            [self roundedRect:UIRectCornerAllCorners withCornerRatio:15 withView:self.bgView];
        }
            break;
        case UIGestureRecognizerStateChanged: {
            CGPoint point = [panGesture translationInView:panGesture.view];
            CGFloat offsetX = (point.x - _beganPoint.x);
            CGFloat offsetY = (point.y - _beganPoint.y);
            self.frame = CGRectMake(_beganOrigin.x + offsetX, _beganOrigin.y + offsetY, self.frame.size.width, self.frame.size.height);
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded: {
            CGFloat leftDefine = 0;
            CGRect screenrect = self.superview.bounds;
            CGFloat currentCenterX = self.frame.origin.x + self.frame.size.width / 2.0;
            CGFloat finalOriginX = (currentCenterX <= screenrect.size.width / 2.0) ? leftDefine : (screenrect.size.width - self.frame.size.width);
            CGFloat finalOriginY = self.frame.origin.y;
            
            if (self.frame.origin.y <= StatusBar_Height) {
                finalOriginY = StatusBar_Height;
            }
            
            if ((self.frame.origin.y + self.frame.size.height) >= screenrect.size.height) {
                finalOriginY = screenrect.size.height - self.frame.size.height - Bottom_SafeHeight;
            }
            
            [UIView animateWithDuration:0.2 animations:^{
                if (self) {
                    self.frame = CGRectMake(finalOriginX , finalOriginY, self.frame.size.width, self.frame.size.height);
                }
            } completion:^(BOOL finished) {
                [self floatingViewRoundedRect];
            }];
        }
            break;
        default:
            break;
    }
}
- (void)floatingViewRoundedRect {
    UIRectCorner corner = UIRectCornerTopLeft | UIRectCornerBottomLeft;
    if (self.frame.origin.x < Screen_Width / 2.0f) {
        corner = UIRectCornerTopRight | UIRectCornerBottomRight;
    }
    [self roundedRect:corner withCornerRatio:15 withView:self.bgView];
}
- (void)roundedRect:(UIRectCorner)corner withCornerRatio:(CGFloat)cornerRatio withView:(UIView*)changeView{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(15, 15)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = changeView.bounds;
    maskLayer.path = maskPath.CGPath;
    changeView.layer.mask = maskLayer;
}
#pragma mark - Getter And Setter
- (UIView *)bgView {
    if (!_bgView) {
        _bgView = [[UIView alloc] init];
        _bgView.backgroundColor = [UIColor grayColor];
        _bgView.alpha = 0.2;
        _bgView.layer.borderWidth = 1;
        _bgView.layer.borderColor = [UIColor clearColor].CGColor;
        _bgView.layer.masksToBounds = YES;
        _bgView.alpha = 0.2;
    }
    return _bgView;
}

- (UIView *)containerView {
    if (!_containerView) {
        _containerView = [[UIView alloc] init];
        _containerView.backgroundColor = [UIColor clearColor];
        _containerView.layer.cornerRadius = 10.0f;
        _containerView.layer.masksToBounds = YES;
    }
    return _containerView;
}

- (UIImageView *)imageView {
    if (!_imageView) {
        _imageView = [[UIImageView alloc] init];
        [_imageView setImage:[UIImage imageNamed:@"help_me_history"]];
        _imageView.hidden = NO;
    }
    return _imageView;
}

- (UILabel *)desLabel {
    if (!_desLabel) {
        _desLabel = [[UILabel alloc] init];
        [_desLabel setFont:[UIFont systemFontOfSize:12.0f]];
        [_desLabel setTextColor:[UIColor blackColor]];
        _desLabel.textAlignment = NSTextAlignmentCenter;
        _desLabel.hidden = YES;
    }
    return _desLabel;
}
@end

你可能感兴趣的:([iOS]iOS开发浮动按钮实现(可拖拽))