| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
jopen
10年前发布

iOS 支付宝首页拖放按钮效果实现

效果图:

1.实现原理

将所有按钮放在viewcontroller的_buttonArray集合中,同时赋值给按钮中

增加长按手势的响应

当手势坐标进入其他按钮的frame时,调整集合中按钮位置;

当长按手势开始,放大按钮; 结束时还原按钮

2.附源码及注释[按钮调控已实现动画]

@interface UIDragButton : UIButton {      CGPoint _prePoint;                  // 移动过程中的上一个点      BOOL    _isPress;                   // 是否按下:实现过程未用到      CGPoint _framePoint;                // 未放大情况下frame的左上角坐标      CGRect  _frameRect;                 // 未放大情况下frame值  }    @property (nonatomic, assign) NSMutableArray *buttonArray;  // button集合  @property (nonatomic, assign) NSInteger      indexOfArray;  // 当前按钮在集合中的下标    // 移动动画,实现过程未用到,暂不能用  - (void)moveTo:(CGRect)rect Animation:(BOOL)flag;  // 初始化一些样式,即长按手势  - (void)initStyle;    @end

.m

@implementation UIDragButton    /*   * 样式初始化,即手势初始化   **/  - (void)initStyle {      self.backgroundColor = [UIColor whiteColor];      self.layer.borderWidth = 0.3;      self.layer.borderColor = [UIColor grayColor].CGColor;      UILongPressGestureRecognizer * longPressGr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressToDo:)];      longPressGr.minimumPressDuration = 1.0;      [self addGestureRecognizer:longPressGr];  }    #pragma mark - 按钮尺寸更改  // 放大  - (void)changeBig {      self.transform = CGAffineTransformScale(self.transform,1.25,1.25);      self.backgroundColor = [UIColor colorWithHexString:@"E0E0E0" alpha:1];  }    // 还原  - (void)changeBack {      self.transform = CGAffineTransformScale(self.transform,0.8,0.8);      // 按钮放大还原后会有偏移,所以要设置回正常位置,80和100是按钮尺寸      self.frame = CGRectMake(_framePoint.x, _framePoint.y, 80, 100);  }    #pragma mark - 手势管理  /*   * 手势响应,并判断状态   **/  - (void)longPressToDo:(UILongPressGestureRecognizer *)press {      if ([press state] == UIGestureRecognizerStateBegan) {          [self beganTouch:press];          [self changeBig]; // 放大      }      else if ([press state] == UIGestureRecognizerStateChanged) {          [self movedTouch:press];      }      else if ([press state] == UIGestureRecognizerStateEnded){          [self endedTouch:press];      }  }    /*   * 手势长按开始   **/  - (void)beganTouch:(UILongPressGestureRecognizer *)press {      _prePoint = [press locationInView:self];      _frameRect = self.frame;      _framePoint = self.frame.origin;      // 该通知用于告诉controller点击的是第几个按钮,用于将该按钮放在最上层      [[NSNotificationCenter defaultCenter] postNotificationName:@"buttonChanged" object:[NSNumber numberWithInteger:_indexOfArray]];  }    /*   * 手势长按结束   **/  - (void)endedTouch:(UILongPressGestureRecognizer *)press {      _prePoint = [press locationInView:self];      [self changeBack];      self.backgroundColor = [UIColor whiteColor];  }    /*   * 长按过程中移动   **/  - (void)movedTouch:(UILongPressGestureRecognizer *)press {      CGPoint now = [press locationInView:self];            NSInteger x = now.x - _prePoint.x;      NSInteger y = now.y - _prePoint.y;      self.frame = CGRectMake(self.frame.origin.x+x, self.frame.origin.y+y, self.frame.size.width, self.frame.size.height);      [self placeIsChanged:CGPointMake(self.frame.origin.x + _prePoint.x, self.frame.origin.y + _prePoint.y)];  }    #pragma mark - 按钮调整  /*   * 判断当前按钮位置是否变化,并进行调整   **/  - (void)placeIsChanged:(CGPoint)point {      for (NSInteger i = 0; i < [self.buttonArray count]; i++) {          if ([self pointIn:point rect:((UIButton *)[_buttonArray objectAtIndex:i]).frame]              && _indexOfArray != i) {              [self adjustButtons:i];          }      }  }    /*   * 判断点是否在rect内   **/  - (BOOL)pointIn:(CGPoint)point rect:(CGRect)rect {      if (point.x > rect.origin.x && point.y > rect.origin.y && point.x < rect.origin.x+rect.size.width && point.y < rect.origin.y+rect.size.height) {          return YES;      }      return NO;  }    /*   * 调整按钮位置   **/  - (void)adjustButtons:(NSInteger)index {      CGRect rect = ((UIButton *)[_buttonArray objectAtIndex:index]).frame;            __block NSInteger i = 0;      __block NSInteger num = index;      // 将靠前的按钮移动到靠后的位置      if (_indexOfArray < index) {          // 将上一个按钮的位置赋值给当前按钮          [UIView animateWithDuration:0.5 animations:^{              for (i = num; i > _indexOfArray+1; i--) {                  ((UIDragButton *)[_buttonArray objectAtIndex:i]).frame = ((UIDragButton *)[_buttonArray objectAtIndex:i-1]).frame;              }              ((UIDragButton *)[_buttonArray objectAtIndex:i]).frame = _frameRect;          }];          _frameRect = rect;                    // 调整顺序  保证数组中按钮的frame按顺序排列          for (i = _indexOfArray; i < index; i++) {              [_buttonArray exchangeObjectAtIndex:i withObjectAtIndex:i+1];              ((UIDragButton *)[_buttonArray objectAtIndex:i]).indexOfArray = i;          }          ((UIDragButton *)[_buttonArray objectAtIndex:index]).indexOfArray = index;      }      else { // 将靠后的按钮移动到前边          // 将上一个按钮的位置赋值给当前按钮          [UIView animateWithDuration:0.5 animations:^{              for (i = num; i < _indexOfArray-1; i++) {                  ((UIDragButton *)[_buttonArray objectAtIndex:i]).frame = ((UIDragButton *)[_buttonArray objectAtIndex:i+1]).frame;              }              ((UIDragButton *)[_buttonArray objectAtIndex:i]).frame = _frameRect;          }];          _frameRect = rect;                    // 调整顺序  保证数组中按钮的frame按顺序排列          for (i = _indexOfArray; i > index; i--) {              [_buttonArray exchangeObjectAtIndex:i withObjectAtIndex:i-1];              ((UIDragButton *)[_buttonArray objectAtIndex:i]).indexOfArray = i;          }          ((UIDragButton *)[_buttonArray objectAtIndex:index]).indexOfArray = index;      }      _framePoint = _frameRect.origin;  }    #pragma mark - 按钮移动动画  - (void)moveTo:(CGRect)rect Animation:(BOOL)flag {      if (flag) {          // 计算偏移并移动          float x = rect.origin.x - self.frame.origin.x;          float y = rect.origin.y - self.frame.origin.y;          [self.layer addAnimation:[self moveX:0.1 X:[NSNumber numberWithFloat:x]] forKey:nil];          [self.layer addAnimation:[self moveY:0.1 Y:[NSNumber numberWithFloat:y]] forKey:nil];      }      else {          self.frame = rect;      }  }    - (CABasicAnimation *)moveX:(float)time X:(NSNumber *)x  // 横向移动  {      CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.x"];      animation.toValue=x;      animation.duration=time;                    // 动画持续时间      animation.removedOnCompletion=NO;      animation.fillMode=kCAFillModeForwards;      return animation;  }    - (CABasicAnimation *)moveY:(float)time Y:(NSNumber *)y  // 纵向移动  {      CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.y"];      animation.toValue=y;      animation.duration=time;      animation.removedOnCompletion=NO;      animation.fillMode=kCAFillModeForwards;      return animation;  }    @end