• 设计能长按并有动画效果且能触发事件的高级view


    设计能长按并有动画效果且能触发事件的高级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是业界良心啊!以下是使用细节:

  • 相关阅读:
    跨域请求
    django数据模型中关于on_delete, db_constraint的使用
    rest-framework之分页器
    跨域请求
    相对路径与绝对路径
    html常用标签
    ES6中字符串扩展
    javascript中startswith和endsWidth 与 es6中的 startswith 和 endsWidth
    Angular6 组件树结构优化
    docker限制容器内存使用上限
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4025160.html
Copyright © 2020-2023  润新知