仿照苹果自带的吸附按钮


哈哈好久没有写简书了,抽点空闲时间写一个简单的Demo

上个星期的版本迭代,产品经理提出一个需求,就是页面上要有一个悬浮按钮。就和苹果系统自带的小白色按钮一样。还带吸附的效果,我觉得直接放在window 的上不就ok ,然后然后等我做完以后说只需要三个主页面有这个效果。尼玛这下我就要改呀改,想想appdelegate不是单利吗,直接给他一个button 的属性,不就可以了设置下隐藏的效果,然后自己测试的时候,乱七八糟的小问题,之后觉得这方案太垃圾了,还要判断好多的隐藏和显示,而且后台的接口还不是在配置文件中的而是在第一个主界面里面给定的接口。。最后无奈之下写一个单利,什么连七八糟的问题都解决了。。小白一个,代码分享给大家。。有问题多多指点。。求大神轻喷。。《代码还需要优化》

废话就不多说了直接上效果图,这是我公司项目中加的
这个只是为了符合产品需求写的,有需要的小伙伴可以自己修改修改放在window上或者view 上都有方法
#######效果

6月-26-2017 13-44-28.gif

最好真机测试比较好,因为模拟器移动的时候会触发点击的事件
########代码

CBBDraggableButton.h

@protocol CBBDragButtonDelegate <NSObject>

- (void)cbb_DraggableButtonClicked:(UIButton *)button;

@end
@interface CBBDraggableButton : UIButton
+(instancetype)sharedInstance;

/** 点击 */
@property (nonatomic,copy) void (^clickBlock) (CBBDraggableButton *clickButton) ;
/** 拖拽 */
@property (nonatomic,copy) void (^draggbleBlock) (CBBDraggableButton*draggbleButton) ;

/** 代理 */
@property (nonatomic,weak) id<CBBDragButtonDelegate> dragButtonDelegate;

- (void)showWindow;


@property (nonatomic) BOOL draggable;
@property (nonatomic) BOOL autoDocking;
----

CBBDraggableButton.m
#import "CBBDraggableButton.h"

@interface CBBDraggableButton ()
{
    CGPoint _beginLocation;
    UILongPressGestureRecognizer *_longPressGestureRecognizer;
}

@end

@implementation CBBDraggableButton

@synthesize draggable = _draggable;
@synthesize autoDocking = _autoDocking;
@synthesize clickBlock = _clickBlock;

######CBBDraggableButton.m
/** 单利 */
+ (instancetype)sharedInstance
{
    static CBBDraggableButton *manager;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       
        manager = [[self alloc]init];
    });
    return manager;
}


- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setUpSubViews];
    }
    return self;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setUpSubViews];
    }
    return self;
}

- (instancetype)initAtView:(id)view WithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [view addSubview:self];
        [self setUpSubViews];
    }
    return self;
}
- (instancetype)initInKeyWindowWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self performSelector:@selector(addToKeyWindow) withObject:nil afterDelay:0.1];
        self.hidden = YES;
        [self setUpSubViews];
    }
    return self;
}


- (void)setUpSubViews
{
     [self.layer setMasksToBounds:YES];
    _autoDocking = YES;
    _draggable = NO;
}

- (void)addToKeyWindow
{
    
    [[UIApplication sharedApplication].keyWindow addSubview:self];

}

- (void)setClickBlock:(void (^)(CBBDraggableButton *))clickBlock
{
    _clickBlock = clickBlock;
    
    if (_clickBlock && _draggable) {
        [self addTarget:self action:@selector(buttonTouched) forControlEvents:UIControlEventTouchUpInside];
    }
}

- (void)buttonTouched {
    [self performSelector:@selector(executeButtonTouchedBlock) withObject:nil afterDelay:0];
}

- (void)executeButtonTouchedBlock {
    
    _clickBlock(self);
    
}

#pragma mark  ------ touth 代理 ------
/** 开始 */
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    
    [super touchesBegan:touches withEvent:event];
    /** 获取 开始位置 */
    _beginLocation = [[touches anyObject] locationInView:self];
}


