设计能长按并有动画效果且能触发事件的高级view
效果图:
源码:
LongTapAnimationView.h 与 LongTapAnimationView.m
// // LongTapAnimationView.h // YouXianMingClock // // Created by YouXianMing on 14-10-13. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <UIKit/UIKit.h> @class LongTapAnimationView; @protocol LongTapAnimationViewDelegate <NSObject> /** * 长按百分比 * * @param percent 百分比 * @param view 自身 */ - (void)longPressPercentage:(CGFloat)percent view:(LongTapAnimationView *)view; - (void)longPressCompleteWithView:(LongTapAnimationView *)view; @end @interface LongTapAnimationView : UIView /** * 代理 */ @property (nonatomic, assign) id<LongTapAnimationViewDelegate> delegate; /** * 百分比 */ @property (nonatomic, assign, readonly) CGFloat percent; /** * 缩放比例 */ @property (nonatomic, assign) CGFloat scaleValue; /** * 时候允许按下(默认为YES) */ @property (nonatomic, assign) BOOL canTouch; /** * 长按时间多长时间才能表示已经按下按钮激活事件 */ @property (nonatomic, assign) NSTimeInterval completeDurationAfterLongPress; /** * 激活按钮事件 */ - (void)activateButtonEffect; @end
// // LongTapAnimationView.m // YouXianMingClock // // Created by YouXianMing on 14-10-13. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import "LongTapAnimationView.h" #import "POP.h" @interface LongTapAnimationView ()<POPAnimationDelegate> @property (nonatomic, strong) UIButton *button; @end @implementation LongTapAnimationView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 完整显示按住按钮后的动画效果 _button = [[UIButton alloc] initWithFrame:self.bounds]; [self addSubview:_button]; // 按住按钮后没有松手的动画 [_button addTarget:self action:@selector(scaleToSmall) forControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter]; // 按住按钮松手后的动画 [_button addTarget:self action:@selector(scaleAnimations) forControlEvents:UIControlEventTouchUpInside]; // 按住按钮后拖拽出去的动画 [_button addTarget:self action:@selector(scaleToDefault) forControlEvents:UIControlEventTouchDragExit]; _button.userInteractionEnabled = NO; } return self; } /** * 在设定frame值的时候也设置button的frame值 * * @param frame 当前view的frame值 */ - (void)setFrame:(CGRect)frame { [super setFrame:frame]; _button.bounds = frame; } - (void)scaleToSmall { CGFloat tmpScale = (_scaleValue > 0)? _scaleValue : 0.7f; // 变小尺寸 POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(tmpScale, tmpScale)]; scaleAnimation.delegate = self; // 核心 [self.layer pop_addAnimation:scaleAnimation forKey:nil]; [self performSelector:@selector(performSelectorEvent) withObject:nil afterDelay:(_completeDurationAfterLongPress > 1.5 ? _completeDurationAfterLongPress : 1.5)]; } - (void)scaleToDefault { // 恢复尺寸 POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)]; scaleAnimation.delegate = self; // 核心 [self.layer pop_addAnimation:scaleAnimation forKey:nil]; [NSObject cancelPreviousPerformRequestsWithTarget:self]; } - (void)scaleAnimations { // 恢复尺寸 POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)]; scaleAnimation.delegate = self; // 核心 [self.layer pop_addAnimation:scaleAnimation forKey:nil]; [NSObject cancelPreviousPerformRequestsWithTarget:self]; } - (void)performSelectorEvent { if (_delegate) { [_delegate longPressCompleteWithView:self]; } } /** * POP动画代理 * * @param anim 执行动画的那个对象 */ - (void)pop_animationDidApply:(POPAnimation *)anim { NSValue *toValue = (NSValue *)[anim valueForKeyPath:@"currentValue"]; CGSize size = [toValue CGSizeValue]; CGFloat tmpScale = (_scaleValue > 0)? _scaleValue : 0.7f; _percent = (size.height - calculateConstant(0, 1, 1, tmpScale))/calculateSlope(0, 1, 1, tmpScale); if (_delegate) { [_delegate longPressPercentage:_percent view:self]; } } CGFloat calculateSlope(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2) { return (y2 - y1) / (x2 - x1); } CGFloat calculateConstant(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2) { return (y1*(x2 - x1) - x1*(y2 - y1)) / (x2 - x1); } - (void)addSubview:(UIView *)view { [super addSubview:view]; /** * 如果继承了这个类,则子类不会执行以下方法 */ if ([self class] == [LongTapAnimationView class]) { [self bringSubviewToFront:_button]; } } - (void)activateButtonEffect { [self bringSubviewToFront:_button]; } #pragma mark - 重写setter,getter方法 @synthesize canTouch = _canTouch; - (void)setCanTouch:(BOOL)canTouch { _canTouch = canTouch; _button.userInteractionEnabled = canTouch; } - (BOOL)canTouch { return _canTouch; } @end
笔者设计这个类可谓用心良苦,Facebook是业界良心啊!以下是使用细节: