(IOS)懸浮按鈕Demo


思路:傳入一個底層的view,將懸浮按鈕(用view實現)和展開的子按鈕列表add在其上,子按鈕列表開始將坐標和懸浮按鈕對應好后先將其隱藏,懸浮按鈕識別到tap手勢后觸發展示子按鈕列表的方法。通過在touchMove中實現子按鈕列表和懸浮按鈕的中心坐標同步更新,實現同時一起拖動,其中限定了懸浮按鈕在手指拿起后的坐標,通過在touchEnd作判斷調整。關鍵點是tap手勢有時會將touchBegan之后的方法砍斷,在調用tap的回調函數后會執行touchCancel方法,所以tap的回調函數中必須帶上touchEnd中的功能,將UI的效果恢復和位置糾正。

 

源碼:

#import "SuspendedButton.h"
#import <QuartzCore/QuartzCore.h>

#define BUTTON_AVAILABLE @"BUTTONAVAILABLE"

@interface SuspendedButton ()
{
    BOOL _isShowingButtonList;
    BOOL _isOnLeft;
    BOOL _isBackUp;
    BOOL _isTest;
    CGPoint _tempCenter;
    CGPoint _originalPosition;
    CGRect _windowSize;
    UIView *_buttonListView;
    UIView *_baseView;
}

@property (nonatomic,retain) UIView *buttonListView;
@property (nonatomic,retain) UIView *baseView;
@end

@implementation SuspendedButton
@synthesize buttonListView = _buttonListView;
@synthesize baseView = _baseView;

static SuspendedButton *_instance = nil;

#pragma mark - 繼承方法
- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        _isShowingButtonList = NO;
        //_isBackUp = NO;
        //self.hidden = YES;
        //_isTest = NO;
        //[self httpRequest];
        
        [[NSNotificationCenter defaultCenter] removeObserver:self name:BUTTON_AVAILABLE object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showButton) name:BUTTON_AVAILABLE object:nil];
    }
    return self;
}

- (void)dealloc
{
    [_buttonListView release];
    [_baseView release];
  
    [[NSNotificationCenterdefaultCenter] removeObserver:self];

    [super dealloc];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //NSLog(@"touchBegan");
    
    _originalPosition = [[touches anyObject] locationInView:self];
    _tempCenter = self.center;
    
    self.backgroundColor = [UIColor blueColor];
    
    CGAffineTransform toBig = CGAffineTransformMakeScale(1.2, 1.2);
    
    [UIView animateWithDuration:0.1 animations:^{
        // Translate bigger
        self.transform = toBig;
        
    } completion:^(BOOL finished)   {}];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    //NSLog(@"touchMove");
    
    CGPoint currentPosition = [[touches anyObject] locationInView:self];
    float detaX = currentPosition.x - _originalPosition.x;
    float detaY = currentPosition.y - _originalPosition.y;
    
    CGPoint targetPositionSelf = self.center;
    CGPoint targetPositionButtonList = _buttonListView.center;
    targetPositionSelf.x += detaX;
    targetPositionSelf.y += detaY;
    targetPositionButtonList.x += detaX;
    targetPositionButtonList.y += detaY;
    
    self.center = targetPositionSelf;
    _buttonListView.center = targetPositionButtonList;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    //NSLog(@"touchCancell");
    
    // 觸發touchBegan后,tap手勢被識別后會將touchMove和touchEnd的事件截取掉觸發自身手勢回調,然后運行touchCancell。touchBegan中設置的按鈕狀態在touchEnd和按鈕觸發方法兩者中分別設置還原。
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    //NSLog(@"touchEnd");
    
    CGAffineTransform toNormal = CGAffineTransformTranslate(CGAffineTransformIdentity, 1/1.2, 1/1.2);
    CGPoint newPosition = [self correctPosition:self.frame.origin];
    
    [UIView animateWithDuration:0.1 animations:^{
        
        // Translate normal
        self.transform = toNormal;
        self.backgroundColor = [UIColor greenColor];
        
    } completion:^(BOOL finished) {
        
        [UIView animateWithDuration:0.4 animations:^{
            self.frame = CGRectMake(newPosition.x, newPosition.y, self.bounds.size.width, self.bounds.size.height);
            [self adjustButtonListView];
        }];
        
    }];
}

#pragma mark - 類方法
+ (SuspendedButton *)suspendedButtonWithCGPoint:(CGPoint)pos inView:(UIView *)baseview
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[SuspendedButton alloc] initWithCGPoint:pos];
        _instance.baseView = baseview;
        [_instance constructUI];
        [baseview addSubview:_instance];
        [_instance release];
    });
    
    return _instance;
}

+ (void)deleteSuspendedButton
{
    [_instance removeFromSuperview];
}

