New file |
| | |
| | | // |
| | | // ZFPlayerGestureControl.m |
| | | // ZFPlayer |
| | | // |
| | | // Copyright (c) 2016年 任子丰 ( http://github.com/renzifeng ) |
| | | // |
| | | // Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | // of this software and associated documentation files (the "Software"), to deal |
| | | // in the Software without restriction, including without limitation the rights |
| | | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | // copies of the Software, and to permit persons to whom the Software is |
| | | // furnished to do so, subject to the following conditions: |
| | | // |
| | | // The above copyright notice and this permission notice shall be included in |
| | | // all copies or substantial portions of the Software. |
| | | // |
| | | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| | | // THE SOFTWARE. |
| | | |
| | | #import "ZFPlayerGestureControl.h" |
| | | |
| | | @interface ZFPlayerGestureControl ()<UIGestureRecognizerDelegate> |
| | | |
| | | @property (nonatomic, strong) UITapGestureRecognizer *singleTap; |
| | | @property (nonatomic, strong) UITapGestureRecognizer *doubleTap; |
| | | @property (nonatomic, strong) UIPanGestureRecognizer *panGR; |
| | | @property (nonatomic, strong) UIPinchGestureRecognizer *pinchGR; |
| | | @property (nonatomic) ZFPanDirection panDirection; |
| | | @property (nonatomic) ZFPanLocation panLocation; |
| | | @property (nonatomic) ZFPanMovingDirection panMovingDirection; |
| | | @property (nonatomic, weak) UIView *targetView; |
| | | |
| | | @end |
| | | |
| | | @implementation ZFPlayerGestureControl |
| | | |
| | | - (void)addGestureToView:(UIView *)view { |
| | | self.targetView = view; |
| | | self.targetView.multipleTouchEnabled = YES; |
| | | [self.singleTap requireGestureRecognizerToFail:self.doubleTap]; |
| | | [self.doubleTap requireGestureRecognizerToFail:self.panGR]; |
| | | [self.targetView addGestureRecognizer:self.singleTap]; |
| | | [self.targetView addGestureRecognizer:self.doubleTap]; |
| | | [self.targetView addGestureRecognizer:self.panGR]; |
| | | [self.targetView addGestureRecognizer:self.pinchGR]; |
| | | } |
| | | |
| | | - (void)removeGestureToView:(UIView *)view { |
| | | [view removeGestureRecognizer:self.singleTap]; |
| | | [view removeGestureRecognizer:self.doubleTap]; |
| | | [view removeGestureRecognizer:self.panGR]; |
| | | [view removeGestureRecognizer:self.pinchGR]; |
| | | } |
| | | |
| | | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { |
| | | ZFPlayerGestureType type = ZFPlayerGestureTypeUnknown; |
| | | if (gestureRecognizer == self.singleTap) type = ZFPlayerGestureTypeSingleTap; |
| | | else if (gestureRecognizer == self.doubleTap) type = ZFPlayerGestureTypeDoubleTap; |
| | | else if (gestureRecognizer == self.panGR) type = ZFPlayerGestureTypePan; |
| | | else if (gestureRecognizer == self.pinchGR) type = ZFPlayerGestureTypePinch; |
| | | CGPoint locationPoint = [touch locationInView:touch.view]; |
| | | if (locationPoint.x > _targetView.bounds.size.width / 2) { |
| | | self.panLocation = ZFPanLocationRight; |
| | | } else { |
| | | self.panLocation = ZFPanLocationLeft; |
| | | } |
| | | |
| | | ZFPlayerDisableGestureTypes disableTypes = self.disableTypes; |
| | | if (disableTypes & ZFPlayerDisableGestureTypesAll) { |
| | | disableTypes = ZFPlayerDisableGestureTypesPan | ZFPlayerDisableGestureTypesPinch | ZFPlayerDisableGestureTypesDoubleTap | ZFPlayerDisableGestureTypesSingleTap; |
| | | } |
| | | switch (type) { |
| | | case ZFPlayerGestureTypeUnknown: break; |
| | | case ZFPlayerGestureTypePan: { |
| | | if (disableTypes & ZFPlayerDisableGestureTypesPan) { |
| | | return NO; |
| | | } |
| | | } |
| | | break; |
| | | case ZFPlayerGestureTypePinch: { |
| | | if (disableTypes & ZFPlayerDisableGestureTypesPinch) { |
| | | return NO; |
| | | } |
| | | } |
| | | break; |
| | | case ZFPlayerGestureTypeDoubleTap: { |
| | | if (disableTypes & ZFPlayerDisableGestureTypesDoubleTap) { |
| | | return NO; |
| | | } |
| | | } |
| | | break; |
| | | case ZFPlayerGestureTypeSingleTap: { |
| | | if (disableTypes & ZFPlayerDisableGestureTypesSingleTap) { |
| | | return NO; |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | |
| | | if (self.triggerCondition) return self.triggerCondition(self, type, gestureRecognizer, touch); |
| | | return YES; |
| | | } |
| | | |
| | | // Whether to support multi-trigger, return YES, you can trigger a method with multiple gestures, return NO is mutually exclusive |
| | | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { |
| | | if (otherGestureRecognizer != self.singleTap && |
| | | otherGestureRecognizer != self.doubleTap && |
| | | otherGestureRecognizer != self.panGR && |
| | | otherGestureRecognizer != self.pinchGR) return NO; |
| | | if (gestureRecognizer.numberOfTouches >= 2) { |
| | | return NO; |
| | | } |
| | | return YES; |
| | | } |
| | | |
| | | - (UITapGestureRecognizer *)singleTap { |
| | | if (!_singleTap){ |
| | | _singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; |
| | | _singleTap.delegate = self; |
| | | _singleTap.delaysTouchesBegan = YES; |
| | | _singleTap.delaysTouchesEnded = YES; |
| | | _singleTap.numberOfTouchesRequired = 1; |
| | | _singleTap.numberOfTapsRequired = 1; |
| | | } |
| | | return _singleTap; |
| | | } |
| | | |
| | | - (UITapGestureRecognizer *)doubleTap { |
| | | if (!_doubleTap) { |
| | | _doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; |
| | | _doubleTap.delegate = self; |
| | | _doubleTap.delaysTouchesBegan = YES; |
| | | _singleTap.delaysTouchesEnded = YES; |
| | | _doubleTap.numberOfTouchesRequired = 1; |
| | | _doubleTap.numberOfTapsRequired = 2; |
| | | } |
| | | return _doubleTap; |
| | | } |
| | | |
| | | - (UIPanGestureRecognizer *)panGR { |
| | | if (!_panGR) { |
| | | _panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; |
| | | _panGR.delegate = self; |
| | | _panGR.delaysTouchesBegan = YES; |
| | | _panGR.delaysTouchesEnded = YES; |
| | | _panGR.maximumNumberOfTouches = 1; |
| | | _panGR.cancelsTouchesInView = YES; |
| | | } |
| | | return _panGR; |
| | | } |
| | | |
| | | - (UIPinchGestureRecognizer *)pinchGR { |
| | | if (!_pinchGR) { |
| | | _pinchGR = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; |
| | | _pinchGR.delegate = self; |
| | | _pinchGR.delaysTouchesBegan = YES; |
| | | } |
| | | return _pinchGR; |
| | | } |
| | | |
| | | - (void)handleSingleTap:(UITapGestureRecognizer *)tap { |
| | | if (self.singleTapped) self.singleTapped(self); |
| | | } |
| | | |
| | | - (void)handleDoubleTap:(UITapGestureRecognizer *)tap { |
| | | if (self.doubleTapped) self.doubleTapped(self); |
| | | } |
| | | |
| | | - (void)handlePan:(UIPanGestureRecognizer *)pan { |
| | | CGPoint translate = [pan translationInView:pan.view]; |
| | | CGPoint velocity = [pan velocityInView:pan.view]; |
| | | switch (pan.state) { |
| | | case UIGestureRecognizerStateBegan: { |
| | | self.panMovingDirection = ZFPanMovingDirectionUnkown; |
| | | CGFloat x = fabs(velocity.x); |
| | | CGFloat y = fabs(velocity.y); |
| | | if (x > y) { |
| | | self.panDirection = ZFPanDirectionH; |
| | | } else { |
| | | self.panDirection = ZFPanDirectionV; |
| | | } |
| | | |
| | | if (self.beganPan) self.beganPan(self, self.panDirection, self.panLocation); |
| | | } |
| | | break; |
| | | case UIGestureRecognizerStateChanged: { |
| | | switch (_panDirection) { |
| | | case ZFPanDirectionH: { |
| | | if (translate.x > 0) { |
| | | self.panMovingDirection = ZFPanMovingDirectionRight; |
| | | } else if (translate.y < 0) { |
| | | self.panMovingDirection = ZFPanMovingDirectionLeft; |
| | | } |
| | | } |
| | | break; |
| | | case ZFPanDirectionV: { |
| | | if (translate.y > 0) { |
| | | self.panMovingDirection = ZFPanMovingDirectionBottom; |
| | | } else { |
| | | self.panMovingDirection = ZFPanMovingDirectionTop; |
| | | } |
| | | } |
| | | break; |
| | | case ZFPanDirectionUnknown: |
| | | break; |
| | | } |
| | | if (self.changedPan) self.changedPan(self, self.panDirection, self.panLocation, velocity); |
| | | } |
| | | break; |
| | | case UIGestureRecognizerStateFailed: |
| | | case UIGestureRecognizerStateCancelled: |
| | | case UIGestureRecognizerStateEnded: { |
| | | if (self.endedPan) self.endedPan(self, self.panDirection, self.panLocation); |
| | | } |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | [pan setTranslation:CGPointZero inView:pan.view]; |
| | | } |
| | | |
| | | - (void)handlePinch:(UIPinchGestureRecognizer *)pinch { |
| | | switch (pinch.state) { |
| | | case UIGestureRecognizerStateEnded: { |
| | | if (self.pinched) self.pinched(self, pinch.scale); |
| | | } |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | @end |