123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- //
- // AHKActionSheet.m
- // AHKActionSheetExample
- //
- // Created by Arkadiusz on 08-04-14.
- // Copyright (c) 2014 Arkadiusz Holko. All rights reserved.
- //
- #import <QuartzCore/QuartzCore.h>
- #import "AHKActionSheet.h"
- #import "AHKActionSheetViewController.h"
- #import "UIImage+AHKAdditions.h"
- #import "UIWindow+AHKAdditions.h"
- static const NSTimeInterval kDefaultAnimationDuration = 0.5f;
- // Length of the range at which the blurred background is being hidden when the user scrolls the tableView to the top.
- static const CGFloat kBlurFadeRangeSize = 200.0f;
- static NSString * const kCellIdentifier = @"Cell";
- // How much user has to scroll beyond the top of the tableView for the view to dismiss automatically.
- static const CGFloat kAutoDismissOffset = 80.0f;
- // Offset at which there's a check if the user is flicking the tableView down.
- static const CGFloat kFlickDownHandlingOffset = 20.0f;
- static const CGFloat kFlickDownMinVelocity = 2000.0f;
- // How much free space to leave at the top (above the tableView's contents) when there's a lot of elements. It makes this control look similar to the UIActionSheet.
- static const CGFloat kTopSpaceMarginFraction = 0.0; //TWS 0.333f;
- // cancelButton's shadow height as the ratio to the cancelButton's height
- static const CGFloat kCancelButtonShadowHeightRatio = 0.333f;
- /// Used for storing button configuration.
- @interface AHKActionSheetItem : NSObject
- @property (copy, nonatomic) NSString *title;
- @property (strong, nonatomic) UIImage *image;
- @property (nonatomic) AHKActionSheetButtonType type;
- @property (strong, nonatomic) AHKActionSheetHandler handler;
- @end
- @implementation AHKActionSheetItem
- @end
- @interface AHKActionSheet() <UITableViewDataSource, UITableViewDelegate, UIGestureRecognizerDelegate>
- @property (strong, nonatomic) NSMutableArray *items;
- @property (weak, nonatomic, readwrite) UIWindow *previousKeyWindow;
- @property (strong, nonatomic) UIWindow *window;
- @property (weak, nonatomic) UIImageView *blurredBackgroundView;
- @property (weak, nonatomic) UITableView *tableView;
- @property (weak, nonatomic) UIButton *cancelButton;
- @property (weak, nonatomic) UIView *cancelButtonShadowView;
- @end
- @implementation AHKActionSheet
- #pragma mark - Init
- + (void)initialize
- {
- if (self != [AHKActionSheet class]) {
- return;
- }
- AHKActionSheet *appearance = [self appearance];
- [appearance setBlurRadius:16.0f];
- [appearance setBlurTintColor:[UIColor colorWithWhite:1.0f alpha:0.5f]];
- [appearance setBlurSaturationDeltaFactor:1.8f];
- [appearance setButtonHeight:60.0f];
- [appearance setCancelButtonHeight:44.0f];
- [appearance setAutomaticallyTintButtonImages:@YES];
- [appearance setSelectedBackgroundColor:[UIColor colorWithWhite:0.1f alpha:0.2f]];
- [appearance setCancelButtonTextAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:17.0f],
- NSForegroundColorAttributeName : [UIColor darkGrayColor] }];
- [appearance setButtonTextAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:17.0f]}];
- [appearance setDisabledButtonTextAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:14.0f],
- NSForegroundColorAttributeName : [UIColor colorWithWhite:0.6f alpha:1.0] }];
- [appearance setDestructiveButtonTextAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:17.0f],
- NSForegroundColorAttributeName : [UIColor redColor] }];
- [appearance setTitleTextAttributes:@{ NSFontAttributeName : [UIFont systemFontOfSize:14.0f],
- NSForegroundColorAttributeName : [UIColor grayColor] }];
- [appearance setCancelOnPanGestureEnabled:@(YES)];
- [appearance setCancelOnTapEmptyAreaEnabled:@(NO)];
- [appearance setAnimationDuration:kDefaultAnimationDuration];
- }
- - (instancetype)initWithTitle:(NSString *)title
- {
- self = [super init];
- if (self) {
- _title = [title copy];
- _cancelButtonTitle = @"Cancel";
- }
- return self;
- }
- - (instancetype)initWithView:(UIView *)view title:(NSString *)title
- {
- self = [super init];
-
- if (self) {
- _title = [title copy];
- _cancelButtonTitle = @"Cancel";
- _view = view;
- }
-
- return self;
- }
- - (instancetype)init
- {
- return [self initWithTitle:nil];
- }
- - (void)dealloc
- {
- self.tableView.dataSource = nil;
- self.tableView.delegate = nil;
- }
- #pragma mark - UITableViewDataSource
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- {
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- {
- return (NSInteger)[self.items count];
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath];
-
- //TWS
- cell.separatorInset = UIEdgeInsetsMake(0.f, 55.f, 0.f, 0.f);
- AHKActionSheetItem *item = self.items[(NSUInteger)indexPath.row];
- NSDictionary *attributes = nil;
- switch (item.type)
- {
- case AHKActionSheetButtonTypeDefault:
- attributes = self.buttonTextAttributes;
- break;
- case AHKActionSheetButtonTypeDisabled:
- attributes = self.disabledButtonTextAttributes;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- break;
- case AHKActionSheetButtonTypeDestructive:
- attributes = self.destructiveButtonTextAttributes;
- break;
- case AHKActionSheetButtonTypeCrypto:
- attributes = self.cryptoButtonTextAttributes;
- break;
- }
- NSAttributedString *attrTitle = [[NSAttributedString alloc] initWithString:item.title attributes:attributes];
- cell.textLabel.attributedText = attrTitle;
- cell.textLabel.textAlignment = [self.buttonTextCenteringEnabled boolValue] ? NSTextAlignmentCenter : NSTextAlignmentLeft;
- // Use image with template mode with color the same as the text (when enabled).
- BOOL useTemplateMode = [UIImage instancesRespondToSelector:@selector(imageWithRenderingMode:)] && [self.automaticallyTintButtonImages boolValue];
- cell.imageView.image = useTemplateMode ? [item.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] : item.image;
- if ([UIImageView instancesRespondToSelector:@selector(tintColor)]){
- cell.imageView.tintColor = attributes[NSForegroundColorAttributeName] ? attributes[NSForegroundColorAttributeName] : [UIColor blackColor];
- }
- //TWS
- cell.backgroundColor = [UIColor whiteColor];
- if (self.selectedBackgroundColor && ![cell.selectedBackgroundView.backgroundColor isEqual:self.selectedBackgroundColor]) {
- cell.selectedBackgroundView = [[UIView alloc] init];
- cell.selectedBackgroundView.backgroundColor = self.selectedBackgroundColor;
- }
- return cell;
- }
- #pragma mark - UITableViewDelegate
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- {
- AHKActionSheetItem *item = self.items[(NSUInteger)indexPath.row];
-
- if (item.type != AHKActionSheetButtonTypeDisabled) {
- [self dismissAnimated:YES duration:self.animationDuration completion:item.handler];
- }
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- {
- return self.buttonHeight;
- }
- //TWS
- /*
- -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
- {
- // Remove separator inset as described here: http://stackoverflow.com/a/25877725/783960
- if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
- [cell setSeparatorInset:UIEdgeInsetsZero];
- }
-
- // Prevent the cell from inheriting the Table View's margin settings
- if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
- [cell setPreservesSuperviewLayoutMargins:NO];
- }
-
- // Explictly set your cell's layout margins
- if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
- [cell setLayoutMargins:UIEdgeInsetsZero];
- }
- }
- */
- #pragma mark - UIScrollViewDelegate
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- if (![self.cancelOnPanGestureEnabled boolValue]) {
- return;
- }
- [self fadeBlursOnScrollToTop];
- }
- - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- {
- if (![self.cancelOnPanGestureEnabled boolValue]) {
- return;
- }
- CGPoint scrollVelocity = [scrollView.panGestureRecognizer velocityInView:self];
- BOOL viewWasFlickedDown = scrollVelocity.y > kFlickDownMinVelocity && scrollView.contentOffset.y < -self.tableView.contentInset.top - kFlickDownHandlingOffset;
- BOOL shouldSlideDown = scrollView.contentOffset.y < -self.tableView.contentInset.top - kAutoDismissOffset;
- if (viewWasFlickedDown) {
- // use a shorter duration for a flick down animation
- static const NSTimeInterval duration = 0.2f;
- [self dismissAnimated:YES duration:duration completion:self.cancelHandler];
- } else if (shouldSlideDown) {
- [self dismissAnimated:YES duration:self.animationDuration completion:self.cancelHandler];
- }
- }
- #pragma mark - Properties
- - (NSMutableArray *)items
- {
- if (!_items) {
- _items = [NSMutableArray array];
- }
- return _items;
- }
- #pragma mark - Actions
- - (void)cancelButtonTapped:(id)sender
- {
- [self dismissAnimated:YES duration:self.animationDuration completion:self.cancelHandler];
- }
- #pragma mark - Public
- - (void)addButtonWithTitle:(NSString *)title type:(AHKActionSheetButtonType)type handler:(AHKActionSheetHandler)handler
- {
- [self addButtonWithTitle:title image:nil type:type handler:handler];
- }
- - (void)addButtonWithTitle:(NSString *)title image:(UIImage *)image type:(AHKActionSheetButtonType)type handler:(AHKActionSheetHandler)handler
- {
- AHKActionSheetItem *item = [[AHKActionSheetItem alloc] init];
- item.title = title;
- item.image = image;
- item.type = type;
- item.handler = handler;
- [self.items addObject:item];
- }
- - (void)show
- {
- NSAssert([self.items count] > 0, @"Please add some buttons before calling -show.");
- if ([self isVisible]) {
- return;
- }
- self.previousKeyWindow = [UIApplication sharedApplication].keyWindow;
- UIImage *previousKeyWindowSnapshot = [self.previousKeyWindow ahk_snapshot];
- [self setUpNewWindow];
- [self setUpBlurredBackgroundWithSnapshot:previousKeyWindowSnapshot];
- [self setUpCancelButton];
- [self setUpTableView];
-
- if (self.cancelOnPanGestureEnabled.boolValue) {
- [self setUpCancelTapGestureForView:self.tableView];
- }
-
- CGFloat slideDownMinOffset = (CGFloat)fmin(CGRectGetHeight(self.frame) + self.tableView.contentOffset.y, CGRectGetHeight(self.frame));
- self.tableView.transform = CGAffineTransformMakeTranslation(0, slideDownMinOffset);
- void(^immediateAnimations)(void) = ^(void) {
- self.blurredBackgroundView.alpha = 1.0f;
- };
- void(^delayedAnimations)(void) = ^(void) {
- self.cancelButton.frame = CGRectMake(0,
- CGRectGetMaxY(self.bounds) - self.cancelButtonHeight,
- CGRectGetWidth(_view.bounds),
- self.cancelButtonHeight);
-
- //TWS
- self.cancelButton.backgroundColor = [UIColor whiteColor];
-
- self.tableView.transform = CGAffineTransformMakeTranslation(0, 0);
- // manual calculation of table's contentSize.height
- CGFloat tableContentHeight = [self.items count] * self.buttonHeight + CGRectGetHeight(self.tableView.tableHeaderView.frame);
- CGFloat topInset;
- BOOL buttonsFitInWithoutScrolling = tableContentHeight < CGRectGetHeight(self.tableView.frame) * (1.0 - kTopSpaceMarginFraction);
- if (buttonsFitInWithoutScrolling) {
- // show all buttons if there isn't many
- topInset = CGRectGetHeight(self.tableView.frame) - tableContentHeight;
- } else {
- // leave an empty space on the top to make the control look similar to UIActionSheet
- topInset = (CGFloat)round(CGRectGetHeight(self.tableView.frame) * kTopSpaceMarginFraction);
- }
-
- self.tableView.contentInset = UIEdgeInsetsMake(topInset, 0, 0, 0);
- self.tableView.bounces = [self.cancelOnPanGestureEnabled boolValue] || !buttonsFitInWithoutScrolling;
- };
- if ([UIView respondsToSelector:@selector(animateKeyframesWithDuration:delay:options:animations:completion:)]){
- // Animate sliding in tableView and cancel button with keyframe animation for a nicer effect.
- [UIView animateKeyframesWithDuration:self.animationDuration delay:0 options:0 animations:^{
- immediateAnimations();
- [UIView addKeyframeWithRelativeStartTime:0.3f relativeDuration:0.7f animations:^{
- delayedAnimations();
- }];
- } completion:nil];
- } else {
- [UIView animateWithDuration:self.animationDuration animations:^{
- immediateAnimations();
- delayedAnimations();
- }];
- }
- }
- - (void)dismissAnimated:(BOOL)animated
- {
- [self dismissAnimated:animated duration:self.animationDuration completion:self.cancelHandler];
- }
- #pragma mark - Private
- - (BOOL)isVisible
- {
- // action sheet is visible iff it's associated with a window
- return !!self.window;
- }
- - (void)dismissAnimated:(BOOL)animated duration:(NSTimeInterval)duration completion:(AHKActionSheetHandler)completionHandler
- {
- if (![self isVisible]) {
- return;
- }
- // delegate isn't needed anymore because tableView will be hidden (and we don't want delegate methods to be called now)
- self.tableView.delegate = nil;
- self.tableView.userInteractionEnabled = NO;
- // keep the table from scrolling back up
- self.tableView.contentInset = UIEdgeInsetsMake(-self.tableView.contentOffset.y, 0, 0, 0);
- void(^tearDownView)(void) = ^(void) {
- // remove the views because it's easiest to just recreate them if the action sheet is shown again
- for (UIView *view in @[self.tableView, self.cancelButton, self.blurredBackgroundView, self.window]) {
- [view removeFromSuperview];
- }
- self.window = nil;
- [self.previousKeyWindow makeKeyAndVisible];
- if (completionHandler) {
- completionHandler(self);
- }
- };
- if (animated) {
- // animate sliding down tableView and cancelButton.
- [UIView animateWithDuration:duration animations:^{
- self.blurredBackgroundView.alpha = 0.0f;
- self.cancelButton.transform = CGAffineTransformTranslate(self.cancelButton.transform, 0, self.cancelButtonHeight);
- self.cancelButtonShadowView.alpha = 0.0f;
- // Shortest shift of position sufficient to hide all tableView contents below the bottom margin.
- // contentInset isn't used here (unlike in -show) because it caused weird problems with animations in some cases.
- CGFloat slideDownMinOffset = (CGFloat)fmin(CGRectGetHeight(self.frame) + self.tableView.contentOffset.y, CGRectGetHeight(self.frame));
- self.tableView.transform = CGAffineTransformMakeTranslation(0, slideDownMinOffset);
- } completion:^(BOOL finished) {
- tearDownView();
- }];
- } else {
- tearDownView();
- }
- }
- - (void)setUpNewWindow
- {
- AHKActionSheetViewController *actionSheetVC = [[AHKActionSheetViewController alloc] initWithNibName:nil bundle:nil];
- actionSheetVC.actionSheet = self;
- self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
- self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- self.window.opaque = NO;
- self.window.rootViewController = actionSheetVC;
- [self.window makeKeyAndVisible];
- }
- - (void)setUpBlurredBackgroundWithSnapshot:(UIImage *)previousKeyWindowSnapshot
- {
- UIImage *blurredViewSnapshot = [previousKeyWindowSnapshot
- ahk_applyBlurWithRadius:self.blurRadius
- tintColor:self.blurTintColor
- saturationDeltaFactor:self.blurSaturationDeltaFactor
- maskImage:nil];
- UIImageView *backgroundView = [[UIImageView alloc] initWithImage:blurredViewSnapshot];
- backgroundView.frame = self.bounds;
- backgroundView.alpha = 0.0f;
- [self addSubview:backgroundView];
- self.blurredBackgroundView = backgroundView;
- }
- - (void)setUpCancelTapGestureForView:(UIView*)view {
- UITapGestureRecognizer *cancelTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cancelButtonTapped:)];
- cancelTap.delegate = self;
- [view addGestureRecognizer:cancelTap];
- }
- - (void)setUpCancelButton
- {
- UIButton *cancelButton;
- // It's hard to check if UIButtonTypeSystem enumeration exists, so we're checking existence of another method that was introduced in iOS 7.
- if ([UIView instancesRespondToSelector:@selector(tintAdjustmentMode)]) {
- cancelButton= [UIButton buttonWithType:UIButtonTypeSystem];
- } else {
- cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
- }
- NSAttributedString *attrTitle = [[NSAttributedString alloc] initWithString:self.cancelButtonTitle
- attributes:self.cancelButtonTextAttributes];
- [cancelButton setAttributedTitle:attrTitle forState:UIControlStateNormal];
- [cancelButton addTarget:self action:@selector(cancelButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
- cancelButton.frame = CGRectMake(0,
- CGRectGetMaxY(self.bounds) - self.cancelButtonHeight,
- CGRectGetWidth(self.bounds),
- self.cancelButtonHeight);
- // move the button below the screen (ready to be animated -show)
- cancelButton.transform = CGAffineTransformMakeTranslation(0, self.cancelButtonHeight);
- cancelButton.clipsToBounds = YES;
- [self addSubview:cancelButton];
- self.cancelButton = cancelButton;
- // add a small shadow/glow above the button
- if (self.cancelButtonShadowColor) {
- self.cancelButton.clipsToBounds = NO;
- CGFloat gradientHeight = (CGFloat)round(self.cancelButtonHeight * kCancelButtonShadowHeightRatio);
- UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, -gradientHeight, CGRectGetWidth(self.bounds), gradientHeight)];
- CAGradientLayer *gradient = [CAGradientLayer layer];
- gradient.frame = view.bounds;
- gradient.colors = @[ (id)[UIColor colorWithWhite:0.0 alpha:0.0].CGColor, (id)[self.blurTintColor colorWithAlphaComponent:0.1f].CGColor ];
- [view.layer insertSublayer:gradient atIndex:0];
- [self.cancelButton addSubview:view];
- self.cancelButtonShadowView = view;
- }
- }
- - (void)setUpTableView
- {
- CGRect statusBarViewRect = [self convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil];
- CGFloat statusBarHeight = CGRectGetHeight(statusBarViewRect);
- CGRect frame = CGRectMake(0,
- statusBarHeight,
- CGRectGetWidth(_view.bounds),
- CGRectGetHeight(self.bounds) - statusBarHeight - self.cancelButtonHeight);
- UITableView *tableView = [[UITableView alloc] initWithFrame:frame];
- tableView.backgroundColor = [UIColor clearColor];
- tableView.showsVerticalScrollIndicator = NO;
- if (self.separatorColor) {
- tableView.separatorColor = self.separatorColor;
- }
-
- tableView.delegate = self;
- tableView.dataSource = self;
- [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kCellIdentifier];
- [self insertSubview:tableView aboveSubview:self.blurredBackgroundView];
- // move the content below the screen, ready to be animated in -show
- tableView.contentInset = UIEdgeInsetsMake(CGRectGetHeight(self.bounds), 0, 0, 0);
- // removes separators below the footer (between empty cells)
- tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
- self.tableView = tableView;
- [self setUpTableViewHeader];
- }
- - (void)setUpTableViewHeader
- {
- if (self.title) {
- // paddings similar to those in the UITableViewCell
- static const CGFloat leftRightPadding = 15.0f;
- static const CGFloat topBottomPadding = 8.0f;
- CGFloat labelWidth = CGRectGetWidth(self.bounds) - 2*leftRightPadding;
- NSAttributedString *attrText = [[NSAttributedString alloc] initWithString:self.title attributes:self.titleTextAttributes];
- // create a label and calculate its size
- UILabel *label = [[UILabel alloc] init];
- label.numberOfLines = 0;
- [label setAttributedText:attrText];
- CGSize labelSize = [label sizeThatFits:CGSizeMake(labelWidth, MAXFLOAT)];
- label.frame = CGRectMake(leftRightPadding, topBottomPadding, labelWidth, labelSize.height);
- label.backgroundColor = [UIColor clearColor];
- // create and add a header consisting of the label
- UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), labelSize.height + 2*topBottomPadding)];
- [headerView addSubview:label];
-
- self.tableView.tableHeaderView = headerView;
-
- } else if (self.headerView) {
- self.tableView.tableHeaderView = self.headerView;
- }
- // add a separator between the tableHeaderView and a first row (technically at the bottom of the tableHeaderView)
- if (self.tableView.tableHeaderView && self.tableView.separatorStyle != UITableViewCellSeparatorStyleNone) {
- CGFloat separatorHeight = 1.0f / [UIScreen mainScreen].scale;
- CGRect separatorFrame = CGRectMake(0,
- CGRectGetHeight(self.tableView.tableHeaderView.frame) - separatorHeight,
- CGRectGetWidth(self.tableView.tableHeaderView.frame),
- separatorHeight);
-
- UIView *separator = [[UIView alloc] initWithFrame:separatorFrame];
- separator.backgroundColor = self.tableView.separatorColor;
-
- //TWS
- UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.tableView.tableHeaderView.frame), 1 / UIScreen.mainScreen.scale)];
- line.backgroundColor = self.tableView.separatorColor;
- [self.tableView.tableHeaderView addSubview:separator];
- [self.tableView.tableHeaderView addSubview:line];
- }
- }
- - (void)fadeBlursOnScrollToTop
- {
- if (self.tableView.isDragging || self.tableView.isDecelerating) {
- CGFloat alphaWithoutBounds = 1.0f - ( -(self.tableView.contentInset.top + self.tableView.contentOffset.y) / kBlurFadeRangeSize);
- // limit alpha to the interval [0, 1]
- CGFloat alpha = (CGFloat)fmax(fmin(alphaWithoutBounds, 1.0f), 0.0f);
- self.blurredBackgroundView.alpha = alpha;
- self.cancelButtonShadowView.alpha = alpha;
- }
- }
- - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
- // If the view that is touched is not the view associated with this view's table view, but
- // is one of the sub-views, we should not recognize the touch.
- // Original source: http://stackoverflow.com/questions/10755566/how-to-know-uitableview-is-pressed-when-empty
- if (touch.view != self.tableView && [touch.view isDescendantOfView:self.tableView]) {
- return NO;
- }
- return YES;
- }
- @end
|