视频+图片混合浏览器

闲暇时做的一个可以浏览图片以及视频的框架。效果图如下:


Untitled5.gif

基本功能

  • 视频和图片(含GIF)的混合浏览。
  • 支持屏幕旋转,横屏浏览。
  • 支持双击放大图片、拖曳退出浏览等多种手势操作。

说明:本项目是在GKPhotoBrowser基础上修改及扩展的,GKPhotoBrowser是一款支持图片浏览的图片浏览器,本项目新增了视频播放的功能,播放器修改自SBPlayer。此外,本项目保留了GKPhotoBrowser的原有功能。

如何使用

具体方法详见下载的demo。其他功能或样式可参考GKPhotoBrowser原项目的说明。

下载地址

https://github.com/imsz5460/SZPhotoVideoBrowser

核心代码

*图片的复用机制:

简单来说,会预先加载3张紧邻的图片,比如现在屏幕显示的是第2张图,则第1张与第3张也一并加载了,这3张图放在_visiblePhotoViews数组,这样用户左滑右滑都能有较好的体验。_visiblePhotoViews是随着显示图片的变化而更新的,当新的图片加进来,则有原图片从这个数组移除,并把移除的图片放到缓存池。这样下次加载图片时首先去缓存池中获取,如果没有才重新创建新图片。同时,如果需要展示的是视频,则在图片上直接加载视频view。具体可参看代码实现。

//在scrollview监听滚动的代理方法中设置图片
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (self.isRotation) return;
    [self updateReusableViews];
    [self setupPhotoViews];
}
- (void)updateReusableViews {
    NSMutableArray *viewsForRemove = [NSMutableArray new];
    for (GKPhotoView *photoView in _visiblePhotoViews) {
        if ((photoView.frame.origin.x + photoView.frame.size.width < self.photoScrollView.contentOffset.x - self.photoScrollView.frame.size.width) || (photoView.frame.origin.x > self.photoScrollView.contentOffset.x + 2 * self.photoScrollView.frame.size.width)) {
        
            [photoView._playerView stop];
           
            [photoView removeFromSuperview];
            GKPhoto *photo = nil;
            [photoView setupPhoto:photo];
            [viewsForRemove addObject:photoView];
            [_reusablePhotoViews addObject:photoView];
        }
    }
    [_visiblePhotoViews removeObjectsInArray:viewsForRemove];
}
- (void)setupPhotoViews {
    CGFloat index2 = self.photoScrollView.contentOffset.x / self.photoScrollView.frame.size.width;
    NSInteger index = index2 + 0.5;
    NSInteger i  = index2;
    for (NSInteger i = index - 1; i <= index + 1; i++) {
        if (i < 0 || i >= self.photos.count) {
            continue;
        }
        GKPhotoView *photoView = [self photoViewForIndex:i];
        if (photoView == nil) {
            photoView               = [self dequeueReusablePhotoView];
            CGRect frame            = self.photoScrollView.bounds;
            
            CGFloat photoScrollW    = frame.size.width;
            CGFloat photoScrollH    = frame.size.height;
            // 调整当前显示的photoView的frame
            CGFloat w = photoScrollW - kPhotoViewPadding * 2;
            CGFloat h = photoScrollH;
            CGFloat x = kPhotoViewPadding + i * (kPhotoViewPadding * 2 + w);
            CGFloat y = 0;

            photoView.frame = CGRectMake(x, y, w, h);
            photoView.tag   = i;
            [self.photoScrollView addSubview:photoView];
            
            GKPhoto *photo = self.photos[i];
            if (photo.isVideo) {
                [photoView addSubview: photoView.playerView];
                photoView.clipsToBounds = YES;//防止上次的横屏挡住旁边的view
            }
           
            [_visiblePhotoViews addObject:photoView];
            [photoView resetFrame];
        }
        if (photoView.photo == nil && self.isShow) {
            [photoView setupPhoto:self.photos[i]];
        }
    }
 
        if (index2 == i) {
            if (preindex != index2) {
                [_playerView pause];
                preindex = i;
                [self currentPlayViewPlay:i];
            }
        }

    // 更换photoView
    if (index != self.currentIndex && self.isShow && (index >= 0 && index < self.photos.count)) {
        self.currentIndex = index;
        
        GKPhotoView *photoView = [self currentPhotoView];
        if (photoView.scrollView.zoomScale > 1.0 ) {
            [self removePanGesture];
        }else {
            [self addPanGesture:NO];
        }
        [self updateLabel];
        
        if ([self.delegate respondsToSelector:@selector(photoBrowser:didChangedIndex:)]) {
            [self.delegate photoBrowser:self didChangedIndex:self.currentIndex];
        }
    }
}
// 重用页面
- (GKPhotoView *)dequeueReusablePhotoView {
    GKPhotoView *photoView = [self.reusablePhotoViews anyObject];
    if (photoView) {
       
        [photoView._playerView stop];
       
        [_reusablePhotoViews removeObject:photoView];
    }else {
        photoView = [[GKPhotoView alloc] initWithFrame:self.photoScrollView.bounds imageProtocol:_imageProtocol];
    }
    photoView.tag =  -1;
    return photoView;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容