Advertisement
Guest User

Untitled

a guest
Feb 15th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. //  UIKitPagingScrollView.m
  3. //  DotsView
  4. //
  5. //  Created by SveDo on 12/01/2018.
  6. //  Copyright © 2018 SveDo. All rights reserved.
  7. //
  8.  
  9. #import "UIKitPagingView.h"
  10. #import "MagicScrollView.h"
  11. #import "UIKitScrollViewsSynchronizer.h"
  12. #import "Taptic.h"
  13.  
  14. #define kUIKitPagingViewIsUsingRunLoop        NO
  15.  
  16. @interface UIKitPagingView ()
  17. {
  18.     MagicScrollView *mScrollView;
  19.     NSMutableArray *mArrayOfScrollSubviews;
  20.     Class mClassElement;
  21.     void(^mConfigureElementBlock)(NSUInteger mUIntegerElementIndex, UIView *mReuseView);
  22.     CFRunLoopObserverRef mRunLoopObserver;
  23.    
  24.     BOOL mBoolIsNeedPose;
  25.     CGRect mCGRectBufferFrame;
  26.    
  27.     NSMutableDictionary *mMutableDictionaryPosedViews;
  28.     NSMutableSet *mSetOfReusableViews;
  29.    
  30.     CGFloat mCGFloatStartXPosition;
  31.    
  32.     UIView *mViewContent;
  33. }
  34. @end
  35.  
  36. @interface UIKitPagingView (UIScrollViewDelegate) <UIScrollViewDelegate>
  37. @end
  38.  
  39. @implementation UIKitPagingView
  40.  
  41. - (instancetype)initWithFrame:(CGRect)frame
  42. {
  43.     self = [super initWithFrame:frame];
  44.     if (self)
  45.     {
  46.         self.translatesAutoresizingMaskIntoConstraints = NO;
  47.         mMutableDictionaryPosedViews = [[NSMutableDictionary alloc] init];
  48.         mSetOfReusableViews = [[NSMutableSet alloc] init];
  49.        
  50.         mViewContent = [[UIView alloc] init];
  51.         [mViewContent setBackgroundColor:[UIColor clearColor]];
  52.         mViewContent.layer.masksToBounds = YES;
  53.         [self addSubview:mViewContent];
  54.        
  55.         mScrollView = [[MagicScrollView alloc] init];
  56.         mScrollView.directionalLockEnabled = YES;
  57.         [mViewContent addSubview:mScrollView];
  58.         mScrollView.delegate = self;
  59.         mScrollView.clipsToBounds = NO;
  60.         mScrollView.showsHorizontalScrollIndicator = NO;
  61.         mScrollView.showsVerticalScrollIndicator = NO;
  62.         mScrollView.pagingEnabled = YES;
  63.         if (kUIKitPagingViewIsUsingRunLoop)
  64.         {
  65.             __weak UIKitPagingView *weakSelf = self;
  66.             mRunLoopObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity)
  67.             {
  68.                 __strong UIKitPagingView *strongSelf = weakSelf;
  69.                 if (strongSelf->mBoolIsNeedPose == YES)
  70.                 {
  71.                     [strongSelf poseViews];
  72.                 }
  73.             });
  74.             CFRunLoopAddObserver(CFRunLoopGetMain(), mRunLoopObserver, kCFRunLoopCommonModes);
  75.         }
  76.     }
  77.     return self;
  78. }
  79.  
  80. - (UIView *)getReusableView
  81. {
  82.     if ([mSetOfReusableViews count] > 0)
  83.     {
  84.         UIView *view = [mSetOfReusableViews anyObject];
  85.         [mSetOfReusableViews removeObject:view];
  86.         return view;
  87.     }
  88.     return [[mClassElement alloc] init];
  89. }
  90.  
  91. - (void)reloadElements
  92. {
  93.     [[mMutableDictionaryPosedViews allValues] makeObjectsPerformSelector:@selector(removeFromSuperview)];
  94.     [mSetOfReusableViews addObjectsFromArray:[mMutableDictionaryPosedViews allValues]];
  95.     [mMutableDictionaryPosedViews removeAllObjects];
  96.     [self poseViews];
  97. }
  98.  
  99. - (void)poseViews
  100. {
  101.     if (mScrollView.bounds.size.width == 0)
  102.     {
  103.         return;
  104.     }
  105.     NSMutableIndexSet *mIndexSetShowedIndexes = [NSMutableIndexSet indexSet];
  106.    
  107.     for (NSUInteger index = (int)(mScrollView.contentOffset.x/self.bounds.size.width); index < [self mUIntegerNumberOfPages]; index++)
  108.     {
  109.         if (mScrollView.bounds.size.width * index - mScrollView.contentOffset.x > [self mViewContent].bounds.size.width)
  110.         {
  111.             break;
  112.         }
  113.         [mIndexSetShowedIndexes addIndex:index];
  114.     }
  115.    
  116.     for (NSNumber *index in [[mMutableDictionaryPosedViews allKeys] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id  _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings)
  117.                                                                                                  {
  118.                                                                                                      return [mIndexSetShowedIndexes containsIndex:[evaluatedObject unsignedIntegerValue]] ? NO : YES;
  119.                                                                                                  }]])
  120.     {
  121.         UIView *view = [mMutableDictionaryPosedViews objectForKey:index];
  122.         [view removeFromSuperview];
  123.         [mMutableDictionaryPosedViews removeObjectForKey:index];
  124.         [mSetOfReusableViews addObject:view];
  125.     }
  126.    
  127.     if (mClassElement == nil)
  128.     {
  129.         return;
  130.     }
  131.    
  132.     [mIndexSetShowedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop)
  133.     {
  134.         UIView *view;
  135.         if (!(view = [mMutableDictionaryPosedViews objectForKey:[NSNumber numberWithUnsignedInteger:idx]]))
  136.         {
  137.             view = [self getReusableView];
  138.             view.frame = CGRectMake(self.mCGFloatInsetBettweenPages/2.0 + mScrollView.bounds.size.width * idx, 0, mScrollView.bounds.size.width - self.mCGFloatInsetBettweenPages, mScrollView.bounds.size.height);
  139.             mConfigureElementBlock(idx, view);
  140.             [mScrollView addSubview:view];
  141.             [mMutableDictionaryPosedViews setObject:view forKey:[NSNumber numberWithUnsignedInteger:idx]];
  142.         }
  143.     }];
  144.    
  145.     CGSize targetContentSize = CGSizeMake(mScrollView.bounds.size.width * self.mUIntegerNumberOfPages, mScrollView.bounds.size.height);
  146.     if (!CGSizeEqualToSize(mScrollView.contentSize, targetContentSize))
  147.     {
  148.         mScrollView.contentSize = targetContentSize;
  149.     }
  150.    
  151.     NSUInteger selectedIndex = MIN((int)((mScrollView.contentOffset.x + (mScrollView.bounds.size.width/2.0))/ mScrollView.bounds.size.width), self.mUIntegerNumberOfPages-1);
  152.     if (selectedIndex != self.mUIntegerSelectedIndex)
  153.     {
  154.         mScrollView.contentOffset = CGPointMake(mScrollView.bounds.size.width * self.mUIntegerSelectedIndex, 0);
  155.         if (self.selectedIndexOffsetChangeBlock != nil)
  156.         {
  157.             self.selectedIndexOffsetChangeBlock(_mDoubleSelectedIndexOffset, YES);
  158.         }
  159.     }
  160.    
  161.     if (kUIKitPagingViewIsUsingRunLoop)
  162.     {
  163.         mBoolIsNeedPose = NO;
  164.     }
  165. }
  166.  
  167. - (void)setMUIEdgeInsetsPagePositionInsets:(UIEdgeInsets)mUIEdgeInsetsPagePositionInsets
  168. {
  169.     _mUIEdgeInsetsPagePositionInsets = mUIEdgeInsetsPagePositionInsets;
  170.     mCGRectBufferFrame = CGRectZero;
  171.     [self setNeedsLayout];
  172. }
  173.  
  174. - (void)layoutSubviews
  175. {
  176.     [super layoutSubviews];
  177.     if (!CGRectEqualToRect(mCGRectBufferFrame, self.bounds))
  178.     {
  179.         mViewContent.frame = self.bounds;
  180.         mScrollView.frame = CGRectMake(0 + _mUIEdgeInsetsPagePositionInsets.left, 0 + _mUIEdgeInsetsPagePositionInsets.top, self.bounds.size.width -  _mUIEdgeInsetsPagePositionInsets.left - _mUIEdgeInsetsPagePositionInsets.right, self.bounds.size.height - _mUIEdgeInsetsPagePositionInsets.top - _mUIEdgeInsetsPagePositionInsets.bottom);
  181.         mCGRectBufferFrame = self.bounds;
  182.         if (kUIKitPagingViewIsUsingRunLoop)
  183.         {
  184.             mBoolIsNeedPose = YES;
  185.         }
  186.         else
  187.         {
  188.             [self poseViews];
  189.         }
  190.     }
  191. }
  192.  
  193. - (UIView *)mViewContent
  194. {
  195.     return mViewContent;
  196. }
  197.  
  198. - (void)setMUIntegerNumberOfPages:(NSUInteger)mUIntegerNumberOfPages
  199. {
  200.     if (_mUIntegerNumberOfPages != mUIntegerNumberOfPages)
  201.     {
  202.         _mUIntegerNumberOfPages = mUIntegerNumberOfPages;
  203.         if (kUIKitPagingViewIsUsingRunLoop)
  204.         {
  205.             mBoolIsNeedPose = YES;
  206.         }
  207.         else
  208.         {
  209.             [self poseViews];
  210.         }
  211.     }
  212. }
  213.  
  214. - (void)setClass:(Class)elementsClass forConfigureElementBlock:(void (^)(NSUInteger, UIView *))block
  215. {
  216.     mClassElement = elementsClass;
  217.     mConfigureElementBlock = block;
  218.     if (kUIKitPagingViewIsUsingRunLoop)
  219.     {
  220.         mBoolIsNeedPose = YES;
  221.     }
  222.     else
  223.     {
  224.         [self poseViews];
  225.     }
  226. }
  227.  
  228. - (void)setMUIntegerSelectedIndex:(NSUInteger)mUIntegerSelectedIndex
  229. {
  230.     if (_mUIntegerSelectedIndex != mUIntegerSelectedIndex)
  231.     {
  232.         [self willChangeValueForKey:@"mUIntegerSelectedIndex"];
  233.         _mUIntegerSelectedIndex = mUIntegerSelectedIndex;
  234.         if (kUIKitPagingViewIsUsingRunLoop)
  235.         {
  236.             mBoolIsNeedPose = YES;
  237.         }
  238.         else
  239.         {
  240.             [self poseViews];
  241.         }
  242.         if (self.selectedIndexChangeBlock != nil)
  243.         {
  244.             self.selectedIndexChangeBlock(_mUIntegerSelectedIndex, mScrollView.contentOffset.x > mCGFloatStartXPosition);
  245.         }
  246.         [self didChangeValueForKey:@"mUIntegerSelectedIndex"];
  247.     }
  248. }
  249.  
  250. - (void)setMDoubleSelectedIndexOffset:(double)mDoubleSelectedIndexOffset
  251. {
  252.     if (_mDoubleSelectedIndexOffset != mDoubleSelectedIndexOffset)
  253.     {
  254.         [self willChangeValueForKey:@"mDoubleSelectedIndexOffset"];
  255.         _mDoubleSelectedIndexOffset = mDoubleSelectedIndexOffset;
  256.         if (kUIKitPagingViewIsUsingRunLoop)
  257.         {
  258.             mBoolIsNeedPose = YES;
  259.         }
  260.         else
  261.         {
  262.             [self poseViews];
  263.         }
  264.         if (self.selectedIndexOffsetChangeBlock != nil)
  265.         {
  266.             self.selectedIndexOffsetChangeBlock(_mDoubleSelectedIndexOffset, mScrollView.contentOffset.x > mCGFloatStartXPosition);
  267.         }
  268.         [self didChangeValueForKey:@"mDoubleSelectedIndexOffset"];
  269.     }
  270. }
  271.  
  272. - (void)dealloc
  273. {
  274.     if (mRunLoopObserver != NULL)
  275.     {
  276.         CFRunLoopRemoveObserver(CFRunLoopGetMain(), mRunLoopObserver, kCFRunLoopCommonModes);
  277.         CFRunLoopObserverInvalidate(mRunLoopObserver);
  278.         CFRelease(mRunLoopObserver);
  279.     }
  280. }
  281.  
  282. @end
  283.  
  284. @implementation UIKitPagingView (UIScrollViewDelegate)
  285.  
  286. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  287. {
  288.     [UIKitScrollViewsSynchronizer scrollViewDidScroll:scrollView];
  289.     NSUInteger selectedIndex = MIN((int)((MAX(scrollView.contentOffset.x, 0) + (scrollView.bounds.size.width/2.0))/ scrollView.bounds.size.width), self.mUIntegerNumberOfPages-1);
  290.     if ( self.mUIntegerSelectedIndex != selectedIndex )
  291.     {
  292.         self.mUIntegerSelectedIndex = selectedIndex;
  293.         [Taptic object:self requestTapticWithType:TapticTypeSelect];
  294.     }
  295.     self.mDoubleSelectedIndexOffset = (scrollView.contentOffset.x - (scrollView.bounds.size.width * selectedIndex))/(scrollView.bounds.size.width);
  296. }
  297.  
  298. - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  299. {
  300.     [Taptic object:self willRequestTapticWithType:TapticTypeSelect];
  301.     mCGFloatStartXPosition = scrollView.contentOffset.x;
  302.     [UIKitScrollViewsSynchronizer scrollViewWillBeginDragging:scrollView];
  303. }
  304.  
  305. - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
  306. {
  307.     if (!decelerate)
  308.     {
  309.         [Taptic object:self didRequestTapticWithType:TapticTypeSelect];
  310.     }
  311.     [UIKitScrollViewsSynchronizer scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
  312. }
  313.  
  314. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  315. {
  316.     [Taptic object:self didRequestTapticWithType:TapticTypeSelect];
  317.     [UIKitScrollViewsSynchronizer scrollViewDidEndDecelerating:scrollView];
  318. }
  319.  
  320. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement