|
@@ -0,0 +1,917 @@
|
|
|
+//
|
|
|
+// UIScrollView+ZFPlayer.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 "UIScrollView+ZFPlayer.h"
|
|
|
+#import <objc/runtime.h>
|
|
|
+#import "ZFReachabilityManager.h"
|
|
|
+#import "ZFPlayer.h"
|
|
|
+
|
|
|
+#pragma clang diagnostic push
|
|
|
+#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
|
|
+
|
|
|
+@interface UIScrollView ()
|
|
|
+
|
|
|
+@property (nonatomic) CGFloat zf_lastOffsetY;
|
|
|
+@property (nonatomic) CGFloat zf_lastOffsetX;
|
|
|
+@property (nonatomic) ZFPlayerScrollDirection zf_scrollDirection;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation UIScrollView (ZFPlayer)
|
|
|
+
|
|
|
++ (void)load {
|
|
|
+ static dispatch_once_t onceToken;
|
|
|
+ dispatch_once(&onceToken, ^{
|
|
|
+ SEL selectors[] = {
|
|
|
+ @selector(setContentOffset:)
|
|
|
+ };
|
|
|
+
|
|
|
+ for (NSInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) {
|
|
|
+ SEL originalSelector = selectors[index];
|
|
|
+ SEL swizzledSelector = NSSelectorFromString([@"zf_" stringByAppendingString:NSStringFromSelector(originalSelector)]);
|
|
|
+ Method originalMethod = class_getInstanceMethod(self, originalSelector);
|
|
|
+ Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
|
|
|
+ if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) {
|
|
|
+ class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
|
|
|
+ } else {
|
|
|
+ method_exchangeImplementations(originalMethod, swizzledMethod);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_setContentOffset:(CGPoint)contentOffset {
|
|
|
+ if (self.zf_scrollViewDirection == ZFPlayerScrollViewDirectionVertical) {
|
|
|
+ [self _findCorrectCellWhenScrollViewDirectionVertical:nil];
|
|
|
+ } else {
|
|
|
+ [self _findCorrectCellWhenScrollViewDirectionHorizontal:nil];
|
|
|
+ }
|
|
|
+ [self zf_setContentOffset:contentOffset];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - private method
|
|
|
+
|
|
|
+- (void)_scrollViewDidStopScroll {
|
|
|
+ @weakify(self)
|
|
|
+ [self zf_filterShouldPlayCellWhileScrolled:^(NSIndexPath * _Nonnull indexPath) {
|
|
|
+ @strongify(self)
|
|
|
+ if (self.zf_scrollViewDidStopScrollCallback) self.zf_scrollViewDidStopScrollCallback(indexPath);
|
|
|
+ if (self.zf_scrollViewDidEndScrollingCallback) self.zf_scrollViewDidEndScrollingCallback(indexPath);
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)_scrollViewBeginDragging {
|
|
|
+ if (self.zf_scrollViewDirection == ZFPlayerScrollViewDirectionVertical) {
|
|
|
+ self.zf_lastOffsetY = self.contentOffset.y;
|
|
|
+ } else {
|
|
|
+ self.zf_lastOffsetX = self.contentOffset.x;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ The percentage of scrolling processed in vertical scrolling.
|
|
|
+ */
|
|
|
+- (void)_scrollViewScrollingDirectionVertical {
|
|
|
+ CGFloat offsetY = self.contentOffset.y;
|
|
|
+ self.zf_scrollDirection = (offsetY - self.zf_lastOffsetY > 0) ? ZFPlayerScrollDirectionUp : ZFPlayerScrollDirectionDown;
|
|
|
+ self.zf_lastOffsetY = offsetY;
|
|
|
+ if (self.zf_stopPlay) return;
|
|
|
+
|
|
|
+ UIView *playerView;
|
|
|
+ if (self.zf_containerType == ZFPlayerContainerTypeCell) {
|
|
|
+ // Avoid being paused the first time you play it.
|
|
|
+ if (self.contentOffset.y < 0) return;
|
|
|
+ if (!self.zf_playingIndexPath) return;
|
|
|
+
|
|
|
+ UIView *cell = [self zf_getCellForIndexPath:self.zf_playingIndexPath];
|
|
|
+ if (!cell) {
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ } else if (self.zf_containerType == ZFPlayerContainerTypeView) {
|
|
|
+ if (!self.zf_containerView) return;
|
|
|
+ playerView = self.zf_containerView;
|
|
|
+ }
|
|
|
+
|
|
|
+ CGRect rect1 = [playerView convertRect:playerView.frame toView:self];
|
|
|
+ CGRect rect = [self convertRect:rect1 toView:self.superview];
|
|
|
+ /// playerView top to scrollView top space.
|
|
|
+ CGFloat topSpacing = CGRectGetMinY(rect) - CGRectGetMinY(self.frame) - CGRectGetMinY(playerView.frame);
|
|
|
+ /// playerView bottom to scrollView bottom space.
|
|
|
+ CGFloat bottomSpacing = CGRectGetMaxY(self.frame) - CGRectGetMaxY(rect) + CGRectGetMinY(playerView.frame);
|
|
|
+ /// The height of the content area.
|
|
|
+ CGFloat contentInsetHeight = CGRectGetMaxY(self.frame) - CGRectGetMinY(self.frame);
|
|
|
+
|
|
|
+ CGFloat playerDisapperaPercent = 0;
|
|
|
+ CGFloat playerApperaPercent = 0;
|
|
|
+
|
|
|
+ if (self.zf_scrollDirection == ZFPlayerScrollDirectionUp) { /// Scroll up
|
|
|
+ /// Player is disappearing.
|
|
|
+ if (topSpacing <= 0 && CGRectGetHeight(rect) != 0) {
|
|
|
+ playerDisapperaPercent = -topSpacing/CGRectGetHeight(rect);
|
|
|
+ if (playerDisapperaPercent > 1.0) playerDisapperaPercent = 1.0;
|
|
|
+ if (self.zf_playerDisappearingInScrollView) self.zf_playerDisappearingInScrollView(self.zf_playingIndexPath, playerDisapperaPercent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Top area
|
|
|
+ if (topSpacing <= 0 && topSpacing > -CGRectGetHeight(rect)/2) {
|
|
|
+ /// When the player will disappear.
|
|
|
+ if (self.zf_playerWillDisappearInScrollView) self.zf_playerWillDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (topSpacing <= -CGRectGetHeight(rect)) {
|
|
|
+ /// When the player did disappeared.
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (topSpacing > 0 && topSpacing <= contentInsetHeight) {
|
|
|
+ /// Player is appearing.
|
|
|
+ if (CGRectGetHeight(rect) != 0) {
|
|
|
+ playerApperaPercent = -(topSpacing-contentInsetHeight)/CGRectGetHeight(rect);
|
|
|
+ if (playerApperaPercent > 1.0) playerApperaPercent = 1.0;
|
|
|
+ if (self.zf_playerAppearingInScrollView) self.zf_playerAppearingInScrollView(self.zf_playingIndexPath, playerApperaPercent);
|
|
|
+ }
|
|
|
+ /// In visable area
|
|
|
+ if (topSpacing <= contentInsetHeight && topSpacing > contentInsetHeight-CGRectGetHeight(rect)/2) {
|
|
|
+ /// When the player will appear.
|
|
|
+ if (self.zf_playerWillAppearInScrollView) self.zf_playerWillAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else {
|
|
|
+ /// When the player did appeared.
|
|
|
+ if (self.zf_playerDidAppearInScrollView) self.zf_playerDidAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (self.zf_scrollDirection == ZFPlayerScrollDirectionDown) { /// Scroll Down
|
|
|
+ /// Player is disappearing.
|
|
|
+ if (bottomSpacing <= 0 && CGRectGetHeight(rect) != 0) {
|
|
|
+ playerDisapperaPercent = -bottomSpacing/CGRectGetHeight(rect);
|
|
|
+ if (playerDisapperaPercent > 1.0) playerDisapperaPercent = 1.0;
|
|
|
+ if (self.zf_playerDisappearingInScrollView) self.zf_playerDisappearingInScrollView(self.zf_playingIndexPath, playerDisapperaPercent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Bottom area
|
|
|
+ if (bottomSpacing <= 0 && bottomSpacing > -CGRectGetHeight(rect)/2) {
|
|
|
+ /// When the player will disappear.
|
|
|
+ if (self.zf_playerWillDisappearInScrollView) self.zf_playerWillDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (bottomSpacing <= -CGRectGetHeight(rect)) {
|
|
|
+ /// When the player did disappeared.
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (bottomSpacing > 0 && bottomSpacing <= contentInsetHeight) {
|
|
|
+ /// Player is appearing.
|
|
|
+ if (CGRectGetHeight(rect) != 0) {
|
|
|
+ playerApperaPercent = -(bottomSpacing-contentInsetHeight)/CGRectGetHeight(rect);
|
|
|
+ if (playerApperaPercent > 1.0) playerApperaPercent = 1.0;
|
|
|
+ if (self.zf_playerAppearingInScrollView) self.zf_playerAppearingInScrollView(self.zf_playingIndexPath, playerApperaPercent);
|
|
|
+ }
|
|
|
+ /// In visable area
|
|
|
+ if (bottomSpacing <= contentInsetHeight && bottomSpacing > contentInsetHeight-CGRectGetHeight(rect)/2) {
|
|
|
+ /// When the player will appear.
|
|
|
+ if (self.zf_playerWillAppearInScrollView) self.zf_playerWillAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else {
|
|
|
+ /// When the player did appeared.
|
|
|
+ if (self.zf_playerDidAppearInScrollView) self.zf_playerDidAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ The percentage of scrolling processed in horizontal scrolling.
|
|
|
+ */
|
|
|
+- (void)_scrollViewScrollingDirectionHorizontal {
|
|
|
+ CGFloat offsetX = self.contentOffset.x;
|
|
|
+ self.zf_scrollDirection = (offsetX - self.zf_lastOffsetX > 0) ? ZFPlayerScrollDirectionLeft : ZFPlayerScrollDirectionRight;
|
|
|
+ self.zf_lastOffsetX = offsetX;
|
|
|
+ if (self.zf_stopPlay) return;
|
|
|
+
|
|
|
+ UIView *playerView;
|
|
|
+ if (self.zf_containerType == ZFPlayerContainerTypeCell) {
|
|
|
+ // Avoid being paused the first time you play it.
|
|
|
+ if (self.contentOffset.x < 0) return;
|
|
|
+ if (!self.zf_playingIndexPath) return;
|
|
|
+
|
|
|
+ UIView *cell = [self zf_getCellForIndexPath:self.zf_playingIndexPath];
|
|
|
+ if (!cell) {
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ } else if (self.zf_containerType == ZFPlayerContainerTypeView) {
|
|
|
+ if (!self.zf_containerView) return;
|
|
|
+ playerView = self.zf_containerView;
|
|
|
+ }
|
|
|
+
|
|
|
+ CGRect rect1 = [playerView convertRect:playerView.frame toView:self];
|
|
|
+ CGRect rect = [self convertRect:rect1 toView:self.superview];
|
|
|
+ /// playerView left to scrollView left space.
|
|
|
+ CGFloat leftSpacing = CGRectGetMinX(rect) - CGRectGetMinX(self.frame) - CGRectGetMinX(playerView.frame);
|
|
|
+ /// playerView bottom to scrollView right space.
|
|
|
+ CGFloat rightSpacing = CGRectGetMaxX(self.frame) - CGRectGetMaxX(rect) + CGRectGetMinX(playerView.frame);
|
|
|
+ /// The height of the content area.
|
|
|
+ CGFloat contentInsetWidth = CGRectGetMaxX(self.frame) - CGRectGetMinX(self.frame);
|
|
|
+
|
|
|
+ CGFloat playerDisapperaPercent = 0;
|
|
|
+ CGFloat playerApperaPercent = 0;
|
|
|
+
|
|
|
+ if (self.zf_scrollDirection == ZFPlayerScrollDirectionLeft) { /// Scroll left
|
|
|
+ /// Player is disappearing.
|
|
|
+ if (leftSpacing <= 0 && CGRectGetWidth(rect) != 0) {
|
|
|
+ playerDisapperaPercent = -leftSpacing/CGRectGetWidth(rect);
|
|
|
+ if (playerDisapperaPercent > 1.0) playerDisapperaPercent = 1.0;
|
|
|
+ if (self.zf_playerDisappearingInScrollView) self.zf_playerDisappearingInScrollView(self.zf_playingIndexPath, playerDisapperaPercent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Top area
|
|
|
+ if (leftSpacing <= 0 && leftSpacing > -CGRectGetWidth(rect)/2) {
|
|
|
+ /// When the player will disappear.
|
|
|
+ if (self.zf_playerWillDisappearInScrollView) self.zf_playerWillDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (leftSpacing <= -CGRectGetWidth(rect)) {
|
|
|
+ /// When the player did disappeared.
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (leftSpacing > 0 && leftSpacing <= contentInsetWidth) {
|
|
|
+ /// Player is appearing.
|
|
|
+ if (CGRectGetWidth(rect) != 0) {
|
|
|
+ playerApperaPercent = -(leftSpacing-contentInsetWidth)/CGRectGetWidth(rect);
|
|
|
+ if (playerApperaPercent > 1.0) playerApperaPercent = 1.0;
|
|
|
+ if (self.zf_playerAppearingInScrollView) self.zf_playerAppearingInScrollView(self.zf_playingIndexPath, playerApperaPercent);
|
|
|
+ }
|
|
|
+ /// In visable area
|
|
|
+ if (leftSpacing <= contentInsetWidth && leftSpacing > contentInsetWidth-CGRectGetWidth(rect)/2) {
|
|
|
+ /// When the player will appear.
|
|
|
+ if (self.zf_playerWillAppearInScrollView) self.zf_playerWillAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else {
|
|
|
+ /// When the player did appeared.
|
|
|
+ if (self.zf_playerDidAppearInScrollView) self.zf_playerDidAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (self.zf_scrollDirection == ZFPlayerScrollDirectionRight) { /// Scroll right
|
|
|
+ /// Player is disappearing.
|
|
|
+ if (rightSpacing <= 0 && CGRectGetWidth(rect) != 0) {
|
|
|
+ playerDisapperaPercent = -rightSpacing/CGRectGetWidth(rect);
|
|
|
+ if (playerDisapperaPercent > 1.0) playerDisapperaPercent = 1.0;
|
|
|
+ if (self.zf_playerDisappearingInScrollView) self.zf_playerDisappearingInScrollView(self.zf_playingIndexPath, playerDisapperaPercent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Bottom area
|
|
|
+ if (rightSpacing <= 0 && rightSpacing > -CGRectGetWidth(rect)/2) {
|
|
|
+ /// When the player will disappear.
|
|
|
+ if (self.zf_playerWillDisappearInScrollView) self.zf_playerWillDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (rightSpacing <= -CGRectGetWidth(rect)) {
|
|
|
+ /// When the player did disappeared.
|
|
|
+ if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else if (rightSpacing > 0 && rightSpacing <= contentInsetWidth) {
|
|
|
+ /// Player is appearing.
|
|
|
+ if (CGRectGetWidth(rect) != 0) {
|
|
|
+ playerApperaPercent = -(rightSpacing-contentInsetWidth)/CGRectGetWidth(rect);
|
|
|
+ if (playerApperaPercent > 1.0) playerApperaPercent = 1.0;
|
|
|
+ if (self.zf_playerAppearingInScrollView) self.zf_playerAppearingInScrollView(self.zf_playingIndexPath, playerApperaPercent);
|
|
|
+ }
|
|
|
+ /// In visable area
|
|
|
+ if (rightSpacing <= contentInsetWidth && rightSpacing > contentInsetWidth-CGRectGetWidth(rect)/2) {
|
|
|
+ /// When the player will appear.
|
|
|
+ if (self.zf_playerWillAppearInScrollView) self.zf_playerWillAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ } else {
|
|
|
+ /// When the player did appeared.
|
|
|
+ if (self.zf_playerDidAppearInScrollView) self.zf_playerDidAppearInScrollView(self.zf_playingIndexPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Find the playing cell while the scrollDirection is vertical.
|
|
|
+ */
|
|
|
+- (void)_findCorrectCellWhenScrollViewDirectionVertical:(void (^ __nullable)(NSIndexPath *indexPath))handler {
|
|
|
+ if (!self.zf_shouldAutoPlay) return;
|
|
|
+ if (self.zf_containerType == ZFPlayerContainerTypeView) return;
|
|
|
+
|
|
|
+ NSArray *visiableCells = nil;
|
|
|
+ NSIndexPath *indexPath = nil;
|
|
|
+ if ([self _isTableView]) {
|
|
|
+ UITableView *tableView = (UITableView *)self;
|
|
|
+ visiableCells = [tableView visibleCells];
|
|
|
+ // First visible cell indexPath
|
|
|
+ indexPath = tableView.indexPathsForVisibleRows.firstObject;
|
|
|
+ if (self.contentOffset.y <= 0 && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Last visible cell indexPath
|
|
|
+ indexPath = tableView.indexPathsForVisibleRows.lastObject;
|
|
|
+ if (self.contentOffset.y + self.frame.size.height >= self.contentSize.height && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if ([self _isCollectionView]) {
|
|
|
+ UICollectionView *collectionView = (UICollectionView *)self;
|
|
|
+ visiableCells = [collectionView visibleCells];
|
|
|
+ NSArray *sortedIndexPaths = [collectionView.indexPathsForVisibleItems sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
|
|
+ return [obj1 compare:obj2];
|
|
|
+ }];
|
|
|
+
|
|
|
+ visiableCells = [visiableCells sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
|
|
+ NSIndexPath *path1 = (NSIndexPath *)[collectionView indexPathForCell:obj1];
|
|
|
+ NSIndexPath *path2 = (NSIndexPath *)[collectionView indexPathForCell:obj2];
|
|
|
+ return [path1 compare:path2];
|
|
|
+ }];
|
|
|
+
|
|
|
+ // First visible cell indexPath
|
|
|
+ indexPath = sortedIndexPaths.firstObject;
|
|
|
+ if (self.contentOffset.y <= 0 && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Last visible cell indexPath
|
|
|
+ indexPath = sortedIndexPaths.lastObject;
|
|
|
+ if (self.contentOffset.y + self.frame.size.height >= self.contentSize.height && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ NSArray *cells = nil;
|
|
|
+ if (self.zf_scrollDirection == ZFPlayerScrollDirectionUp) {
|
|
|
+ cells = visiableCells;
|
|
|
+ } else {
|
|
|
+ cells = [visiableCells reverseObjectEnumerator].allObjects;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Mid line.
|
|
|
+ CGFloat scrollViewMidY = CGRectGetHeight(self.frame)/2;
|
|
|
+ /// The final playing indexPath.
|
|
|
+ __block NSIndexPath *finalIndexPath = nil;
|
|
|
+ /// The final distance from the center line.
|
|
|
+ __block CGFloat finalSpace = 0;
|
|
|
+ @weakify(self)
|
|
|
+ [cells enumerateObjectsUsingBlock:^(UIView *cell, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
+ @strongify(self)
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (!playerView) return;
|
|
|
+ CGRect rect1 = [playerView convertRect:playerView.frame toView:self];
|
|
|
+ CGRect rect = [self convertRect:rect1 toView:self.superview];
|
|
|
+ /// playerView top to scrollView top space.
|
|
|
+ CGFloat topSpacing = CGRectGetMinY(rect) - CGRectGetMinY(self.frame) - CGRectGetMinY(playerView.frame);
|
|
|
+ /// playerView bottom to scrollView bottom space.
|
|
|
+ CGFloat bottomSpacing = CGRectGetMaxY(self.frame) - CGRectGetMaxY(rect) + CGRectGetMinY(playerView.frame);
|
|
|
+ CGFloat centerSpacing = ABS(scrollViewMidY - CGRectGetMidY(rect));
|
|
|
+ NSIndexPath *indexPath = [self zf_getIndexPathForCell:cell];
|
|
|
+
|
|
|
+ /// Play when the video playback section is visible.
|
|
|
+ if ((topSpacing >= -(1 - self.zf_playerApperaPercent) * CGRectGetHeight(rect)) && (bottomSpacing >= -(1 - self.zf_playerApperaPercent) * CGRectGetHeight(rect))) {
|
|
|
+ /// If you have a cell that is playing, stop the traversal.
|
|
|
+ if (self.zf_playingIndexPath) {
|
|
|
+ indexPath = self.zf_playingIndexPath;
|
|
|
+ finalIndexPath = indexPath;
|
|
|
+ *stop = YES;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!finalIndexPath || centerSpacing < finalSpace) {
|
|
|
+ finalIndexPath = indexPath;
|
|
|
+ finalSpace = centerSpacing;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ /// if find the playing indexPath.
|
|
|
+ if (finalIndexPath) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(finalIndexPath);
|
|
|
+ }
|
|
|
+ self.zf_shouldPlayIndexPath = finalIndexPath;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ Find the playing cell while the scrollDirection is horizontal.
|
|
|
+ */
|
|
|
+- (void)_findCorrectCellWhenScrollViewDirectionHorizontal:(void (^ __nullable)(NSIndexPath *indexPath))handler {
|
|
|
+ if (!self.zf_shouldAutoPlay) return;
|
|
|
+ if (self.zf_containerType == ZFPlayerContainerTypeView) return;
|
|
|
+
|
|
|
+ NSArray *visiableCells = nil;
|
|
|
+ NSIndexPath *indexPath = nil;
|
|
|
+ if ([self _isTableView]) {
|
|
|
+ UITableView *tableView = (UITableView *)self;
|
|
|
+ visiableCells = [tableView visibleCells];
|
|
|
+ // First visible cell indexPath
|
|
|
+ indexPath = tableView.indexPathsForVisibleRows.firstObject;
|
|
|
+ if (self.contentOffset.x <= 0 && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Last visible cell indexPath
|
|
|
+ indexPath = tableView.indexPathsForVisibleRows.lastObject;
|
|
|
+ if (self.contentOffset.x + self.frame.size.width >= self.contentSize.width && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if ([self _isCollectionView]) {
|
|
|
+ UICollectionView *collectionView = (UICollectionView *)self;
|
|
|
+ visiableCells = [collectionView visibleCells];
|
|
|
+ NSArray *sortedIndexPaths = [collectionView.indexPathsForVisibleItems sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
|
|
+ return [obj1 compare:obj2];
|
|
|
+ }];
|
|
|
+
|
|
|
+ visiableCells = [visiableCells sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
|
|
+ NSIndexPath *path1 = (NSIndexPath *)[collectionView indexPathForCell:obj1];
|
|
|
+ NSIndexPath *path2 = (NSIndexPath *)[collectionView indexPathForCell:obj2];
|
|
|
+ return [path1 compare:path2];
|
|
|
+ }];
|
|
|
+
|
|
|
+ // First visible cell indexPath
|
|
|
+ indexPath = sortedIndexPaths.firstObject;
|
|
|
+ if (self.contentOffset.x <= 0 && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Last visible cell indexPath
|
|
|
+ indexPath = sortedIndexPaths.lastObject;
|
|
|
+ if (self.contentOffset.x + self.frame.size.width >= self.contentSize.width && (!self.zf_playingIndexPath || [indexPath compare:self.zf_playingIndexPath] == NSOrderedSame)) {
|
|
|
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (playerView) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ NSArray *cells = nil;
|
|
|
+ if (self.zf_scrollDirection == ZFPlayerScrollDirectionUp) {
|
|
|
+ cells = visiableCells;
|
|
|
+ } else {
|
|
|
+ cells = [visiableCells reverseObjectEnumerator].allObjects;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Mid line.
|
|
|
+ CGFloat scrollViewMidX = CGRectGetWidth(self.frame)/2;
|
|
|
+ /// The final playing indexPath.
|
|
|
+ __block NSIndexPath *finalIndexPath = nil;
|
|
|
+ /// The final distance from the center line.
|
|
|
+ __block CGFloat finalSpace = 0;
|
|
|
+ @weakify(self)
|
|
|
+ [cells enumerateObjectsUsingBlock:^(UIView *cell, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
+ @strongify(self)
|
|
|
+ UIView *playerView = [cell viewWithTag:self.zf_containerViewTag];
|
|
|
+ if (!playerView) return;
|
|
|
+ CGRect rect1 = [playerView convertRect:playerView.frame toView:self];
|
|
|
+ CGRect rect = [self convertRect:rect1 toView:self.superview];
|
|
|
+ /// playerView left to scrollView top space.
|
|
|
+ CGFloat leftSpacing = CGRectGetMinX(rect) - CGRectGetMinX(self.frame) - CGRectGetMinX(playerView.frame);
|
|
|
+ /// playerView right to scrollView top space.
|
|
|
+ CGFloat rightSpacing = CGRectGetMaxX(self.frame) - CGRectGetMaxX(rect) + CGRectGetMinX(playerView.frame);
|
|
|
+ CGFloat centerSpacing = ABS(scrollViewMidX - CGRectGetMidX(rect));
|
|
|
+ NSIndexPath *indexPath = [self zf_getIndexPathForCell:cell];
|
|
|
+
|
|
|
+ /// Play when the video playback section is visible.
|
|
|
+ if ((leftSpacing >= -(1 - self.zf_playerApperaPercent) * CGRectGetWidth(rect)) && (rightSpacing >= -(1 - self.zf_playerApperaPercent) * CGRectGetWidth(rect))) {
|
|
|
+ /// If you have a cell that is playing, stop the traversal.
|
|
|
+ if (self.zf_playingIndexPath) {
|
|
|
+ indexPath = self.zf_playingIndexPath;
|
|
|
+ finalIndexPath = indexPath;
|
|
|
+ *stop = YES;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!finalIndexPath || centerSpacing < finalSpace) {
|
|
|
+ finalIndexPath = indexPath;
|
|
|
+ finalSpace = centerSpacing;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ /// if find the playing indexPath.
|
|
|
+ if (finalIndexPath) {
|
|
|
+ if (self.zf_scrollViewDidScrollCallback) self.zf_scrollViewDidScrollCallback(indexPath);
|
|
|
+ if (handler) handler(finalIndexPath);
|
|
|
+ self.zf_shouldPlayIndexPath = finalIndexPath;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)_isTableView {
|
|
|
+ return [self isKindOfClass:[UITableView class]];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)_isCollectionView {
|
|
|
+ return [self isKindOfClass:[UICollectionView class]];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - public method
|
|
|
+
|
|
|
+- (UIView *)zf_getCellForIndexPath:(NSIndexPath *)indexPath {
|
|
|
+ if ([self _isTableView]) {
|
|
|
+ UITableView *tableView = (UITableView *)self;
|
|
|
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
|
|
|
+ return cell;
|
|
|
+ } else if ([self _isCollectionView]) {
|
|
|
+ UICollectionView *collectionView = (UICollectionView *)self;
|
|
|
+ UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
|
|
|
+ return cell;
|
|
|
+ }
|
|
|
+ return nil;
|
|
|
+}
|
|
|
+
|
|
|
+- (NSIndexPath *)zf_getIndexPathForCell:(UIView *)cell {
|
|
|
+ if ([self _isTableView]) {
|
|
|
+ UITableView *tableView = (UITableView *)self;
|
|
|
+ NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)cell];
|
|
|
+ return indexPath;
|
|
|
+ } else if ([self _isCollectionView]) {
|
|
|
+ UICollectionView *collectionView = (UICollectionView *)self;
|
|
|
+ NSIndexPath *indexPath = [collectionView indexPathForCell:(UICollectionViewCell *)cell];
|
|
|
+ return indexPath;
|
|
|
+ }
|
|
|
+ return nil;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollToRowAtIndexPath:(NSIndexPath *)indexPath completionHandler:(void (^ __nullable)(void))completionHandler {
|
|
|
+ [self zf_scrollToRowAtIndexPath:indexPath animated:YES completionHandler:completionHandler];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollToRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated completionHandler:(void (^ __nullable)(void))completionHandler {
|
|
|
+ [self zf_scrollToRowAtIndexPath:indexPath animateWithDuration:animated ? 0.4 : 0.0 completionHandler:completionHandler];
|
|
|
+}
|
|
|
+
|
|
|
+/// Scroll to indexPath with animations duration.
|
|
|
+- (void)zf_scrollToRowAtIndexPath:(NSIndexPath *)indexPath animateWithDuration:(NSTimeInterval)duration completionHandler:(void (^ __nullable)(void))completionHandler {
|
|
|
+ BOOL animated = duration > 0.0;
|
|
|
+ if ([self _isTableView]) {
|
|
|
+ UITableView *tableView = (UITableView *)self;
|
|
|
+ [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:animated];
|
|
|
+ } else if ([self _isCollectionView]) {
|
|
|
+ UICollectionView *collectionView = (UICollectionView *)self;
|
|
|
+ [collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionTop animated:animated];
|
|
|
+ }
|
|
|
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
+ if (completionHandler) completionHandler();
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollViewDidEndDecelerating {
|
|
|
+ BOOL scrollToScrollStop = !self.tracking && !self.dragging && !self.decelerating;
|
|
|
+ if (scrollToScrollStop) {
|
|
|
+ [self _scrollViewDidStopScroll];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollViewDidEndDraggingWillDecelerate:(BOOL)decelerate {
|
|
|
+ if (!decelerate) {
|
|
|
+ BOOL dragToDragStop = self.tracking && !self.dragging && !self.decelerating;
|
|
|
+ if (dragToDragStop) {
|
|
|
+ [self _scrollViewDidStopScroll];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollViewDidScrollToTop {
|
|
|
+ [self _scrollViewDidStopScroll];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollViewDidScroll {
|
|
|
+ if (self.zf_scrollViewDirection == ZFPlayerScrollViewDirectionVertical) {
|
|
|
+ [self _scrollViewScrollingDirectionVertical];
|
|
|
+ } else {
|
|
|
+ [self _scrollViewScrollingDirectionHorizontal];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_scrollViewWillBeginDragging {
|
|
|
+ [self _scrollViewBeginDragging];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - getter
|
|
|
+
|
|
|
+- (ZFPlayerScrollDirection)zf_scrollDirection {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) integerValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (ZFPlayerScrollViewDirection)zf_scrollViewDirection {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) integerValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (CGFloat)zf_lastOffsetY {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) floatValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (CGFloat)zf_lastOffsetX {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) floatValue];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - setter
|
|
|
+
|
|
|
+- (void)setZf_scrollDirection:(ZFPlayerScrollDirection)zf_scrollDirection {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_scrollDirection), @(zf_scrollDirection), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_scrollViewDirection:(ZFPlayerScrollViewDirection)zf_scrollViewDirection {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_scrollViewDirection), @(zf_scrollViewDirection), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_lastOffsetY:(CGFloat)zf_lastOffsetY {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_lastOffsetY), @(zf_lastOffsetY), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_lastOffsetX:(CGFloat)zf_lastOffsetX {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_lastOffsetX), @(zf_lastOffsetX), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation UIScrollView (ZFPlayerCannotCalled)
|
|
|
+
|
|
|
+- (void)zf_filterShouldPlayCellWhileScrolling:(void (^ __nullable)(NSIndexPath *indexPath))handler {
|
|
|
+ if (self.zf_scrollViewDirection == ZFPlayerScrollViewDirectionVertical) {
|
|
|
+ [self _findCorrectCellWhenScrollViewDirectionVertical:handler];
|
|
|
+ } else {
|
|
|
+ [self _findCorrectCellWhenScrollViewDirectionHorizontal:handler];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)zf_filterShouldPlayCellWhileScrolled:(void (^ __nullable)(NSIndexPath *indexPath))handler {
|
|
|
+ if (!self.zf_shouldAutoPlay) return;
|
|
|
+ @weakify(self)
|
|
|
+ [self zf_filterShouldPlayCellWhileScrolling:^(NSIndexPath *indexPath) {
|
|
|
+ @strongify(self)
|
|
|
+ /// 如果当前控制器已经消失,直接return
|
|
|
+ if (self.zf_viewControllerDisappear) return;
|
|
|
+ if ([ZFReachabilityManager sharedManager].isReachableViaWWAN && !self.zf_WWANAutoPlay) {
|
|
|
+ /// 移动网络
|
|
|
+ self.zf_shouldPlayIndexPath = indexPath;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (handler) handler(indexPath);
|
|
|
+ self.zf_playingIndexPath = indexPath;
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - getter
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerDisappearingInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerAppearingInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_playerDidAppearInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_playerWillDisappearInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_playerWillAppearInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_playerDidDisappearInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidEndScrollingCallback {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidScrollCallback {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_playerShouldPlayInScrollView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (CGFloat)zf_playerApperaPercent {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) floatValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (CGFloat)zf_playerDisapperaPercent {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) floatValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)zf_viewControllerDisappear {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) boolValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)zf_stopPlay {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) boolValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)zf_stopWhileNotVisible {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) boolValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (NSIndexPath *)zf_playingIndexPath {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (NSIndexPath *)zf_shouldPlayIndexPath {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (NSInteger)zf_containerViewTag {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) integerValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)zf_isWWANAutoPlay {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) boolValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)zf_shouldAutoPlay {
|
|
|
+ NSNumber *number = objc_getAssociatedObject(self, _cmd);
|
|
|
+ if (number) return number.boolValue;
|
|
|
+ self.zf_shouldAutoPlay = YES;
|
|
|
+ return YES;
|
|
|
+}
|
|
|
+
|
|
|
+- (ZFPlayerContainerType)zf_containerType {
|
|
|
+ return [objc_getAssociatedObject(self, _cmd) integerValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (UIView *)zf_containerView {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - setter
|
|
|
+
|
|
|
+- (void)setZf_playerDisappearingInScrollView:(void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerDisappearingInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerDisappearingInScrollView), zf_playerDisappearingInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerAppearingInScrollView:(void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerAppearingInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerAppearingInScrollView), zf_playerAppearingInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerDidAppearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerDidAppearInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerDidAppearInScrollView), zf_playerDidAppearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerWillDisappearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerWillDisappearInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerWillDisappearInScrollView), zf_playerWillDisappearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerWillAppearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerWillAppearInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerWillAppearInScrollView), zf_playerWillAppearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerDidDisappearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerDidDisappearInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerDidDisappearInScrollView), zf_playerDidDisappearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_scrollViewDidEndScrollingCallback:(void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidEndScrollingCallback {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_scrollViewDidEndScrollingCallback), zf_scrollViewDidEndScrollingCallback, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_scrollViewDidScrollCallback:(void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidScrollCallback {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_scrollViewDidScrollCallback), zf_scrollViewDidScrollCallback, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerShouldPlayInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerShouldPlayInScrollView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerShouldPlayInScrollView), zf_playerShouldPlayInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerApperaPercent:(CGFloat)zf_playerApperaPercent {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerApperaPercent), @(zf_playerApperaPercent), OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playerDisapperaPercent:(CGFloat)zf_playerDisapperaPercent {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playerDisapperaPercent), @(zf_playerDisapperaPercent), OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_viewControllerDisappear:(BOOL)zf_viewControllerDisappear {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_viewControllerDisappear), @(zf_viewControllerDisappear), OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_stopPlay:(BOOL)zf_stopPlay {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_stopPlay), @(zf_stopPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_stopWhileNotVisible:(BOOL)zf_stopWhileNotVisible {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_stopWhileNotVisible), @(zf_stopWhileNotVisible), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_playingIndexPath:(NSIndexPath *)zf_playingIndexPath {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_playingIndexPath), zf_playingIndexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+ if (zf_playingIndexPath && [zf_playingIndexPath compare:self.zf_shouldPlayIndexPath] != NSOrderedSame) {
|
|
|
+ self.zf_shouldPlayIndexPath = zf_playingIndexPath;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_shouldPlayIndexPath:(NSIndexPath *)zf_shouldPlayIndexPath {
|
|
|
+ if (self.zf_playerShouldPlayInScrollView) self.zf_playerShouldPlayInScrollView(zf_shouldPlayIndexPath);
|
|
|
+ if (self.zf_shouldPlayIndexPathCallback) self.zf_shouldPlayIndexPathCallback(zf_shouldPlayIndexPath);
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_shouldPlayIndexPath), zf_shouldPlayIndexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_containerViewTag:(NSInteger)zf_containerViewTag {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_containerViewTag), @(zf_containerViewTag), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_containerType:(ZFPlayerContainerType)zf_containerType {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_containerType), @(zf_containerType), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_containerView:(UIView *)zf_containerView {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_containerView), zf_containerView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_shouldAutoPlay:(BOOL)zf_shouldAutoPlay {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_shouldAutoPlay), @(zf_shouldAutoPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_WWANAutoPlay:(BOOL)zf_WWANAutoPlay {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_isWWANAutoPlay), @(zf_WWANAutoPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+
|
|
|
+@implementation UIScrollView (ZFPlayerDeprecated)
|
|
|
+
|
|
|
+#pragma mark - getter
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidStopScrollCallback {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+- (void (^)(NSIndexPath * _Nonnull))zf_shouldPlayIndexPathCallback {
|
|
|
+ return objc_getAssociatedObject(self, _cmd);
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - setter
|
|
|
+
|
|
|
+- (void)setZf_scrollViewDidStopScrollCallback:(void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidStopScrollCallback {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_scrollViewDidStopScrollCallback), zf_scrollViewDidStopScrollCallback, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setZf_shouldPlayIndexPathCallback:(void (^)(NSIndexPath * _Nonnull))zf_shouldPlayIndexPathCallback {
|
|
|
+ objc_setAssociatedObject(self, @selector(zf_shouldPlayIndexPathCallback), zf_shouldPlayIndexPathCallback, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
|
|
+}
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+#pragma clang diagnostic pop
|