#pragma mark - 輔助方法
- (id)initWithCGPoint:(CGPoint)pos
{
    _windowSize = [SDKFunctionLib rectFromWinSize_CurrentWinSize]; //封裝了獲取屏幕Size的方法
    
    CGPoint newPosition = [self correctPosition:pos];
    
    return [self initWithFrame:CGRectMake(newPosition.x, newPosition.y, 50, 50)];
}

- (CGPoint)correctPosition:(CGPoint)pos
{
    CGPoint newPosition;
    
    if ((pos.x + 50 > _windowSize.size.width) || (pos.x > _windowSize.size.width/2-25)) {
        newPosition.x = _windowSize.size.width - 50;
        _isOnLeft = NO;
    } else {
        newPosition.x = 0;
        _isOnLeft = YES;
    }
    
    (pos.y + 50 > _windowSize.size.height)?(newPosition.y = _windowSize.size.height - 50):((pos.y < 0)?newPosition.y = 0:(newPosition.y = pos.y));
    
    return newPosition;
}

- (void)constructUI
{
    self.backgroundColor = [UIColor greenColor];
    self.alpha = 0.6;
    self.layer.cornerRadius = 10;
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tiggerButtonList)];
    tap.numberOfTapsRequired = 1;
    tap.numberOfTouchesRequired = 1;
    [self addGestureRecognizer:tap];
    [tap release];
    
    NSUInteger numOfButton = 4;
    self.buttonListView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, numOfButton*40, 40)] autorelease];
    _buttonListView.backgroundColor = [UIColor blueColor];
    _buttonListView.alpha = 0;
    _buttonListView.layer.cornerRadius = 10;
    
    [self createButtonByNumber:numOfButton withSize:CGSizeMake(40, 40) inView:(UIView *)_buttonListView];
    _buttonListView.hidden = YES;
    [_baseView addSubview:_buttonListView];
}

- (void)createButtonByNumber:(NSUInteger)number withSize:(CGSize)size inView:(UIView *)view
{
    //子按鈕的UI效果自定義
    for (NSUInteger i = 0; i < number; i++)
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button addTarget:self action:@selector(optionsButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        button.tag = i + 2000;
        button.frame = CGRectMake(0 + i*size.width, 0, size.width, size.height);
        button.tintColor = [UIColor redColor];
        [view addSubview:button];
    }
}

- (void)adjustButtonListView
{
    if (_isOnLeft) {
        _buttonListView.frame = CGRectMake(50, self.center.y - 20, _buttonListView.bounds.size.width, _buttonListView.bounds.size.height);
    } else {
        _buttonListView.frame = CGRectMake((_windowSize.size.width - 50 - _buttonListView.bounds.size.width), self.center.y - 20, _buttonListView.bounds.size.width, _buttonListView.bounds.size.height);
    }
}

#pragma mark - 按鈕回調
- (void)tiggerButtonList
{
    //NSLog(@"tiggerTap");
    
    _isShowingButtonList = !_isShowingButtonList;
    
    CGAffineTransform toNormal = CGAffineTransformTranslate(CGAffineTransformIdentity, 1/1.2, 1/1.2);
    [UIView animateWithDuration:0.1 animations:^{
        // Translate normal
        self.transform = toNormal;
        self.backgroundColor = [UIColor greenColor];
    } completion:^(BOOL finished) {
        
        [UIView animateWithDuration:0.1 animations:^{
            self.center = _tempCenter;
            [self adjustButtonListView];
        } completion:^(BOOL finished) {
            
            [UIView animateWithDuration:0.5 animations:^{
                _buttonListView.hidden = !_isShowingButtonList;
                _isShowingButtonList ? (_buttonListView.alpha = 0.6) : (_buttonListView.alpha = 0);
            }];
        }];
    }];
}

- (void)optionsButtonPressed:(UIButton *)button
{
    //NSLog(@"buttonNumberPressed:%d",button.tag);
    
    switch (button.tag) {
        case 0:
            break;
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
        default:
            break;
    }
}

#pragma mark - 網絡請求方法
-(void)httpRequest
{
    NSMutableString *tempURL = [[NSMutableString alloc] init];
    NSString *requesURL = URL_SUSPENDED_BUTTON;
    //自定義需求的目標url
   
    [UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
    //封裝了網絡請求的方法
    [HttpRequest getRequestWithURLString:tempURL isSynchronism:NO andFinishHandle:^(NSData *data, NSError *error) {
        
        if (error)
        {
            
            if (!_isBackUp)
            {
                _isBackUp = YES;
                [self httpRequest];
            }
            else
            {
                _isBackUp = NO;
                [UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
            }
        } else {
            _isBackUp = NO;
            NSDictionary *requestDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:Nil];
            NSString *code = [requestDic objectForKey:@"code"];
            
            if ([code isEqualToString:@"1000"]) {
                [[NSNotificationCenter defaultCenter] postNotificationName:BUTTON_AVAILABLE object:nil];
            }
        }
    }];
    [tempURL release];
}

#pragma mark - 網絡請求回調
- (void)showButton
{
    self.hidden = NO;
}

@end
View Code

 

效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM