iOS 首页标题支持展示图片点击展示lottie动画实现方案

现状:app首页标题只支持展示文字

需求

app首页标题支持展示图片,json 动画
如图
请添加图片描述
实现思路:将需要展示的资源包下载到沙盒中,在创建频道标题视图的时候,根据该频道在沙盒中是否有对应的图片、json资源来确定是否展示图片和动画,这里需要用到的技术点有,下载
解压资源包,展示沙盒中的json 动画文件,比较复杂的逻辑是
下载资源的展示,删除,更新逻辑,下面分别介绍

下载资源功能,资源展示逻辑

下载使用的是该下载功能组件
链接: link

资源包的展示逻辑

需求要保证的是,频道标题视图创建过之后,就不会在变化,
由于首页有编辑频道顺序功能,调整频道顺序的时候,是将原有的频道是图更新标题内容,这个过程中会重新从沙盒中获取资源,所以,我们就要保证,频道标题视图创建之后,沙盒中的内容就不再变化, 我这里创建了一个管理下载和使用资源逻辑的单例
代码如下

@implementation TPChannelHeadSourceManager

+ (instancetype)shareManager
{
    static TPChannelHeadSourceManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[TPChannelHeadSourceManager alloc] init];
        [manager inittialHeadSource];
    });
    return manager;
}

- (void)inittialHeadSource
{
    if ([[TPUserDefault instance].channelHeadSourceFlag isEqualToString:@"1"]) {
        //上次标记要删除资源包
        [self deleteChannelSource];
    } else if ([[TPUserDefault instance].channelHeadSourceFlag isEqualToString:@"2"]) {
        ///上次是在进入首页之后请求到资源的,需要更新资源路径
        [self updateChannelSource];
    }
    [TPUserDefault instance].channelHeadSourceFlag = @"";
}

- (BOOL)isHaveChannelSource
{
    //资源包下载好,暂时不更新资源包。(下次更新)
    if (isBlankString([TPUserDefault instance].channelHeadSourcePath)) {
        /*这里没有像皮肤的判断一样添加 ||[[TPUserDefault instance].channelHeadSourceFlag isEqualToString:@"2"]
         因为这个场景:我们创建频道名item的时候(肯定进入首页了) ,资源包下载还没有完成,这时候 [TPUserDefault instance].channelHeadSourceFlag = @"",
         我们是可以获取到资源包的,然后下载完成,这时候  [TPUserDefault instance].channelHeadSourceFlag = @"2" ,
         如果我们加了 [TPUserDefault instance].channelHeadSourceFlag = @"2" 这个判断条件,就会造成,我们调整频道顺序的时候, 判断为没有资源包,从而导致
         原来有资源包的item判断为没有资源包,从而导致有图片的item变为没有图片的
        */
        return NO;
    }else{
        return YES;
    }
}

- (void)updateChannelHeadSourceWithUrl:(NSString *)downloadUrl minVersion:(NSString *)minVersion
{
    if (isBlankString(downloadUrl) || [self isLessThanChannelHeaderSourceMinVersion:minVersion]) {
        //服务端无首页标题图片资源包,或者服务端控制的最低版本号比当前版本号大
        //如果已经进入了首页,则做个标记,下次启动的时候删除
        if (self.isComeMainPage) {
            [TPUserDefault instance].channelHeadSourceFlag = @"1";
        } else {
            //如果还没有进入首页,则直接删除
            [self deleteChannelSource];
        }
        return;
    }

    NSString *localfileName = downloadUrl.lastPathComponent;
    localfileName = [localfileName stringByReplacingOccurrencesOfString:@".zip" withString:@""];
    
    //判断是否更新标题资源包
    if ([[TPUserDefault instance].channelHeadSourceRemoteURL isEqualToString:downloadUrl]) {
        return;
    }
 
    FDownLoaderManager *manger = [[FDownLoaderManager alloc]init];
    [manger downLoader:[NSURL URLWithString:downloadUrl] downloadPath:kChannelHeadSourceCachePath tempPath:kChannelHeaderSourceTmpPath downLoadInfo:^(long long totalSize, NSHTTPURLResponse *response) {
        NSLog(@"下载信息:%lld",totalSize);
    } progress:^(float progress) {
        NSLog(@"下载进度:%f",progress);
    } success:^(NSString *cachePath) {
        NSLog(@"下载成功路径:%@",cachePath);
        //1.文件的存放
        NSString *fileName = cachePath;
        /// 临时文件路径
        ZipArchive *zipArch = [ZipArchive new];
        if ([zipArch UnzipOpenFile:fileName]) {
            NSString *path = [fileName stringByReplacingOccurrencesOfString:@".zip" withString:@""];
            BOOL unzipSuccess = [zipArch UnzipFileTo:path overWrite:YES];
            //删掉zip
             [FFileTool removeFile:fileName];
            if (!unzipSuccess) {
                [zipArch UnzipCloseFile];
            }else{
                //更新新的标题图片资源地址
                if (self.isComeMainPage) {
                    //走到这里说明是进入到首页之后才下载成功的,则标记为2
                    [TPUserDefault instance].channelHeadSourceFlag = @"2";
                    /*
                     这里之所以不更新channelHeadSourcePath ,而更新 toBeUsedHeadSourcePath,
                     是因为下面这个场景:
                    1 之前没有资源包 (本来就没有资源包,或者执行开始下载的时候,还没有进入到首页,资源包被删除了),2 有资源包,执行开始下载的时候,已经进入了首页,所以没有删除资源包),
                     但是下载还没有完成,在以上两种情况的时候创建了频道名item,这时候如果更新 channelHeadSourcePath,我们在调整频道顺序的时候,就会使用新的资源包,造成调整频道顺序前后展示的图片资源不同,
                     所以这里使用 toBeUsedHeadSourcePath 记录 资源包,在下次启动的时候使用
                     */
                    [TPUserDefault instance].toBeUsedHeadSourcePath = localfileName;
                } else {
                    /*
                     下载成功之后再删除资源包
                     如果已经进入首页,则不再删除
                     */
                    /*
                     我们调整频道顺序的时候,是需要重新用到资源包的
                     场景:  之前有资源包,执行到这里的时候,已经进入到首页了,频道名视图已经创建好了, 如果 不添加 !self.isComeMainPage 的判断
                     条件,将资源包删除了,我们调整频道顺序的时候,就会获取包不到资源包,造成有图片的item 在调整顺序之后,没有图片了,
                     所以这里添加了一个没有进入首页的判断
                     */
                    
                    [self deleteChanelSourceWhenDoloadSuccess];
                    
                    /*
                     如果下载结束的时候,还没有进入到首页,则直接 将路径赋值给 channelHeadSourcePath
                     使用新资源包
                     */
                    [TPUserDefault instance].channelHeadSourcePath = localfileName;
                }
                [TPUserDefault instance].channelHeadSourceRemoteURL = downloadUrl;
            }
        }else{
            //删掉zip
            [FFileTool removeFile:fileName];
        }
    } failed:^{
        NSLog(@"下载失败");

    }];
}

- (void)deleteChanelSourceWhenDoloadSuccess
{
    NSString *path = [NSString stringWithFormat:@"%@/%@",kChannelHeadSourceCachePath, [TPUserDefault instance].channelHeadSourcePath];
    if ([FFileTool fileExists:path]) {
        [FFileTool removeFile:path];
    }
}
-(void)deleteChannelSource{
    [FFileTool removeFile:kChannelHeadSourceCachePath];
    [TPUserDefault instance].channelHeadSourcePath = @"";
    [TPUserDefault instance].channelHeadSourceRemoteURL = @"";
}

- (void)updateChannelSource {
    ///这里一定要添加一个不为空的判断,否则如果为空,会导致 toBeUsedHeadSourcePath 目录下的资源也被删除,
    if (!isBlankString([TPUserDefault instance].channelHeadSourcePath) && ![[TPUserDefault instance].channelHeadSourcePath isEqualToString:[TPUserDefault instance].toBeUsedHeadSourcePath]) {
        /*
         这里删除要拼接上 [TPUserDefault instance].channelHeadSourcePath,
         如果不拼接,会将 toBeUsedHeadSourcePath目录下的资源文件删除
         */
        NSString *path = [NSString stringWithFormat:@"%@/%@",kChannelHeadSourceCachePath, [TPUserDefault instance].channelHeadSourcePath];
        if ([FFileTool fileExists:path]) {
            [FFileTool removeFile:path];
        }
    }
    [TPUserDefault instance].channelHeadSourcePath = [TPUserDefault instance].toBeUsedHeadSourcePath;
    [TPUserDefault instance].toBeUsedHeadSourcePath = @"";
}

@end

解压缩

下载好的资源如下图
iOS 首页标题支持展示图片点击展示lottie动画实现方案_第1张图片
将下载好的资源包解压缩,并删除压缩包
iOS 首页标题支持展示图片点击展示lottie动画实现方案_第2张图片
解压缩使用的工具 ZipArchive

展示沙盒中的json 动画和图片

使用如下代码展示沙盒中的json 文件(支持json文件使用图片资源)
[LOTAnimationView animationWithFilePath:jsonPath]

    NSString *jsonPath = [NSString stringWithFormat:@"%@/%@/%@_animation/animation.json",kChannelHeadSourceCachePath,[TPUserDefault instance].channelHeadSourcePath , self.itemDic[@"nodeId"]];
    
    if ([FFileTool fileExists:jsonPath]) {
        self.hasJsonAnimation = YES;
        self.animationView = [LOTAnimationView animationWithFilePath:jsonPath];
        
        [self addSubview:self.animationView];
        self.animationView.frame = CGRectMake(0, 0, width, 44 * rectScale());
    } else {
        self.hasImgSource = YES;
        [self addSubview:self.imgView];
        self.imgView.frame = CGRectMake(0, 0, width, 44 * rectScale());
        self.imgView.image = self.normalImg;
    }

这里要注意的一点,点击按钮(选中)的时候开始json 动画
调用 下面代码 [self.animationView playWithCompletion:^(BOOL animationFinished) {

        }];即可,动画结束的时候,

会自动停留在最后一帧动画

if (self.animationView.animationProgress == 0) {
//这里的 self.animationView.animationProgress == 0表示json 动画还没有开始,防止重复动画
	 [self.animationView playWithCompletion:^(BOOL animationFinished) {

            }];
    }

滑走未选中的时候,要展示json动画的第一帧动画
调用 [self.animationView stop];
即可

 [self.animationView stop];

你可能感兴趣的:(好的方案,UI,ios,objective-c,开发语言)