iOS开发之剖析"秘密"App内容页面效果

最近在玩"秘密",发现点击主界面的Cell进去后的页面效果不错,就写了个Demo来演示下.

它主要效果:下拉头部视图放大,上拉视图模糊而且到一定位置固定不动,其他Cell可以继续上移.

@封装的主要效果类:MTHeadEffect.m(.h文件省略,很简单的)

#import "MTHeadEffect.h"
#import <QuartzCore/QuartzCore.h>
#import <Accelerate/Accelerate.h>

// 屏幕的物理宽度
#define ScreenWidth  [UIScreen mainScreen].bounds.size.width
#define HeadViewH  40

CGFloat const kImageOriginHight = 200.f;

@implementation MTHeadEffect

+ (void)viewDidScroll:(UIScrollView *)tableView withHeadView:(UIImageView *)headView withBlur:(CGFloat)blur{

    NSLog(@"y = %f",tableView.contentOffset.y);
    if (tableView.contentOffset.y > kImageOriginHight - HeadViewH) {

        headView.frame = CGRectMake(0, -(kImageOriginHight - HeadViewH), ScreenWidth, kImageOriginHight);
        [[UIApplication sharedApplication].keyWindow addSubview:headView];

    }else if ((tableView.contentOffset.y < kImageOriginHight - HeadViewH) && tableView.contentOffset.y > 0){

        blur = (tableView.contentOffset.y) / 500.0 + 0.45;
        headView.image = [[UIImage imageNamed:@"2"] boxblurImageWithBlur:blur];
        headView.frame = CGRectMake(0, 0, ScreenWidth, kImageOriginHight);
        [tableView addSubview:headView];

    }else if (tableView.contentOffset.y <= 0){

        // 放大效果---x,y坐标的增量和宽度,高度的增量保持一致
        CGFloat offset  = -tableView.contentOffset.y;
        headView.frame = CGRectMake(-offset,-offset, ScreenWidth+ offset * 2, kImageOriginHight + offset);
        headView.image = [[UIImage imageNamed:@"2"] boxblurImageWithBlur:0.01];
    }

}

@end

@implementation UIImage (BlurEffect)

// 为高斯模糊效果封装的一个类目
-(UIImage *)boxblurImageWithBlur:(CGFloat)blur {

    NSData *imageData = UIImageJPEGRepresentation(self, 1); // convert to jpeg
    UIImage* destImage = [UIImage imageWithData:imageData];

    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 40);
    boxSize = boxSize - (boxSize % 2) + 1;

    CGImageRef img = destImage.CGImage;

    vImage_Buffer inBuffer, outBuffer;

    vImage_Error error;

    void *pixelBuffer;

    //create vImage_Buffer with data from CGImageRef

    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);

    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);

    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);

    //create vImage_Buffer for output

    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));

    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");

    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);

    // Create a third buffer for intermediate processing
    void *pixelBuffer2 = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
    vImage_Buffer outBuffer2;
    outBuffer2.data = pixelBuffer2;
    outBuffer2.width = CGImageGetWidth(img);
    outBuffer2.height = CGImageGetHeight(img);
    outBuffer2.rowBytes = 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(outBuffer.data,
                                             outBuffer.width,
                                             outBuffer.height,
                                             8,
                                             outBuffer.rowBytes,
                                             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

@main.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // tableView
    self.testTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) style:UITableViewStylePlain];
    self.testTableView.delegate = self;
    self.testTableView.dataSource = self;
    [self.view addSubview:_testTableView];

    /**
     *  隐藏状态栏效果
     *  1.系统提供了2种动画,一种是偏移,一种是渐隐
     *  2.在plist文件中将”View controller-based status bar appearance” 设置为 “No”
     */
    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

    // headView不作为tableHeadView,而是覆盖在第一个Cell上
    self.headView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
    self.headView.image = [[UIImage imageNamed:@"2"] boxblurImageWithBlur:0.01];
    self.headView.contentMode = UIViewContentModeScaleAspectFill;  //  图片展示全高度
    self.headView.clipsToBounds = YES;
    [self.testTableView addSubview:self.headView];

}

#pragma mark - scroll delegate 头部视图效果方法
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{

    [MTHeadEffect viewDidScroll:scrollView withHeadView:self.headView 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 (indexPath.row == 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];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"section = %ld row = %ld",indexPath.section,indexPath.row];
    return cell;

}

@效果图:额,不会制作gif动图,所以不太好演示,反正关键代码已经给出,大家可以自己去尝试.

iOS开发之剖析"秘密"App内容页面效果

时间: 2024-11-08 17:26:34

iOS开发之剖析"秘密"App内容页面效果的相关文章

iOS开发之剖析&quot;秘密&quot;App内容页面效果(二)

