iOS为UIview增加触感反馈动画和震动效果
2020-04-16 本文已影响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