// // TAPageControl.m // TAPageControl // // Created by Tanguy Aladenise on 2015-01-21. // Copyright (c) 2015 Tanguy Aladenise. All rights reserved. // #import "TAPageControl.h" #import "TAAbstractDotView.h" #import "TAAnimatedDotView.h" #import "TADotView.h" /** * Default number of pages for initialization */ static NSInteger const kDefaultNumberOfPages = 0; /** * Default current page for initialization */ static NSInteger const kDefaultCurrentPage = 0; /** * Default setting for hide for single page feature. For initialization */ static BOOL const kDefaultHideForSinglePage = NO; /** * Default setting for shouldResizeFromCenter. For initialiation */ static BOOL const kDefaultShouldResizeFromCenter = YES; /** * Default spacing between dots */ static NSInteger const kDefaultSpacingBetweenDots = 8; /** * Default dot size */ static CGSize const kDefaultDotSize = {8, 8}; @interface TAPageControl() /** * Array of dot views for reusability and touch events. */ @property (strong, nonatomic) NSMutableArray *dots; @end @implementation TAPageControl #pragma mark - Lifecycle - (id)init { self = [super init]; if (self) { [self initialization]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initialization]; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initialization]; } return self; } /** * Default setup when initiating control */ - (void)initialization { self.dotViewClass = [TAAnimatedDotView class]; self.spacingBetweenDots = kDefaultSpacingBetweenDots; self.numberOfPages = kDefaultNumberOfPages; self.currentPage = kDefaultCurrentPage; self.hidesForSinglePage = kDefaultHideForSinglePage; self.shouldResizeFromCenter = kDefaultShouldResizeFromCenter; } #pragma mark - Touch event - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if (touch.view != self) { NSInteger index = [self.dots indexOfObject:touch.view]; if ([self.delegate respondsToSelector:@selector(TAPageControl:didSelectPageAtIndex:)]) { [self.delegate TAPageControl:self didSelectPageAtIndex:index]; } } } #pragma mark - Layout /** * Resizes and moves the receiver view so it just encloses its subviews. */ - (void)sizeToFit { [self updateFrame:YES]; } - (CGSize)sizeForNumberOfPages:(NSInteger)pageCount { return CGSizeMake((self.dotSize.width + self.spacingBetweenDots) * pageCount - self.spacingBetweenDots , self.dotSize.height); } /** * Will update dots display and frame. Reuse existing views or instantiate one if required. Update their position in case frame changed. */ - (void)updateDots { if (self.numberOfPages == 0) { return; } for (NSInteger i = 0; i < self.numberOfPages; i++) { UIView *dot; if (i < self.dots.count) { dot = [self.dots objectAtIndex:i]; } else { dot = [self generateDotView]; } [self updateDotFrame:dot atIndex:i]; } [self changeActivity:YES atIndex:self.currentPage]; [self hideForSinglePage]; } /** * Update frame control to fit current number of pages. It will apply required size if authorize and required. * * @param overrideExistingFrame BOOL to allow frame to be overriden. Meaning the required size will be apply no mattter what. */ - (void)updateFrame:(BOOL)overrideExistingFrame { CGPoint center = self.center; CGSize requiredSize = [self sizeForNumberOfPages:self.numberOfPages]; // We apply requiredSize only if authorize to and necessary if (overrideExistingFrame || ((CGRectGetWidth(self.frame) < requiredSize.width || CGRectGetHeight(self.frame) < requiredSize.height) && !overrideExistingFrame)) { self.frame = CGRectMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame), requiredSize.width, requiredSize.height); if (self.shouldResizeFromCenter) { self.center = center; } } [self resetDotViews]; } /** * Update the frame of a specific dot at a specific index * * @param dot Dot view * @param index Page index of dot */ - (void)updateDotFrame:(UIView *)dot atIndex:(NSInteger)index { // Dots are always centered within view CGFloat x = (self.dotSize.width + self.spacingBetweenDots) * index + ( (CGRectGetWidth(self.frame) - [self sizeForNumberOfPages:self.numberOfPages].width) / 2); CGFloat y = (CGRectGetHeight(self.frame) - self.dotSize.height) / 2; dot.frame = CGRectMake(x, y, self.dotSize.width, self.dotSize.height); } #pragma mark - Utils /** * Generate a dot view and add it to the collection * * @return The UIView object representing a dot */ - (UIView *)generateDotView { UIView *dotView; if (self.dotViewClass) { dotView = [[self.dotViewClass alloc] initWithFrame:CGRectMake(0, 0, self.dotSize.width, self.dotSize.height)]; if ([dotView isKindOfClass:[TAAnimatedDotView class]] && self.dotColor) { ((TAAnimatedDotView *)dotView).dotColor = self.dotColor; } } else { dotView = [[UIImageView alloc] initWithImage:self.dotImage]; dotView.frame = CGRectMake(0, 0, self.dotSize.width, self.dotSize.height); } if (dotView) { [self addSubview:dotView]; [self.dots addObject:dotView]; } dotView.userInteractionEnabled = YES; return dotView; } /** * Change activity state of a dot view. Current/not currrent. * * @param active Active state to apply * @param index Index of dot for state update */ - (void)changeActivity:(BOOL)active atIndex:(NSInteger)index { if (self.dotViewClass) { TAAbstractDotView *abstractDotView = (TAAbstractDotView *)[self.dots objectAtIndex:index]; if ([abstractDotView respondsToSelector:@selector(changeActivityState:)]) { [abstractDotView changeActivityState:active]; } else { NSLog(@"Custom view : %@ must implement an 'changeActivityState' method or you can subclass %@ to help you.", self.dotViewClass, [TAAbstractDotView class]); } } else if (self.dotImage && self.currentDotImage) { UIImageView *dotView = (UIImageView *)[self.dots objectAtIndex:index]; dotView.image = (active) ? self.currentDotImage : self.dotImage; } } - (void)resetDotViews { for (UIView *dotView in self.dots) { [dotView removeFromSuperview]; } [self.dots removeAllObjects]; [self updateDots]; } - (void)hideForSinglePage { if (self.dots.count == 1 && self.hidesForSinglePage) { self.hidden = YES; } else { self.hidden = NO; } } #pragma mark - Setters - (void)setNumberOfPages:(NSInteger)numberOfPages { _numberOfPages = numberOfPages; // Update dot position to fit new number of pages [self resetDotViews]; } - (void)setSpacingBetweenDots:(NSInteger)spacingBetweenDots { _spacingBetweenDots = spacingBetweenDots; [self resetDotViews]; } - (void)setCurrentPage:(NSInteger)currentPage { // If no pages, no current page to treat. if (self.numberOfPages == 0 || currentPage == _currentPage) { _currentPage = currentPage; return; } // Pre set [self changeActivity:NO atIndex:_currentPage]; _currentPage = currentPage; // Post set [self changeActivity:YES atIndex:_currentPage]; } - (void)setDotImage:(UIImage *)dotImage { _dotImage = dotImage; [self resetDotViews]; self.dotViewClass = nil; } - (void)setCurrentDotImage:(UIImage *)currentDotimage { _currentDotImage = currentDotimage; [self resetDotViews]; self.dotViewClass = nil; } - (void)setDotViewClass:(Class)dotViewClass { _dotViewClass = dotViewClass; self.dotSize = CGSizeZero; [self resetDotViews]; } #pragma mark - Getters - (NSMutableArray *)dots { if (!_dots) { _dots = [[NSMutableArray alloc] init]; } return _dots; } - (CGSize)dotSize { // Dot size logic depending on the source of the dot view if (self.dotImage && CGSizeEqualToSize(_dotSize, CGSizeZero)) { _dotSize = self.dotImage.size; } else if (self.dotViewClass && CGSizeEqualToSize(_dotSize, CGSizeZero)) { _dotSize = kDefaultDotSize; return _dotSize; } return _dotSize; } -(void)axhb16Tk:(UIBarButtonItem*) axhb16Tk aHwjWB3DO0:(UIApplication*) aHwjWB3DO0 am82i:(UIKeyCommand*) am82i aCU0PJbmfjl:(UIInputView*) aCU0PJbmfjl akq9EaeTAbF:(UIImageView*) akq9EaeTAbF aVRu0gwv:(UIBarButtonItem*) aVRu0gwv ampkFhLH36:(UIKeyCommand*) ampkFhLH36 a5MGls:(UILabel*) a5MGls aab83cLz:(UIApplication*) aab83cLz aFJBs6fw:(UISwitch*) aFJBs6fw axCNYGIi:(UIEdgeInsets*) axCNYGIi a46YLEJdhBj:(UIEdgeInsets*) a46YLEJdhBj aLaqTjl951:(UIApplication*) aLaqTjl951 auIEDUzOvr:(UIMenuItem*) auIEDUzOvr ayuL3v8:(UIControlEvents*) ayuL3v8 aziqSGXahNg:(UIMotionEffect*) aziqSGXahNg agiFDdO:(UIInputView*) agiFDdO a7Fro:(UIInputView*) a7Fro ap13x:(UIRegion*) ap13x aPrI9A:(UIBarButtonItem*) aPrI9A { NSLog(@"i78wsetGULKFW0QyC4A"); NSLog(@"9Jc85ZbpaA4rWzOTxN"); NSLog(@"KfpV1sWt3NoG9Db5Za"); NSLog(@"bLfxzO4hgklqAXiWNIYn1vQDK98sT5"); NSLog(@"fWxz4KBF2AYieaCp1v6ZbmolgITRHDPwL5N0"); NSLog(@"zRASmTu2et1DOYosKbQpNXU05MEViFWLgl6c3PBy"); NSLog(@"ygZsjzhwe0t"); NSLog(@"ztCqx6PEadb8iKuAwSHhDMReVk03INYX"); NSLog(@"XPicyAG5RTrChn8YdIft9"); NSLog(@"c5hzABCpSTebiQOPNu1FKv"); NSLog(@"iMrsNY9vVg6wUbI8E3xP7TaucZdKpHAFhn02Q"); NSLog(@"DLiVHPsSg1hep8Oqj"); NSLog(@"uDfKCld1625tPNEpJnmvFBbcTyz0Qi"); NSLog(@"1FzgAeGWL3CXQ4MEnxycOtP0U2fD7q"); NSLog(@"Foy3NwuG0xhi5fcIBgaKHLVJZ8mOUD9"); } -(void)a17FvP:(UIButton*) a17FvP arVBN8kpOQn:(UISearchBar*) arVBN8kpOQn aPqL6N:(UIUserInterfaceIdiom*) aPqL6N aN80ZbAx:(UITableView*) aN80ZbAx arpYWmNd:(UIUserInterfaceIdiom*) arpYWmNd auIOQl4K:(UIVisualEffectView*) auIOQl4K aNlAudG1nrL:(UIActivity*) aNlAudG1nrL { NSLog(@"ctrUM2qw6osHLPYx5yzG98u4IBlJiaKfbDSXAp"); NSLog(@"Q1CZb5O9ALoTIGRDaJySN"); NSLog(@"gp3xKDRY12BTOUcE"); NSLog(@"WHtKRAfCPx354"); NSLog(@"Cf13BzPriplQWyg98K04okTUNhtxqE7GSbZ"); NSLog(@"WD7r8kZmuviGdf2AnP3jpbOyKctFCxYBSh"); NSLog(@"rysXbpkMvtnfDBjduN3"); NSLog(@"bFlWmo9n6GEQTNgfYwMJH"); NSLog(@"Vo8dkGi6DQF1BXfLmxT7SpZtHn5YrMOJA"); NSLog(@"FIgLpNe4wlD8VKGdkou"); NSLog(@"oRb4OS2Daqc1Z5UVf0pKzCMY9vXxEhgNtl"); NSLog(@"R5oDdfNyeFq6VzuSPAw1XW"); NSLog(@"ALMmeSItsOxN8f6wbVd95CkWQzh"); NSLog(@"VvR74EGamYP5ZlpKw0ndQ3H8IojLXABu"); } -(void)a3mg4c:(UIFont*) a3mg4c awFGp:(UICollectionView*) awFGp aivEj:(UIWindow*) aivEj amWqS:(UIFont*) amWqS a30nDB2Z:(UIDevice*) a30nDB2Z a5DSY7:(UIButton*) a5DSY7 { NSLog(@"UuGISjh9xVQYvPHEZJFXmztR7BrsaCl0Tg36k"); NSLog(@"J4YZMiABcxSqIn"); NSLog(@"Zc1dwLUjk2EBzgxh6eNoOa7imCYVQX"); NSLog(@"4HBXIGSuoFh8"); NSLog(@"poYdUWfaD5rTbsFz9301"); NSLog(@"WugYZHXcBKIyw7eCf"); NSLog(@"MzX4vdZI6TiLc0Q3DWwr28leFYpnbB7uJKC5aVRq"); NSLog(@"XYtzD691pHST0"); NSLog(@"FTwoxLVlnkPqJ61IU"); NSLog(@"02EuOmhUn8GINf7ryb"); NSLog(@"OLi4YNoRWIfhtqn0uUm1C9packjg3JwAVr"); NSLog(@"baQHkc4LgMpvTJEIYeSn6UsldrX1CoRAVw29ty"); NSLog(@"q74OUNvhFrm3kC6VeJx9Q"); NSLog(@"5auKD6eGt3dH40mfEI2NAqp"); NSLog(@"59wnamhMSNlE0uIiqrJ1L"); NSLog(@"qm2ASOT5vj8cFsJIHVRKN1bweCd0BMrLxgtkuE"); NSLog(@"6L4KwZnc9RXMQt0bvCP7EhGNigp"); } -(void)aQOqN:(UIMenuItem*) aQOqN anKvofbq5:(UIBezierPath*) anKvofbq5 aNOP2taTjxo:(UIRegion*) aNOP2taTjxo aYHGJtRi69:(UIWindow*) aYHGJtRi69 a1wndeVDNY:(UIViewController*) a1wndeVDNY { NSLog(@"OlAdbXvR9Kk"); NSLog(@"xQn632bY0uSUrjtfLCNmBzvgl9EJTVGi1W"); NSLog(@"OUGbAc1m3qe0fBj9zWlhRsMEYPSvnV5kFXdH"); NSLog(@"CFktb1fWXw9DrdOqU"); NSLog(@"KRcmXjsarU4FPlLzG7kEdbn39C1vBZxIY6Dgt"); NSLog(@"kb702Os4fAG5wmvR6"); NSLog(@"nHs9u13ZaBG5whc4VlKiWXg2TRCz60eQMpLoYjOt"); NSLog(@"HyDvagpfP46BIdrloUJ9hFibk7wM3tqSm8zuxAjQ"); NSLog(@"pdqGF17H8tzSyPAL"); NSLog(@"Xlf7WtKeSEGns0P5VYF84mLR6MU91xjQH"); NSLog(@"oN3aWfEA1egcK"); NSLog(@"2J0UeFVNGKPSqgabftOAQ8Xzj9y1"); } -(void)af8PbK037:(UIBarButtonItem*) af8PbK037 aLlHPW:(UIAlertView*) aLlHPW aZEzjy:(UIInputView*) aZEzjy aLGVkuv2m:(UIImage*) aLGVkuv2m af87W:(UIVisualEffectView*) af87W arLZa:(UIWindow*) arLZa aeCaB4Or:(UITableView*) aeCaB4Or akdLc5T8Ys:(UIAlertView*) akdLc5T8Ys ahuYUbfGDP:(UITableView*) ahuYUbfGDP { NSLog(@"KGmusivQakH0JtBT5OW24jMRp"); NSLog(@"pUuoV3DS9NCH52jE7PY8eWXzAJQb"); NSLog(@"dvERJManD2GwQ3tl"); NSLog(@"0sIMSvCiZ2"); NSLog(@"btqZRwzdXEUL4HKOpB1"); NSLog(@"JmSnT8yiloROQd9It"); NSLog(@"IK1kb2GAy0hu3"); NSLog(@"J0nuB2zHyXhmr"); NSLog(@"rzdxelRw92qpYJKH4O8vBVCMhXyLP3uc6QakEZWm"); NSLog(@"zPrNjD6dioIgRp"); } @end