@前些天写了一篇"秘密"的Cell效果文章,但是与在工作中想要的效果还是有差距,而且扩展性很不好,于是重写封装,把整体视图都放到scrollView中,基本是和secret app 一模一样的效果了. @代码如下:(模糊效果的类就不写了,大家可以搜"UIImage+ImageEffects",还要导入Accelerate.framework) 1.MTSecretAppEffect.h #import <Foundation/Foundation.h>

iOS开发实用技巧—打包app发给测试人员测试

iOS开发实用技巧—打包app发给测试人员测试 说明:在项目开发过程中经常需要开发人员将项目打包成ipa包后,发给测试人员进行测试.本文贴图对打包的过程简单介绍. 一.Product ->archive (注意,不能是模拟器状态,如果当前调试状况是模拟器的话,则archive为灰色不可点击) 模拟器情况下: 剩余步骤: 选择 证书 生成ipa包 保存 注意:在打包的同时保存xcarchive文件,以备将来查看应用的crash日志.

ios开发 上传到App Store 时出错. iTunes Store Operation Failed, An Error occurred uploading to the iTunes store.

ios开发 上传到App Store 时出错. iTunes Store Operation Failed,    An Error occurred uploading to the iTunes store. 的解决方法,网上找了很多. 如下(当然没有解决我的问题,可以一试): 今天在提交app的时候,最后一步报错, An error occurred uploading to the iTunes Store! 后来上网查了查资料,在这里整理一下: 第一: 有可能是中文编码的问题,需要把编

iOS开发练习之UIPickerView实现歌词翻滚效果

麻雀虽小,五脏俱全.在平时的项目中,任何一个模块或者功能里其实都隐藏着许多我们平时注意不到的知识点,其实很多东西大家每天都在用,但很多时候都是知其然,而不知其所以然.时间久了,也就懒得去想到底是什么原因了,怎么实现的之类.回想自己的学习路程,也基本都这样混过来,实在愧对光阴,近日抽空,查看过往笔记,顺手写了个小代码练习,感觉温故知新.现分享代码,以供新手入门参考,尤其其中错误的部分也很有广泛性.同时也欢迎各路成精的老鸟们喷吐,能够指正,这样也促进我再进步一点. ViewController.m文

iOS开发实用技巧—项目新特性页面的处理

iOS开发实用技巧篇—项目新特性页面的处理 说明:本文主要说明在项目开发中会涉及到的最最简单的新特性界面(实用UIScrollView展示多张图片的轮播)的处理. 代码示例: 新建一个专门的处理新特性界面的控制器,可以实用代码也可以用xib,在这里实用纯代码方式,创建一个控制器NewfeatureViewController. 头文件代码: 1 // 2 // JMNewfeatureViewController.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 t

iOS开发之旅之App的生命周期

在iOS App中,入口函数并不在根目录下,而是在"Supporting Files"目录的main.m文件的main函数中.这很容易理解,C/C++都是以main为入口. int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 这个函数比较简单,只是调用了UI

iOS开发之资讯类App常用分类控件的封装与实现(CollectionView+Swift3.0+)

今天博客中,我们就来实现一下一些常用资讯类App中常用的分类选择的控件的封装.本篇博客中没有使用到什么新的技术点,如果非得说用到了什么新的技术点的话,那么勉强的说,用到了一些iOS9以后UICollectionView添加的一些新的特性.本篇博客所涉及的技术点主要有UICollectionView的Cell移动,手势识别,控件封装,闭包回调,面向接口编程,Swift中的泛型等等.这些技术点在之前的博客中也多次使用到,只不过本篇博客使用这些技术点来完成我们的具体需求. 一.实例运行效果 先入为主,

iOS开发关于真机—App发布证书和调试证书配置

发布证书.真机调试证书.测试证书.推送证书详细过程 更重要的是让你彻底明白为什么要这样配置证书 一:发布证书 遵旨:哪个开发者的哪台电脑要发布哪个app (这句话可以多读几遍) 通过上边的遵旨可以得出要发布app需要哪些文件,为什么配置过程中要上传或者生成那些文件,结论如下 申请开发者账号,即花费了99刀给apple的账号,这是你可以登录developer.apple.com这个网站了 证书签名请求文件(CSR:CertificateSigningRequest) 让你的电脑具备了发布app的功

iOS 开发笔记-获取某个APP素材

有时候,我们看到别人的APP做得挺漂亮的,那么我们想查看该APP的图片素材,要怎么弄呢? 一.下载一个iTools,安装,与手机链接.点击应用,选择我们要查看的APP,选择备份,保存到桌面. 二.回到桌面,解压该.ipa文件 三.解压后,我们选择Payload-->News-->显示包内容 四.这样我们就可以拿到我们想要的APP图片素材了.