13
13
14
14
static CGFloat const kPageControlHeight = 35 ;
15
15
static CGFloat const kSkipButtonWidth = 100 ;
16
- static CGFloat const kSkipButtonHeight = 44 ;
16
+ static CGFloat const kSkipButtonHeight = 35 ;
17
17
static CGFloat const kBackgroundMaskAlpha = 0.6 ;
18
18
static CGFloat const kDefaultBlurRadius = 20 ;
19
19
static CGFloat const kDefaultSaturationDeltaFactor = 1.8 ;
@@ -53,7 +53,7 @@ - (instancetype)initWithBackgroundImage:(UIImage *)backgroundImage contents:(NSA
53
53
}
54
54
55
55
self.backgroundImage = backgroundImage;
56
-
56
+
57
57
return self;
58
58
}
59
59
@@ -72,7 +72,7 @@ - (instancetype)initWithBackgroundVideoURL:(NSURL *)backgroundVideoURL contents:
72
72
}
73
73
74
74
self.videoURL = backgroundVideoURL;
75
-
75
+
76
76
return self;
77
77
}
78
78
@@ -85,21 +85,21 @@ - (instancetype)initWithContents:(NSArray *)contents {
85
85
if (!self) {
86
86
return nil ;
87
87
}
88
-
88
+
89
89
// Store the passed in view controllers array
90
90
self.viewControllers = contents;
91
-
91
+
92
92
// Set the default properties
93
93
self.shouldMaskBackground = YES ;
94
94
self.shouldBlurBackground = NO ;
95
95
self.shouldFadeTransitions = NO ;
96
96
self.fadePageControlOnLastPage = NO ;
97
97
self.fadeSkipButtonOnLastPage = NO ;
98
98
self.swipingEnabled = YES ;
99
-
99
+
100
100
self.allowSkipping = NO ;
101
101
self.skipHandler = ^{};
102
-
102
+
103
103
// Create the initial exposed components so they can be customized
104
104
self.pageControl = [UIPageControl new ];
105
105
self.pageControl .numberOfPages = self.viewControllers .count ;
@@ -109,7 +109,7 @@ - (instancetype)initWithContents:(NSArray *)contents {
109
109
[self .skipButton setTitle: kSkipButtonText forState: UIControlStateNormal];
110
110
[self .skipButton addTarget: self action: @selector (handleSkipButtonPressed ) forControlEvents: UIControlEventTouchUpInside];
111
111
self.skipButton .titleLabel .adjustsFontSizeToFitWidth = YES ;
112
-
112
+
113
113
return self;
114
114
}
115
115
@@ -120,14 +120,14 @@ - (void)viewDidLoad {
120
120
[super viewDidLoad ];
121
121
122
122
[[NSNotificationCenter defaultCenter ] addObserver: self selector: @selector (handleAppEnteredForeground ) name: UIApplicationDidBecomeActiveNotification object: nil ];
123
-
123
+
124
124
// now that the view has loaded, we can generate the content
125
125
[self generateView ];
126
126
}
127
127
128
128
- (void )viewWillAppear : (BOOL )animated {
129
129
[super viewWillAppear: animated];
130
-
130
+
131
131
// if we have a video URL, start playing
132
132
if (self.videoURL ) {
133
133
[self .player play ];
@@ -162,13 +162,13 @@ - (void)generateView {
162
162
self.pageVC .view .backgroundColor = [UIColor whiteColor ];
163
163
self.pageVC .delegate = self;
164
164
self.pageVC .dataSource = self.swipingEnabled ? self : nil ;
165
-
165
+
166
166
if (self.shouldBlurBackground ) {
167
167
[self blurBackground ];
168
168
}
169
-
169
+
170
170
UIImageView *backgroundImageView;
171
-
171
+
172
172
// create the background image view and set it to aspect fill so it isn't skewed
173
173
if (self.backgroundImage ) {
174
174
backgroundImageView = [[UIImageView alloc ] initWithFrame: self .view.bounds];
@@ -177,7 +177,7 @@ - (void)generateView {
177
177
[backgroundImageView setImage: self .backgroundImage];
178
178
[self .view addSubview: backgroundImageView];
179
179
}
180
-
180
+
181
181
// as long as the shouldMaskBackground setting hasn't been set to NO, we want to
182
182
// create a partially opaque view and add it on top of the image view, so that it
183
183
// darkens it a bit for better contrast
@@ -196,40 +196,40 @@ - (void)generateView {
196
196
197
197
// set the initial current page as the first page provided
198
198
_currentPage = [self .viewControllers firstObject ];
199
-
199
+
200
200
// more page controller setup
201
201
[self .pageVC setViewControllers: @[self .currentPage] direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: nil ];
202
202
self.pageVC .view .backgroundColor = [UIColor clearColor ];
203
203
[self addChildViewController: self .pageVC];
204
204
[self .view addSubview: self .pageVC.view];
205
205
[self .pageVC didMoveToParentViewController: self ];
206
206
[self .pageVC.view sendSubviewToBack: backgroundMaskView];
207
-
207
+
208
208
// send the background image view to the back if we have one
209
209
if (backgroundImageView) {
210
210
[self .pageVC.view sendSubviewToBack: backgroundImageView];
211
211
}
212
-
212
+
213
213
// otherwise send the video view to the back if we have one
214
214
else if (self.videoURL ) {
215
215
self.player = [[AVPlayer alloc ] initWithURL: self .videoURL];
216
216
217
217
self.moviePlayerController = [AVPlayerViewController new ];
218
218
self.moviePlayerController .player = self.player ;
219
219
self.moviePlayerController .showsPlaybackControls = NO ;
220
-
220
+
221
221
[self .pageVC.view addSubview: self .moviePlayerController.view];
222
222
[self .pageVC.view sendSubviewToBack: self .moviePlayerController.view];
223
223
}
224
-
224
+
225
225
// create the page control
226
226
[self .view addSubview: self .pageControl];
227
-
227
+
228
228
// if we allow skipping, setup the skip button
229
229
if (self.allowSkipping ) {
230
230
[self .view addSubview: self .skipButton];
231
231
}
232
-
232
+
233
233
// if we want to fade the transitions, we need to tap into the underlying scrollview
234
234
// so we can set ourself as the delegate, this is sort of hackish but the only current
235
235
// solution I am aware of using a page view controller
@@ -300,7 +300,7 @@ - (void)pageViewController:(UIPageViewController *)pageViewController didFinishA
300
300
if (!completed) {
301
301
return ;
302
302
}
303
-
303
+
304
304
// get the view controller we are moving towards, then get the index, then set it as the current page
305
305
// for the page control dots
306
306
UIViewController *viewController = [pageViewController.viewControllers lastObject ];
@@ -310,7 +310,7 @@ - (void)pageViewController:(UIPageViewController *)pageViewController didFinishA
310
310
311
311
- (void )moveNextPage {
312
312
NSUInteger indexOfNextPage = [self .viewControllers indexOfObject: _currentPage] + 1 ;
313
-
313
+
314
314
if (indexOfNextPage < self.viewControllers .count ) {
315
315
[self .pageVC setViewControllers: @[self .viewControllers[indexOfNextPage]] direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: nil ];
316
316
[self .pageControl setCurrentPage: indexOfNextPage];
@@ -336,7 +336,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
336
336
// scrollview's offset and the width of the screen
337
337
CGFloat percentComplete = fabs (scrollView.contentOffset .x - self.view .frame .size .width ) / self.view .frame .size .width ;
338
338
CGFloat percentCompleteInverse = 1.0 - percentComplete;
339
-
339
+
340
340
// these cases have some funky results given the way this method is called, like stuff
341
341
// just disappearing, so we want to do nothing in these cases
342
342
if (percentComplete == 0 ) {
@@ -346,15 +346,15 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
346
346
// set the next page's alpha to be the percent complete, so if we're 90% of the way
347
347
// scrolling towards the next page, its content's alpha should be 90%
348
348
[_upcomingPage updateAlphas: percentComplete];
349
-
349
+
350
350
// set the current page's alpha to the difference between 100% and this percent value,
351
351
// so we're 90% scrolling towards the next page, the current content's alpha sshould be 10%
352
352
[_currentPage updateAlphas: percentCompleteInverse];
353
353
354
354
// determine if we're transitioning to or from our last page
355
355
BOOL transitioningToLastPage = (_currentPage != self.viewControllers .lastObject && _upcomingPage == self.viewControllers .lastObject );
356
356
BOOL transitioningFromLastPage = (_currentPage == self.viewControllers .lastObject ) && (_upcomingPage == self.viewControllers [self .viewControllers.count - 2 ]);
357
-
357
+
358
358
// fade the page control to and from the last page
359
359
if (self.fadePageControlOnLastPage ) {
360
360
if (transitioningToLastPage) {
@@ -391,13 +391,13 @@ - (void)blurBackground {
391
391
NSLog (@" *** error: image must be backed by a CGImage: %@ " , self.backgroundImage );
392
392
return ;
393
393
}
394
-
394
+
395
395
UIColor *tintColor = [UIColor colorWithWhite: 0.7 alpha: 0.3 ];
396
396
CGFloat blurRadius = kDefaultBlurRadius ;
397
397
CGFloat saturationDeltaFactor = kDefaultSaturationDeltaFactor ;
398
398
CGRect imageRect = { CGPointZero, self.backgroundImage .size };
399
399
UIImage *effectImage = self.backgroundImage ;
400
-
400
+
401
401
BOOL hasBlur = blurRadius > __FLT_EPSILON__;
402
402
BOOL hasSaturationChange = fabs (saturationDeltaFactor - 1 .) > __FLT_EPSILON__;
403
403
if (hasBlur || hasSaturationChange) {
@@ -406,21 +406,21 @@ - (void)blurBackground {
406
406
CGContextScaleCTM (effectInContext, 1.0 , -1.0 );
407
407
CGContextTranslateCTM (effectInContext, 0 , -self.backgroundImage .size .height );
408
408
CGContextDrawImage (effectInContext, imageRect, self.backgroundImage .CGImage );
409
-
409
+
410
410
vImage_Buffer effectInBuffer;
411
411
effectInBuffer.data = CGBitmapContextGetData (effectInContext);
412
412
effectInBuffer.width = CGBitmapContextGetWidth (effectInContext);
413
413
effectInBuffer.height = CGBitmapContextGetHeight (effectInContext);
414
414
effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow (effectInContext);
415
-
415
+
416
416
UIGraphicsBeginImageContextWithOptions (self.backgroundImage .size , NO , [[UIScreen mainScreen ] scale ]);
417
417
CGContextRef effectOutContext = UIGraphicsGetCurrentContext ();
418
418
vImage_Buffer effectOutBuffer;
419
419
effectOutBuffer.data = CGBitmapContextGetData (effectOutContext);
420
420
effectOutBuffer.width = CGBitmapContextGetWidth (effectOutContext);
421
421
effectOutBuffer.height = CGBitmapContextGetHeight (effectOutContext);
422
422
effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow (effectOutContext);
423
-
423
+
424
424
if (hasBlur) {
425
425
// A description of how to compute the box kernel width from the Gaussian
426
426
// radius (aka standard deviation) appears in the SVG spec:
@@ -469,40 +469,40 @@ - (void)blurBackground {
469
469
if (!effectImageBuffersAreSwapped)
470
470
effectImage = UIGraphicsGetImageFromCurrentImageContext ();
471
471
UIGraphicsEndImageContext ();
472
-
472
+
473
473
if (effectImageBuffersAreSwapped)
474
474
effectImage = UIGraphicsGetImageFromCurrentImageContext ();
475
475
UIGraphicsEndImageContext ();
476
476
}
477
-
477
+
478
478
// Set up output context.
479
479
UIGraphicsBeginImageContextWithOptions (self.backgroundImage .size , NO , [[UIScreen mainScreen ] scale ]);
480
480
CGContextRef outputContext = UIGraphicsGetCurrentContext ();
481
481
CGContextScaleCTM (outputContext, 1.0 , -1.0 );
482
482
CGContextTranslateCTM (outputContext, 0 , -self.backgroundImage .size .height );
483
-
483
+
484
484
// Draw base image.
485
485
CGContextDrawImage (outputContext, imageRect, self.backgroundImage .CGImage );
486
-
486
+
487
487
// Draw effect image.
488
488
if (hasBlur) {
489
489
CGContextSaveGState (outputContext);
490
490
CGContextDrawImage (outputContext, imageRect, effectImage.CGImage );
491
491
CGContextRestoreGState (outputContext);
492
492
}
493
-
493
+
494
494
// Add in color tint.
495
495
if (tintColor) {
496
496
CGContextSaveGState (outputContext);
497
497
CGContextSetFillColorWithColor (outputContext, tintColor.CGColor );
498
498
CGContextFillRect (outputContext, imageRect);
499
499
CGContextRestoreGState (outputContext);
500
500
}
501
-
501
+
502
502
// Output image is ready.
503
503
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext ();
504
504
UIGraphicsEndImageContext ();
505
-
505
+
506
506
self.backgroundImage = outputImage;
507
507
}
508
508
0 commit comments