V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
CoderKo1o
V2EX  ›  分享创造

iOS 高仿 QQ、微信效果的图片浏览器(支持原图和缩略图、多种手势、CocoaPods)

  •  
  •   CoderKo1o ·
    iphone5solo · 2016-10-11 10:14:17 +08:00 · 3503 次点击
    这是一个创建于 2757 天前的主题,其中的信息可能已经有所发展或是发生改变。

    PYPhotoBrowser (star 800+)

    GitHub地址:https://github.com/iphone5solo/PYPhotoBrowser

    Build Status Pod Version Pod Platform Pod License

    • Framework with a simple method of rendering images.
    • 用法简单的呈现一组图片的框架。

    效果图

    • 图片已发布(网络图片浏览、流水布局)

      (img)

    • 图片未发布(本地图片上传\发布\预览)

      (img)

    哪些 app 使用 PYPhotoBrowser (陆续更新)

    香脉 汕医移动办公

    支持哪些状态

    • 已发布(网络图片浏览)

    (img)

    • 未发布(本地图片上传\发布\预览)

      (img)

    支持哪些布局

    • 流水布局线性布局

    支持哪些手势

    • 单击双击捏合旋转拖拽侧滑

    什么地方用到这个框架

    • 主要用于社交 app,用于呈现一组图片
    • 以下是各个流行社交 app 的部分截图

    (img1) (img1) (img1) (img1) (img1) (img1)

    依赖哪些第三方框架

    • 图片浏览依赖框架
      • MBProgressHUD
      • SDWebImage
      • DACircularProgress

    PYPhotoBrowser 框架的主要类

    PYPhotosView (快速使用)

    
    
    @interface PYPhotosView : UIScrollView
    
    /** 代理 */
    @property (nonatomic, weak) id<PYPhotosViewDelegate> delegate;
    
    /** 网络图片模型数组 */
    @property (nonatomic, copy) NSArray *photos;
    /** 网络图片地址数组(缩略图) */
    @property (nonatomic, copy) NSArray *thumbnailUrls;
    /** 网络图片地址数组(原图) */
    @property (nonatomic, copy) NSArray *originalUrls;
    /** 本地相册图片数组(默认最多为九张,当传入图片数组长度超过九张时,取前九张) */
    @property (nonatomic, strong) NSMutableArray *images;
    
    /** 所有图片的状态(默认为已发布状态) */
    @property (nonatomic, assign) PYPhotosViewState photosState;
    /** 图片布局(默认为流水布局) */
    @property (nonatomic, assign) PYPhotosViewLayoutType layoutType;
    /** 图片分页指示类型(默认为 pageControll 。当图片超过九张,改为 label 显示) */
    @property (nonatomic, assign) PYPhotosViewPageType pageType;
    
    /** 图片间距(默认为 5 ) */
    @property (nonatomic, assign) CGFloat photoMargin;
    /** 图片的宽 (默认为 70) */
    @property (nonatomic, assign) CGFloat photoWidth;
    /** 图片的高 (默认为 70) */
    @property (nonatomic, assign) CGFloat photoHeight;
    
    /** 每行最多个数(默认为 3 ), 当图片布局为线性布局时,此设置失效 */
    @property (nonatomic, assign) NSInteger photosMaxCol;
    /** 当图片上传前,最多上传的张数,默认为 9 */
    @property (nonatomic, assign) NSInteger imagesMaxCountWhenWillCompose;
    
    /** 快速创建 photosView 对象 */
    + (instancetype)photosView;
    /** photos : 保存图片链接的数组 */
    + (instancetype)photosViewWithThumbnailUrls:(NSArray *)thumbnailUrls originalUrls:(NSArray *)originalUrls;
    /** images : 存储本地图片的数组 */
    + (instancetype)photosViewWithImages:(NSMutableArray *)images;
    
    /**
     * thumbnailUrls : 保存图片(缩略图)链接的数组
     * originalUrls : 保存图片(原图)链接的数组
     * type : 布局类型(默认为流水布局)
     */
    + (instancetype)photosViewWithThumbnailUrls:(NSArray *)thumbnailUrls originalUrls:(NSArray *)originalUrls layoutType:(PYPhotosViewLayoutType)type;
    
    /** 
     * thumbnailUrls : 保存图片(缩略图)链接的数组
     * originalUrls : 保存图片(原图)链接的数组
     * maxCol : 每行最多显示图片的个数
     */
    + (instancetype)photosViewWithThumbnailUrls:(NSArray *)thumbnailUrls originalUrls:(NSArray *)originalUrls photosMaxCol:(NSInteger)maxCol;
    
    /** 根据图片个数和图片状态自动计算出 PYPhontosView 的 size */
    - (CGSize)sizeWithPhotoCount:(NSInteger)count photosState:(NSInteger)state;
    
    /**
     * 刷新图片(未发布)
     * images : 新的图片数组
     */
    - (void)reloadDataWithImages:(NSMutableArray *)images;
    
    @end
    
    
    

    PYPhotoBrowseView (自定义)

    
    @protocol PYPhotoBrowseViewDelegate <NSObject>
    
    @optional
    
    /**
     * 图片浏览将要显示时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView willShowWithImages:(NSArray *)images index:(NSInteger)index;
    /**
     * 图片浏览已经显示时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView didShowWithImages:(NSArray *)images index:(NSInteger)index;
    /**
     * 图片浏览将要隐藏时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView willHiddenWithImages:(NSArray *)images index:(NSInteger)index;
    /**
     * 图片浏览已经隐藏时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView didHiddenWithImages:(NSArray *)images index:(NSInteger)index;
    /**
     * 图片单击时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView didSingleClickedImage:(UIImage *)image index:(NSInteger)index;
    /**
     * 图片长按时调用
     */
    - (void)photoBrowseView:(PYPhotoBrowseView *)photoBrowseView didLongPressImage:(UIImage *)image index:(NSInteger)index;
    
    @end
    
    @protocol PYPhotoBrowseViewDataSource <NSObject>
    
    @required
    /** 返回将要浏览的图片( UIImage )数组 */
    - (NSArray *)imagesForBrowse;
    
    @optional
    /** 返回默认显示图片的索引(默认为 0) */
    - (NSInteger)currentIndex;
    
    /** 默认显示图片相对于主窗口的位置 */
    - (CGRect)frameFormWindow;
    
    /** 消失回到相对于住窗口的指定位置 */
    - (CGRect)frameToWindow;
    
    @end
    
    
    @interface PYPhotoBrowseView  : UIWindow <PYPhotoViewDelegate>
    
    /** 代理 */
    @property (nonatomic, weak) id<PYPhotoBrowseViewDelegate> delegate;
    /** 数据源代理 */
    @property (nonatomic, weak) id<PYPhotoBrowseViewDataSource> dataSource;
    
    /** 用来浏览的图片( UIImage )数组 */
    @property (nonatomic, copy) NSArray *images;
    
    
    /** 用来浏览的图片链接( NSString )数组*/
    @property (nonatomic, copy) NSArray *imagesURL;
    
    /** 用来浏览的图片的控件( UIImageView )数组 */
    @property (nonatomic, copy) NSArray *sourceImgageViews;
    
    /** 用来记录当前下标 */
    @property (nonatomic, assign) NSInteger currentIndex;
    
    /**
     * 浏览图片
     */
    - (void)show;
    
    /**
     * 隐藏
     */
    - (void)hidden;
    
    @end
    
    

    如何使用 PYPhotoBrowser

    • 使用 Cocoapods:
      • pod "PYPhotoBrowser"
      • 导入主头文件#import <PYPhotoBrowser.h>
    • 手动导入:
      • PYPhotoBrowser文件夹中的所有文件拽入项目中
      • 导入主头文件#import "PYPhotoBrowser.h"
      • 使用注意:如果项目本来就有依赖的第三方框架:MBProgressHUD 、 SDWebImage 、 DACircularProgress就不必重复导入, 如果没有,选择Dependency文件夹中,项目不存在的框架拽入项目。

    具体使用(详情见示例程序 PYPhotosViewExample )

    • 已发布(网络图片浏览)

      示例代码:

    
        // 1. 创建缩略图图片链接数组
        NSMutableArray *thumbnailImageUrls = [NSMutableArray array];
        // 添加图片(缩略图)链接
        [thumbnailImageUrls addObject:@"http://ww3.sinaimg.cn/thumbnail/006ka0Iygw1f6bqm7zukpj30g60kzdi2.jpg"];
        [thumbnailImageUrls addObject:@"http://ww1.sinaimg.cn/thumbnail/61b69811gw1f6bqb1bfd2j20b4095dfy.jpg"];
        [thumbnailImageUrls addObject:@"http://ww1.sinaimg.cn/thumbnail/54477ddfgw1f6bqkbanqoj20ku0rsn4d.jpg"];
        [thumbnailImageUrls addObject:@"http://ww4.sinaimg.cn/thumbnail/006ka0Iygw1f6b8gpwr2tj30bc0bqmyz.jpg"];
        [thumbnailImageUrls addObject:@"http://ww2.sinaimg.cn/thumbnail/9c2b5f31jw1f6bqtinmpyj20dw0ae76e.jpg"];
        [thumbnailImageUrls addObject:@"http://ww1.sinaimg.cn/thumbnail/536e7093jw1f6bqdj3lpjj20va134ana.jpg"];
        [thumbnailImageUrls addObject:@"http://ww1.sinaimg.cn/thumbnail/75b1a75fjw1f6bqn35ij6j20ck0g8jtf.jpg"];
        [thumbnailImageUrls addObject:@"http://ww2.sinaimg.cn/thumbnail/005NFHyQgw1f6bn8bha0eg308w0gib2d.gif"];
        [thumbnailImageUrls addObject:@"http://ww1.sinaimg.cn/thumbnail/86afb21egw1f6bq3lq0itj20gg0c2myt.jpg"];
        
        // 1.2 创建原图图片链接数组
        NSMutableArray *originalImageUrls = [NSMutableArray array];
        // 添加图片(原图)链接
        [originalImageUrls addObject:@"http://ww3.sinaimg.cn/large/006ka0Iygw1f6bqm7zukpj30g60kzdi2.jpg"];
        [originalImageUrls addObject:@"http://ww1.sinaimg.cn/large/61b69811gw1f6bqb1bfd2j20b4095dfy.jpg"];
        [originalImageUrls addObject:@"http://ww1.sinaimg.cn/large/54477ddfgw1f6bqkbanqoj20ku0rsn4d.jpg"];
        [originalImageUrls addObject:@"http://ww4.sinaimg.cn/large/006ka0Iygw1f6b8gpwr2tj30bc0bqmyz.jpg"];
        [originalImageUrls addObject:@"http://ww2.sinaimg.cn/large/9c2b5f31jw1f6bqtinmpyj20dw0ae76e.jpg"];
        [originalImageUrls addObject:@"http://ww1.sinaimg.cn/large/536e7093jw1f6bqdj3lpjj20va134ana.jpg"];
        [originalImageUrls addObject:@"http://ww1.sinaimg.cn/large/75b1a75fjw1f6bqn35ij6j20ck0g8jtf.jpg"];
        [originalImageUrls addObject:@"http://ww2.sinaimg.cn/large/005NFHyQgw1f6bn8bha0eg308w0gib2d.gif"];
        [originalImageUrls addObject:@"http://ww1.sinaimg.cn/large/86afb21egw1f6bq3lq0itj20gg0c2myt.jpg"];
      
      // 2. 创建一个 photosView
      PYPhotosView *photosView = [PYPhotosView photosViewWithThumbnailUrls:thumbnailImageUrls originalUrls:originalImageUrls];
      
      // 3. 添加 photosView
      [self.view addSubview:photosView];
      
    
    • 未发布(本地图片上传\发布\预览)

      示例代码:

        
        // 1. 创建本地图片数组
        NSMutableArray *imagesM = [NSMutableArray array];
        for (int i = 0; i < arc4random_uniform(4) + 1; i++) {
            [imagesM addObject:[UIImage imageNamed:[NSString stringWithFormat:@"%02d", i + 1]]];
        }
        
        // 2.1 设置本地图片
      	PYPhotosView *photosView = [PYPhotosView photosViewWithImages:imagesM];
        
        // 3. 设置代理
        photosView.delegate = self;
        
        // 4. 添加 photosView
        [self.view addSubview:photosView];
    
    
    • 仅使用图片浏览功能(使用 PYPhotoBrowseView 类)

      示例代码:

    
        // 1. 创建 photoBroseView 对象
        PYPhotoBrowseView *photoBroseView = [[PYPhotoBrowseView alloc] init];
        
        // 2.1 设置图片源(UIImageView)数组
        photoBroseView.sourceImgageViews = imageViews;
        // 2.2 设置初始化图片下标(即当前点击第几张图片)
        photoBroseView.currentIndex = 2;
        
        // 3.显示(浏览)
        [photoBroseView show];
    
    

    自定义 photosView

    通过设置 photosView 的对象属性值即可修改

    • 设置布局类型(默认为流水布局)
    // 设置布局为线性布局
    photosView.layoutType = PYPhotosViewLayoutTypeLine;
    
    
    • 设置分页指示类型(默认为 pageControll 指示器)
    // 设置指示类型为文本指示
    photosView.pageType = PYPhotosViewPageTypeLabel;
    
    • 设置图片间距(默认为 5 )
    // 设置图片间距为 10
    photosView.photoMargin = 10;
    
    • 设置图片大小(默认 70*70 )
    // 设置图片的宽( width )
    photosView.photoWidth = 100;
    // 设置图片的高( height )
    photosView.photoHeight = 60;
    
    • 设置每行图片最多个数(默认为 3 个)
    // 设置图片最多列数
    photosView.photosMaxCol = 6;
    
    • 设置图片上传前,最多上传的张数(默认为 9 )
    // 设置图片最多上传的张数
    photosView.imagesMaxCountWhenWillCompose = 15;
    

    期待

    • 如果您在使用过程中有任何问题,欢迎直接加我 QQ:499491531 联系,很乐意为您解答任何相关问题!
    • 与其给我点 star ,不如向我狠狠地抛来一个 BUG !
    • 如果感兴趣的小伙伴想要参与这个项目的维护,可以随时联系我或者直接 pull request !
    • 如果您想要更多的接口来自定义,欢迎 issue me !我会根据大家的需求提供更多的接口!
    • 如果您在上线的 app 中使用到该第三方,欢迎联系我,让我可以及时统计、更新!
    11 条回复    2016-10-14 17:49:47 +08:00
    eddiechen
        1
    eddiechen  
       2016-10-11 10:41:34 +08:00
    支持一个~~~~~~~~~~
    sobigfish
        2
    sobigfish  
       2016-10-11 11:47:40 +08:00
    图片浏览依赖框架
    呃,-。- 那么多啊,只是浏览例子里依赖了它们 3 个?还是核心源代码里就有耦合
    CoderKo1o
        3
    CoderKo1o  
    OP
       2016-10-11 21:21:51 +08:00
    @sobigfish 主要是 SDWebImage 其他两个一个是用于显示加载进度、一个是用于提示。
    CoderKo1o
        4
    CoderKo1o  
    OP
       2016-10-11 21:24:27 +08:00
    @eddiechen 谢谢支持!
    sobigfish
        5
    sobigfish  
       2016-10-11 21:31:45 +08:00
    @CoderKo1o 是啊, 开源不是尽量少依赖么 SDWebImage 更是多操了一份心,他们也许有其他的方案呢,比如喵神的 kingfisher
    sobigfish
        6
    sobigfish  
       2016-10-11 21:43:10 +08:00
    issues/5 他们不是真的想用 afn 他们想你把整个 app 写给他们
    真心不用什么都给他们做了
    CoderKo1o
        7
    CoderKo1o  
    OP
       2016-10-11 22:37:38 +08:00
    @sobigfish 为了使用简单。 满足更多用户的需求,可用根据需求选择是否依赖框架。 需要的再导入、每一个依赖都是有理由存在的。 而且依赖的框架也是主流框架,大部分相关图片 app 都会依赖的。
    sobigfish
        8
    sobigfish  
       2016-10-11 22:42:01 +08:00
    要完整功能是的-。- 我也只是在吹毛求疵而已 不要在意
    CoderKo1o
        9
    CoderKo1o  
    OP
       2016-10-12 12:39:12 +08:00
    @sobigfish 没事!有反馈还是最好的!
    champage
        10
    champage  
       2016-10-14 15:39:25 +08:00
    恩 发现你的头像跟我微信里的用了同一个
    CoderKo1o
        11
    CoderKo1o  
    OP
       2016-10-14 17:49:47 +08:00
    @champage 都是喜欢 Alan Walker
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   941 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 20:16 · PVG 04:16 · LAX 13:16 · JFK 16:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.