美文网首页
iOS为UIview增加触感反馈动画和震动效果

iOS为UIview增加触感反馈动画和震动效果

作者: 扶兮摇兮 | 来源:发表于2020-04-16 15:38 被阅读0次
    //
    //  UIView+Event.h
    //  testTabBar
    //
    //  Created by vanmr on 2020/3/18.
    //  Copyright © 2020 xdhl. All rights reserved.
    //
    
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface MTAddEventMaker : NSObject
    
    @property(nonatomic, copy) void(^mt_touchBeginBlock)(UIGestureRecognizer *gesture);
    
    @property (nonatomic, copy) void(^mt_touchEndBlock)(UIGestureRecognizer *gesture);
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIView (addEvent)
    
    @property (nonatomic, strong) MTAddEventMaker *mt_eventMaker;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    
    //
    //  UIView+Event.m
    //  testTabBar
    //
    //  Created by vanmr on 2020/3/18.
    //  Copyright © 2020 xdhl. All rights reserved.
    //
    
    #import "UIView+addEvent.h"
    #import <objc/runtime.h>
    
    static NSString *tap_propertyKey = @"MT_add_Tab_Gesture";
    static NSString *tap_block_propertyKey = @"MT_add_Tab_Gesture_block";
    static NSString *longPress_propertyKey = @"MT_add_longPress_Gesture";
    static NSString *group_animation_propertyKey = @"key_add_gruop_animation";
    static NSString *feedback_generator_propertyKey = @"key_add_feedback_generator";
    static NSString *event_maker_propertyKey = @"key_add_event_maker";
    
    @implementation MTAddEventMaker
    
    @end
    
    @implementation UIView (addEvent)
    
    - (CAAnimationGroup *)createGroupAnimationScaleFromValue:(CGFloat)scaleFromValue
                                                     toValue:(CGFloat)scaleToValue
                                            opacityFromValue:(CGFloat)opacityFromValue
                                              opacityToValue:(CGFloat)opacityToValue
                                                    duration:(CGFloat)duration
                                                 autoReverse:(BOOL)isAutoReverse
                                      animationCompleteBlock:(void (^)(void))completeBlock {
        [self.layer removeAnimationForKey:group_animation_propertyKey];
    
        CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        [scaleAnimation setFromValue:@(scaleFromValue)];
        [scaleAnimation setToValue:@(scaleToValue)];
    
        CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        [opacityAnimation setFromValue:@(opacityFromValue)];
        [opacityAnimation setToValue:@(opacityToValue)];
    
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[scaleAnimation, opacityAnimation];
        group.duration = duration;
        group.removedOnCompletion = NO;
        if (isAutoReverse) {
            group.autoreverses = YES;
        }
        group.fillMode = kCAFillModeForwards;
        [self.layer addAnimation:group forKey:group_animation_propertyKey];
        CGFloat delayTime = duration;
        if (isAutoReverse) {
            delayTime = 2 * duration;
        }
        [self performSelector:@selector(animationComplete:) withObject:completeBlock afterDelay:delayTime];
        return group;
    }
    
    - (void)animationComplete:(void (^)(void))completeBlock {
        if (completeBlock) {
            completeBlock();
        }
    }
    
    - (void)setFeedbackGenerator:(UIImpactFeedbackGenerator *)feedbackGenerator {
        if (!feedbackGenerator) {
            return;
        }
        objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(feedback_generator_propertyKey), feedbackGenerator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UIImpactFeedbackGenerator *)feedbackGenerator {
        UIImpactFeedbackGenerator *_feedbackRator = objc_getAssociatedObject(self, CFBridgingRetain(feedback_generator_propertyKey));
        if (!_feedbackRator) {
            _feedbackRator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
            objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(feedback_generator_propertyKey), _feedbackRator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return _feedbackRator;
    }
    
    
    - (void)setTabGesture:(UITapGestureRecognizer *)tabGesture {
        if (!tabGesture) {
            return;
        }
        objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(tap_propertyKey), tabGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UITapGestureRecognizer *)tabGesture {
        UITapGestureRecognizer *_tabGesture = objc_getAssociatedObject(self, CFBridgingRetain(tap_propertyKey));
        if (!_tabGesture) {
            _tabGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchViewGesture:)];
            objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(tap_propertyKey), _tabGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return _tabGesture;
    }
    
    - (void)setMt_eventMaker:(MTAddEventMaker *)mt_eventMaker {
        if (!mt_eventMaker) {
            return;
        }
        objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(event_maker_propertyKey), mt_eventMaker, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (MTAddEventMaker *)mt_eventMaker {
        MTAddEventMaker *_eventMaker = objc_getAssociatedObject(self, CFBridgingRetain(event_maker_propertyKey));
        if (!_eventMaker) {
            _eventMaker = [[MTAddEventMaker alloc] init];
    
            [self addGestureRecognizer:self.tabGesture];
            [self addGestureRecognizer:self.longPressGesture];
            self.userInteractionEnabled = YES;
            
            objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(event_maker_propertyKey), _eventMaker, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return _eventMaker;
    }
    
    - (void)setLongPressGesture:(UILongPressGestureRecognizer *)longPressGesture {
        if (!longPressGesture) {
            return;
        }
        objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(longPress_propertyKey), longPressGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UILongPressGestureRecognizer *)longPressGesture {
        UILongPressGestureRecognizer *_longPressGesture = objc_getAssociatedObject(self, CFBridgingRetain(longPress_propertyKey));
        if (!_longPressGesture) {
            _longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressViewGesture:)];
            _longPressGesture.minimumPressDuration = 0.3;
            objc_setAssociatedObject(self, (__bridge const void *_Nonnull)(longPress_propertyKey), _longPressGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
        return _longPressGesture;
    }
    
    - (void)touchViewGesture:(UITapGestureRecognizer *)tapGesture {
        self.userInteractionEnabled = NO;
    
        if (self.mt_eventMaker.mt_touchBeginBlock) {
            self.mt_eventMaker.mt_touchBeginBlock(tapGesture);
        }
    
        [self.feedbackGenerator impactOccurred];
        [self createGroupAnimationScaleFromValue:1.0 toValue:0.95 opacityFromValue:1.0 opacityToValue:0.7 duration:0.2 autoReverse:YES animationCompleteBlock:^{
            if (self.mt_eventMaker.mt_touchEndBlock) {
                self.mt_eventMaker.mt_touchEndBlock(tapGesture);
            }
            self.userInteractionEnabled = YES;
        }];
    }
    
    - (void)longPressViewGesture:(UILongPressGestureRecognizer *)longPressGesture {
        if (longPressGesture.state == UIGestureRecognizerStateBegan) {
            self.userInteractionEnabled = NO;
    
            if (self.mt_eventMaker.mt_touchBeginBlock) {
                self.mt_eventMaker.mt_touchBeginBlock(longPressGesture);
            }
            [self createGroupAnimationScaleFromValue:1.0 toValue:0.95 opacityFromValue:1.0 opacityToValue:0.7 duration:0.3 autoReverse:NO animationCompleteBlock:nil];
            [self.feedbackGenerator impactOccurred];
        }
    
        if (longPressGesture.state == UIGestureRecognizerStateEnded) {
            [self createGroupAnimationScaleFromValue:0.95 toValue:1.0 opacityFromValue:0.7 opacityToValue:1.0 duration:0.3 autoReverse:NO animationCompleteBlock:^{
                if (self.mt_eventMaker.mt_touchEndBlock) {
                    self.mt_eventMaker.mt_touchEndBlock(longPressGesture);
                }
            }];
            self.userInteractionEnabled = YES;
        }
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:iOS为UIview增加触感反馈动画和震动效果

          本文链接:https://www.haomeiwen.com/subject/sparvhtx.html