Put the overall view of the "secret" Cell effect into the scrollView, which is basically the same as the secret app.
The code is as follows: (I won’t write a class with fuzzy effects. You can search for "UIImage+ImageEffects" and import it.)
#import <Foundation/>
@interface MTSecretAppEffect : NSObject
/**
* Create a whole scrollView, load all the headScrollView and tableView on it, and slide up and down, and all the other slides are prohibited
*
* @return mainScrollView
*/
- (UIScrollView *)createMainScrollView;
/**
* Create headScrollView
*
* @return headScrollView
*/
- (UIScrollView *)createHeadScrollView;
/**
* Create a blurred view of the head
*
* @param scrollview headScrollView
*
* @return blurImageView
*/
- (UIImageView *)createBlurImageViewOfView:(UIScrollView *)scrollview;
/**
* Methods called in - (void)scrollViewDidScroll:(UIScrollView *)scrollView
*
* @param scrollView
* @param mainScrollView
* @param tableView
* @param headScrollView
* @param blurImageView
*/
- (void)scrollDidScrollView:(UIScrollView *)scrollView withMainScrollView:(UIScrollView *)mainScrollView withTableView:(UITableView *)tableView withHeadScrollView:(UIScrollView *)headScrollView withBlurImageView:(UIImageView *)blurImageView;
@end
#import ""
#import "UIImage+"
#import <QuartzCore/>
#define HEADER_HEIGHT 200.0f
#define HEADER_INIT_FRAME CGRectMake(0, 0, 320, HEADER_HEIGHT)
const CGFloat kBarHeight = 50.0f;
const CGFloat kBackgroundParallexFactor = 0.5f;
const CGFloat kBlurFadeInFactor = 0.015f;
@implementation MTSecretAppEffect
// Deficiency: The caller sets up a proxy
- (UIScrollView *)createMainScrollView{
// Bottom ScrollView of the same size
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:[UIApplication sharedApplication].];
= YES;
= YES;
= CGSizeZero;
= YES;
= UIEdgeInsetsMake(50.0f, 0, 0, 0);
return mainScrollView;
}
- (UIScrollView *)createHeadScrollView{
UIScrollView *headScrollView = [[UIScrollView alloc] initWithFrame:HEADER_INIT_FRAME];
= NO;
= CGSizeMake(320, 1000);
return headScrollView;
}
- (UIImageView *)createBlurImageViewOfView:(UIScrollView *)scrollview{
UIGraphicsBeginImageContextWithOptions(, , 0.0);
[ renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *blurImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, HEADER_HEIGHT)];
= [img applyBlurWithRadius:12 tintColor:[UIColor colorWithWhite:0.8 alpha:0.4] saturationDeltaFactor:1.8 maskImage:nil];
= UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
= 0;
= [UIColor clearColor];
return blurImageView;
}
- (void)scrollDidScrollView:(UIScrollView *)scrollView withMainScrollView:(UIScrollView *)mainScrollView withTableView:(UITableView *)tableView withHeadScrollView:(UIScrollView *)headScrollView withBlurImageView:(UIImageView *)blurImageView{
CGFloat y = 0.0f;
CGRect rect = HEADER_INIT_FRAME;
if ( < 0.0f) {
// Pull down to increase the effect
y = fabs(MIN(0.0f, ));
= CGRectMake(CGRectGetMinX(rect) - y / 2.0f, CGRectGetMinY(rect) - y, CGRectGetWidth(rect) + y, CGRectGetHeight(rect) + y);
}
else {
y = ;
= MIN(1 , y * kBlurFadeInFactor);
CGFloat backgroundScrollViewLimit = - kBarHeight;
if (y > backgroundScrollViewLimit) {
= (CGRect) {.origin = {0, y - + kBarHeight}, .size = {320, HEADER_HEIGHT}};
= (CGRect){.origin = {0, CGRectGetMinY() + CGRectGetHeight()}, .size = };
= CGPointMake (0, y - backgroundScrollViewLimit);
CGFloat contentOffsetY = -backgroundScrollViewLimit * kBackgroundParallexFactor;
[headScrollView setContentOffset:(CGPoint){0,contentOffsetY} animated:NO];
}
else {
= rect;
= (CGRect){.origin = {0, CGRectGetMinY(rect) + CGRectGetHeight(rect)}, .size = };
[tableView setContentOffset:(CGPoint){0,0} animated:NO];
[headScrollView setContentOffset:CGPointMake(0, -y * kBackgroundParallexFactor)animated:NO];
}
}
}
@end
#import ""
#import ""
#import ""
#define HEADER_HEIGHT 200.0f
@interface RootViewController () <UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate>
@property (nonatomic,strong) MTSecretAppEffect *secretEffect; // secretApp effect object
@property (nonatomic,strong) UIScrollView *mainScrollView; // ScrollView of the same size as the view
@property (nonatomic,strong) UIScrollView *headScrollView; //
@property (nonatomic,strong) UIImageView *blurImageView; //
@property (nonatomic,strong) UITableView *tableView; //
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 0. Create SecretApp effect object
= [[MTSecretAppEffect alloc] init];
// 1. Main bottom scrollView
= [ createMainScrollView];
= self;
= ;
// Background View
= [ createHeadScrollView];
// 3. Background picture view
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, HEADER_HEIGHT)];
= [UIImage imageNamed:@""];
= UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[ addSubview:imageView];
// 4. Blur view
_blurImageView = [ createBlurImageViewOfView:];
[ addSubview:_blurImageView];
//
= [[UITableView alloc] initWithFrame:CGRectMake(0, HEADER_HEIGHT, CGRectGetWidth(), CGRectGetHeight() - 50 ) style:UITableViewStylePlain];
= NO;
= self;
= self;
= [[UIView alloc] initWithFrame:CGRectZero];
= [UIColor clearColor];
// 6. Add a view
[ addSubview:];
[ addSubview:];
// 7. Set it up
= CGSizeMake(320, + CGRectGetHeight());
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 8. Calling method
[ scrollDidScrollView:scrollView withMainScrollView: withTableView: withHeadScrollView: withBlurImageView:];
}
#pragma mark - Hide status bar
- (BOOL)prefersStatusBarHidden {
return YES;
}
#pragma mark - UITableView dataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"Cell %ld", ]];
if (!cell) {
cell = [[CommentCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:@"Cell %ld", ]];
}
= [NSString stringWithFormat:@"section = %ld row = %ld",,];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Reproduction picture:
PPPPPPPPPPPPPPPPPPPPPP1
Its main effect: the head view of the pull-down is enlarged, the pull-up view is blurred and fixed to a certain position, and other cells can continue to move upward.
The main effect of encapsulation: (.h file is omitted, very simple)
#import ""
#import <QuartzCore/>
#import <Accelerate/>
// The physical width of the screen
#define ScreenWidth [UIScreen mainScreen].
#define HeadViewH 40
CGFloat const kImageOriginHight = ;
@implementation MTHeadEffect
+ (void)viewDidScroll:(UIScrollView *)tableView withHeadView:(UIImageView *)headView withBlur:(CGFloat)blur{
NSLog(@"y = %f",);
if ( > kImageOriginHight - HeadViewH) {
= CGRectMake(0, -(kImageOriginHight - HeadViewH), ScreenWidth, kImageOriginHight);
[[UIApplication sharedApplication].keyWindow addSubview:headView];
}else if (( < kImageOriginHight - HeadViewH) && > 0){
blur = () / 500.0 + 0.45;
= [[UIImage imageNamed:@"2"] boxblurImageWithBlur:blur];
= CGRectMake(0, 0, ScreenWidth, kImageOriginHight);
[tableView addSubview:headView];
}else if ( <= 0){
// Zoom effect --- the increments of x,y coordinates and width and height are consistent
CGFloat offset = -;
= CGRectMake(-offset,-offset, ScreenWidth+ offset * 2, kImageOriginHight + offset);
= [[UIImage imageNamed:@"2"] boxblurImageWithBlur:0.01];
}
}
@end
@implementation UIImage (BlurEffect)
// A category for Gaussian blur effect encapsulation
-(UIImage *)boxblurImageWithBlur:(CGFloat)blur {
NSData *imageData = UIImageJPEGRepresentation(self, 1); // convert to jpeg
UIImage* destImage = [UIImage imageWithData:imageData];
if (blur < || blur > ) {
blur = 0.5f;
}
int boxSize = (int)(blur * 40);
boxSize = boxSize - (boxSize % 2) + 1;
CGImageRef img = ;
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
voidvoid *pixelBuffer;
//create vImage_Buffer with data from CGImageRef
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
= CGImageGetWidth(img);
= CGImageGetHeight(img);
= CGImageGetBytesPerRow(img);
= (void*)CFDataGetBytePtr(inBitmapData);
//create vImage_Buffer for output
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
if(pixelBuffer == NULL)
NSLog(@"No pixelbuffer");
= pixelBuffer;
= CGImageGetWidth(img);
= CGImageGetHeight(img);
= CGImageGetBytesPerRow(img);
// Create a third buffer for intermediate processing
voidvoid *pixelBuffer2 = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
vImage_Buffer outBuffer2;
= pixelBuffer2;
= CGImageGetWidth(img);
= CGImageGetHeight(img);
= CGImageGetBytesPerRow(img);
//perform convolution
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
error = vImageBoxConvolve_ARGB8888(&outBuffer2, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(,
,
,
8,
,
colorSpace,
(CGBitmapInfo)kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
//clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
free(pixelBuffer2);
CFRelease(inBitmapData);
CGImageRelease(imageRef);
return returnImage;
}
@end
@
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// tableView
= [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) style:UITableViewStylePlain];
= self;
= self;
[ addSubview:_testTableView];
/**
* Hide status bar effect
* 1. The system provides two types of animations, one is offset and the other is fading
* 2. Set "View controller-based status bar appearance" to "No" in the plist file
*/
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
// The headView is not used as a tableHeadView, but is overlaid on the first cell.
= [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
= [[UIImage imageNamed:@"2"] boxblurImageWithBlur:0.01];
= UIViewContentModeScaleAspectFill; // Full height of picture display
= YES;
[ addSubview:];
}
#pragma mark - scroll delegate head view effect method
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[MTHeadEffect viewDidScroll:scrollView withHeadView: withBlur:0.01];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 25;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if ( == 0) {
return 200;
}
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentf = @"cell";
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:cellIdentf];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentf];
}
= [NSString stringWithFormat:@"section = %ld row = %ld",,];
return cell;
}
Reproduction: Well, I can't make gif animations, so it's not easy to demonstrate. Anyway, the key code has been given, so everyone can try it yourself.
Key code for third-party FXBlurView practices:
- (void)createBlurView{
= [[FXBlurView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, kOriginHight)];
= [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
= 1.0;
= YES;
= 0.0;
= UIViewContentModeBottom;
}
#pragma mark - scroll delegate head view effect method
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ( > 0) {
= 1.0;
= / 4.0;
}
if ( == 0) {
= 0.0;
}
if ( < 0) {
CGFloat offset = - ;
= 0.0;
NSArray *indexPathArray = [ indexPathsForVisibleRows];
HMTBlurTableViewCell *blurCell = (HMTBlurTableViewCell *)[ cellForRowAtIndexPath:[indexPathArray objectAtIndex:0]];
= CGRectMake(-offset, -offset, ScreenWidth + offset * 2, kOriginHight + offset);
}
}