/** 移动 */
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInView:self];
    
    float offsetX = currentLocation.x - _beginLocation.x;
    float offsetY = currentLocation.y - _beginLocation.y;
    self.center = CGPointMake(self.center.x + offsetX, self.center.y + offsetY);
 
    CGRect superviewFrame = self.superview.frame;
    CGRect frame = self.frame;
    CGFloat leftLimitX = frame.size.width / 2;
    CGFloat rightLimitX = superviewFrame.size.width - leftLimitX;
    CGFloat topLimitY = frame.size.height / 2;
    CGFloat bottomLimitY = superviewFrame.size.height - topLimitY - 49 ;
    if (self.center.x > rightLimitX) {
        self.center = CGPointMake(rightLimitX, self.center.y);
    }else if (self.center.x <= leftLimitX) {
        self.center = CGPointMake(leftLimitX, self.center.y);
    }
    if (self.center.y > bottomLimitY) {
        self.center = CGPointMake(self.center.x, bottomLimitY );
    }else if (self.center.y <= topLimitY){
        self.center = CGPointMake(self.center.x, topLimitY);
    }
    
    
}

/** 结束 */
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded: touches withEvent: event];
    UITouch *touch = [touches anyObject];
    CGPoint currentLocation = [touch locationInView:self];
    
    /** 获取偏移 */
    float offsetX = currentLocation.x - _beginLocation.x;
    float offsetY = currentLocation.y - _beginLocation.y;
    
    NSLog(@"----%f-----%f",offsetY,offsetY);
    if (pow(offsetX,2) + pow(offsetY,2) <0.1) {
        /** 判断 如果拖拽  间距 < 0.1  进行点击 */
        _draggable = NO;
        [self executeButtonTouchedBlock];
        return;
    }
    
    
    CGRect superviewFrame = self.superview.frame;
    CGRect frame = self.frame;
    CGFloat middleX = superviewFrame.size.width / 2;
    if (self.center.x >= middleX) {
        [UIView animateWithDuration:0.2f animations:^{
            self.center = CGPointMake(superviewFrame.size.width - frame.size.width / 2, self.center.y);
            
        } completion:^(BOOL finished) {
            
        }];
    } else {
        [UIView animateWithDuration:0.4 animations:^{
            self.center = CGPointMake(frame.size.width / 2, self.center.y);
            
        } completion:^(BOOL finished) {
            
        }];
    }
    
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
}







/** 删除 */
+ (void)removeAllFromView:(id)superView {
    for (id view in [superView subviews]) {
        if ([view isKindOfClass:[CBBDraggableButton class]]) {
            [view removeFromSuperview];
        }
    }
}
/** 显示 隐藏 */
- (void)showWindow
{
    self.hidden = NO;
}
- (void)dissMissWindow;
{
    self.hidden = YES;
}
初始化
  CBBDraggableButton *draggableButton = [CBBDraggableButton sharedInstance];
    draggableButton.frame = CGRectMake( [UIScreen mainScreen].bounds.size.width - 90, [UIScreen mainScreen].bounds.size.height - 49 - 15 - 75, 75, 75) ;
    [draggableButton setAutoDocking:YES];
    draggableButton.hidden = YES;
    [self.view addSubview:draggableButton];
    
    draggableButton.backgroundColor = [UIColor redColor];
    draggableButton.layer.cornerRadius = 75/2;
    draggableButton.clipsToBounds = YES;
    [[CBBDraggableButton sharedInstance ] showWindow];
    [CBBDraggableButton sharedInstance].clickBlock = ^(CBBDraggableButton *clickBlock) {
       
        UIAlertController*alertController = [[UIAlertController alloc] init];
        
        UIAlertAction*alertAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
            
        }];
        
        [alertController addAction:alertAction];
        
        [alertController addAction:({
            
            UIAlertAction*action = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction *  action) {
                
            }];
            
            action;
            
        })];
        
        [alertController addAction:({
            
            UIAlertAction*action = [UIAlertAction actionWithTitle:@"从相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction *  action) {
                
                //UIAlertActionStyleDestructive字体是红色的  
                
                
                
            }];  
            
            action;  
            
        })];  
        
          [self presentViewController:alertController animated:YES completion:nil];  
    };

2017年06月26日 未完待续。。 有什么问题可以提出意见。。基本上就是所有代码了,需要源码留下邮箱。。后续上传Git

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,139评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,103评论 4 62
  • 1-Supportive of money is a symbol of success are people w...
    Tao爱葡萄柚阅读 214评论 0 0
  • 昨天吃撑了,很不舒服。今天决定尝试轻断食一天,早上喝了一杯豆浆。一直到晚上六点真的就是超级饿啊,特别是我一直在看书...
    亲爱的吴小仙阅读 230评论 1 0