123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- //
- // XYFloatingDragView.m
- // Starbuds
- //
- // Created by 翟玉磊 on 2020/6/29.
- // Copyright © 2020 翟玉磊. All rights reserved.
- //
- #import "XYFloatingDragView.h"
- @interface XYFloatingDragView ()
- /// 悬浮按钮的拖拽范围 不设置则默认父view的bounds
- @property (nonatomic, assign) CGRect cagingArea;
- /// 停留样式 默认 无吸附边界
- @property (nonatomic, assign) XYFloatingDragAutomaticStyle remainStyle;
- /// 内容类型 默认语音
- @property (nonatomic, assign) XYFloatingDragType floatingDataType;
- @end
- @implementation XYFloatingDragView
- #pragma mark - Public
- // 根据类型创建悬浮窗 会默认好初始值
- + (instancetype)floatingDragViewWithFloatingDragType:(XYFloatingDragType)type {
- XYFloatingDragView *floatingDragView = nil;
- switch (type) {
- case XYFloatingDragTypeVoiceChatRoom:
- {
- CGRect cagingArea = CGRectMake(0, NAVGATION_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - NAVGATION_HEIGHT - TABBAR_HEIGHT);
- floatingDragView = [[XYFloatingDragView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - 162.0f, cagingArea.size.height - 48.0f, 162.0f, 48.0f)];
- floatingDragView.floatingDataType = type;
- floatingDragView.cagingArea = cagingArea;
- floatingDragView.remainStyle = XYFloatingDragAutomaticStyleMargin;
-
- // 语音view
- XYFloatingDragVoiceView *voiceView = [[XYFloatingDragVoiceView alloc] initWithFrame:floatingDragView.bounds];
- [floatingDragView addSubview:voiceView];
- floatingDragView.voiceView = voiceView;
- [voiceView setCloseFloatingDragBlock:^{
- if (floatingDragView.delegate && [floatingDragView.delegate respondsToSelector:@selector(closeFloatingDragWindow)]) {
- [floatingDragView.delegate closeFloatingDragWindow];
- }
- [floatingDragView dismissAnimation:YES];
- }];
- }
- break;
-
- default:
- break;
- }
- return floatingDragView;
- }
- /// 显示view
- - (void)showAnimation:(BOOL)animation {
- if (!self.superview) {
- // 没有父view则进行添加
- [ApplicationDelegate.tabbarVC.view addSubview:self];
- }
- // 把悬浮窗移到最上层
- [ApplicationDelegate.tabbarVC.view bringSubviewToFront:self];
- if (animation) {
- [UIView animateWithDuration:.3 animations:^{
- self.alpha = 1;
- } completion:^(BOOL finished) {
-
- }];
- }
- }
- /// 隐藏view且销毁view
- - (void)dismissAnimation:(BOOL)animation {
- if (animation) {
- [UIView animateWithDuration:.3 animations:^{
- self.alpha = 0;
- } completion:^(BOOL finished) {
- [self clear];
- }];
- }else {
- [self clear];
- }
- }
- /// 设置view信息
- - (void)setupViewDataWithModel:(id)model {
- switch (self.floatingDataType) {
- case XYFloatingDragTypeVoiceChatRoom:
- if (self.voiceView) {
- [self.voiceView setupViewDataWithModel:model];
- }
- break;
-
- default:
- break;
- }
- }
- /// 销毁view
- - (void)clear {
- switch (self.floatingDataType) {
- case XYFloatingDragTypeVoiceChatRoom:
- if (self.voiceView) {
- [self.voiceView clear];
- [self.voiceView removeFromSuperview];
- }
- break;
-
- default:
- break;
- }
- }
- #pragma mark - Action
- // 拖动手势处理
- - (void)handlePan:(UIPanGestureRecognizer *)sender {
- if(sender.state == UIGestureRecognizerStateChanged){
- {
- CGPoint translation = [sender translationInView:[self superview]];
- CGFloat newXOrigin = CGRectGetMinX(self.frame) + translation.x;
- CGFloat newYOrigin = CGRectGetMinY(self.frame) + translation.y;
- CGRect cagingArea = self.cagingArea;
- CGFloat cagingAreaOriginX = CGRectGetMinX(cagingArea);
- CGFloat cagingAreaOriginY = CGRectGetMinY(cagingArea);
- CGFloat cagingAreaRightSide = cagingAreaOriginX + CGRectGetWidth(cagingArea);
- CGFloat cagingAreaBottomSide = cagingAreaOriginY + CGRectGetHeight(cagingArea);
- if (!CGRectEqualToRect(cagingArea, CGRectZero)) {
- if (newXOrigin <= cagingAreaOriginX ||
- newXOrigin + CGRectGetWidth(self.frame) >= cagingAreaRightSide) {
- newXOrigin = CGRectGetMinX(self.frame);
- }
- if(newYOrigin <= cagingAreaOriginY ||
- newYOrigin + CGRectGetHeight(self.frame) >= cagingAreaBottomSide) {
- newYOrigin = CGRectGetMinY(self.frame);
- }
- }
- self.frame = CGRectMake(newXOrigin,
- newYOrigin,
- CGRectGetWidth(self.frame),
- CGRectGetHeight(self.frame));
- [sender setTranslation:(CGPoint){0, 0} inView:[self superview]];
-
- }
-
- }else if (sender.state == UIGestureRecognizerStateEnded){
-
- CGSize dragBtnSize = self.frame.size;
- CGFloat dragBtn_Y = CGRectGetMinY(self.frame);
- CGFloat dragBtn_X = 0;
- CGFloat duration = 0.7;//默认时间
- //计算出按钮距离边界的差 用作动画时间的计算
- CGFloat difference = 1.0;
- switch (_remainStyle) {
- case XYFloatingDragAutomaticStyleNone:
- return;
- case XYFloatingDragAutomaticStyleMargin:
- {
- if (self.center.x >= self.cagingArea.size.width / 2.0) {
- //右
- dragBtn_X = self.cagingArea.size.width - dragBtnSize.width;
- difference = (self.cagingArea.size.width - CGRectGetMaxX(self.frame)) / self.cagingArea.size.width;
- }else{
- //左
- dragBtn_X = 0;
- difference = CGRectGetMidX(self.frame) / self.cagingArea.size.width;
- }
- }
- break;
- case XYFloatingDragAutomaticStyleMarginLeft:
- dragBtn_X = 0;
- difference = CGRectGetMidX(self.frame) / self.cagingArea.size.width;
- break;
- case XYFloatingDragAutomaticStyleMarginRight:
-
- dragBtn_X = self.cagingArea.size.width - dragBtnSize.width;
- difference = (self.cagingArea.size.width - CGRectGetMaxX(self.frame)) / self.cagingArea.size.width;
- break;
- default:
- break;
- }
- //距离越近。动画时间就越短
- duration = duration * difference;
- [UIView animateWithDuration:duration animations:^{
- self.frame = CGRectMake(dragBtn_X, dragBtn_Y, dragBtnSize.width, dragBtnSize.height);
- }];
- }
- }
- // 处理 点击事件
- - (void)handleTap:(UITapGestureRecognizer *)sender {
- if (self.delegate && [self.delegate respondsToSelector:@selector(openFloatingDragWindow)]) {
- [self.delegate openFloatingDragWindow];
- }
- }
- #pragma mark - 初始化
- - (instancetype)initWithFrame:(CGRect)frame {
-
- if (self = [super initWithFrame:frame]) {
-
- [self _setup];
- [self _setupSubViews];
- [self _makeSubViewsConstraint];
- }
- return self;
- }
- #pragma mark - 配置属性
- - (void)_setup {
-
- // 添加手势
- UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
- [self addGestureRecognizer:pan];
-
- UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
- [self addGestureRecognizer:tap];
- }
- #pragma mark - 设置子控件
- - (void)_setupSubViews {
-
- }
- #pragma mark - 布局子控件
- - (void)_makeSubViewsConstraint {
-
- // 设置边框和阴影
- [self addViewShadowWithShadowColor:ColorFromHexStringWithAlpha(@"#FF4D79", 0.5f) shadowOffset:CGSizeMake(0, 4) shadowOpacity:1 shadowRadius:10.0f cornerRadius:self.f_heigh/2];
- }
- #pragma mark - Getter/Setter
- - (CGRect)cagingArea {
- if (_cagingArea.size.width == 0 || _cagingArea.size.height == 0) {
- // 可拖动范围如果宽高有一项为空则默认父控制器的bounds
- if (self.superview) {
- _cagingArea = self.superview.bounds;
- }
- }
- return _cagingArea;
- }
- @end
|