仿製新浪微博九宮格視圖

主要實現的功能
1.封裝一個imageview imageview上顯示九個縮略圖
2.點擊圖片實現放大效果顯示高清圖片
3.當查看大圖的時候可以滑動查看其它圖
4.當點擊圖片的時候圖片縮小回歸到原來的九宮格中

實現方法看代碼
用了SDWebImage
和UIView+UIViewController

#import <UIKit/UIKit.h>
#import "WBImageViewItem.h"
@interface WBImageView : UIView

@property(nonatomic,copy)NSArray *imageList;//圖片的url數組

@property(nonatomic,assign)NSInteger subImageViewSpace;//設置圖片大小

@property(nonatomic,assign)NSInteger subImageViewInset;//設置圖片空隙大小


@property(nonatomic,copy)NSMutableArray *items;//圖片的item數組
@end
#import "WBImageView.h"
#import "UIImageView+WebCache.h"
#define ZQItemWidth self.subImageViewSpace
#define ZQItemHeight self.subImageViewSpace
#define ZQSpace self.subImageViewInset

@implementation WBImageView

//這個方法是解決 不能同時使用set方法和get方法的
@synthesize subImageViewSpace = _subImageViewSpace;

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

- (NSInteger)subImageViewInset{
    if (_subImageViewInset == 0) {
        return 5;
    }
    return _subImageViewInset;
}

- (NSInteger)subImageViewSpace{
    if (_subImageViewSpace==0) {
        return 80;
    }
    return _subImageViewSpace;
}
- (void)setSubImageViewSpace:(NSInteger)subImageViewSpace{
    _subImageViewSpace=subImageViewSpace;

}

- (void)setImageList:(NSArray *)imageList{
    _imageList=imageList;

#pragma mark -- 根據傳入的數據 計算視圖的寬高

    CGFloat width=ZQItemWidth*3+ZQSpace*2;

    CGFloat height=((_imageList.count-1)/3+1)*ZQItemHeight+ZQSpace*((_imageList.count-1)/3);

    self.frame=CGRectMake(self.frame.origin.x, self.frame.origin.y, width, height);

#pragma mark --創建UIImageView顯示圖片

    //這裏將所有創建愛你出來的圖片視圖存儲起來  當我們想要放大的時候會用到
    _items=[[NSMutableArray alloc]init];

    for (int index=0; index<_imageList.count; index++) {

        //初始化九宮格視圖內的imagView
        WBImageViewItem *item=[[WBImageViewItem alloc]initWithFrame:[self getItemFrameForSupview:index]];

        item.imageList=_imageList;

        //設置一個標記 讓外部知道現在是第幾個item 用來計算座標
        item.index=index;

        [item sd_setImageWithURL:_imageList[index]];

        [_items addObject:item];

#pragma mark -- 將item的frame存儲起來 當我們點擊大圖縮小的時候使用 

        item.originFrame=item.frame;

        [self addSubview:item];
    }
}
#pragma mark -- 根據item加載的圖片在數組的位置 計算item在父視圖上的frame屬性

- (CGRect)getItemFrameForSupview:(int)index{

    CGFloat x=index%3*(ZQSpace+ZQItemWidth);

    CGFloat y=index/3*(ZQSpace+ZQItemHeight);

    return CGRectMake(x, y, ZQItemWidth, ZQItemHeight);
}
@end
#import <UIKit/UIKit.h>

@interface WBImageViewItem : UIImageView

@property(nonatomic,copy)NSArray *imageList;

@property(nonatomic,assign)NSInteger index;//用於scrollView計算contentSize

@property(nonatomic,assign)CGRect originFrame;//原始frame,做完放大動畫後恢復原狀態
@end
#import "WBImageViewItem.h"
#import "UIView+UIViewController.h"
#import "WBImageViewController.h"
@implementation WBImageViewItem

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        //開啓imageView的響應點擊事件
        self.userInteractionEnabled=YES;

        //設置imagView的顯示模式 該模式爲不對圖片進行拉伸  原比例放大
        self.contentMode=UIViewContentModeScaleAspectFit;

        //添加點擊事件 當點擊的時候執行放大動畫
        UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self
                                                                           action:@selector(tapAction:)];
        [self addGestureRecognizer:tap];
    }
    return self;
}

- (void)tapAction:(UITapGestureRecognizer *)tap{

    //當點擊的時候彈出控制器
    WBImageViewController *viewC=[[WBImageViewController alloc]init];

    //設置控制器的數據  當我們要在scroll上顯示數據的時候使用
    viewC.imageList=_imageList;

    viewC.currentItem=self;

    //記錄 self.superview 是WBImageView
    viewC.itemOriginSuperView=(WBImageView *)self.superview;

    //彈出視圖控制器
    [self.viewController presentViewController:viewC animated:NO completion:nil];

}
@end
#import <UIKit/UIKit.h>
#import "WBImageViewItem.h"
#import "WBImageView.h"
@interface WBImageViewController : UIViewController

@property(nonatomic,copy)NSArray *imageList;

@property(nonatomic,strong)WBImageViewItem *currentItem;//記錄當前的item

@property(nonatomic,strong)WBImageView *itemOriginSuperView;//記錄原始的itme的父視圖 用以查找放大前的座標
@end
#import "WBImageViewController.h"
#import "UIImageView+WebCache.h"
@interface WBImageViewController ()<UIScrollViewDelegate>
{
    UIScrollView *_scrollView;//用於顯示大圖
}
@end

@implementation WBImageViewController

#pragma mark -- 執行放大的動畫
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];

    //改變點擊的item的origin屬性 當我們點擊item的時候 我們需要這個圖片的動畫的起點是我們點擊圖片的位置
    //轉換item所在位置的座標   這樣看來就是縮略圖的位置沒有變化 但是他的父視圖換了一下
    //下面的方法 有三個參數 一個返回值 三個參數分別是 原有的frame所在的父視圖 原有的frame 和目的視圖 返回值是目的frame
    self.currentItem.frame=[self.currentItem.superview convertRect:self.currentItem.frame toView:self.view];

    //將點擊的item拿到視圖控制器上
    [self.view addSubview:self.currentItem];

    [UIView animateWithDuration:2 animations:^{

        self.currentItem.frame=self.view.frame;

    } completion:^(BOOL finished) {

        _scrollView.hidden=NO;//顯示高清圖片

        //恢復item的frame
        self.currentItem.frame=self.currentItem.originFrame;

        //將item放回原始的父視圖上 我們在這裏移動的是縮略圖  在這裏肯能有些不好理解
        //爲什麼不在當點擊縮小的時候纔去縮小?
        //因爲當我們在彈出的視圖控制器種可能會滾動換一個圖片 這時候 在這裏拿到的圖片 和縮小回去的圖片就不是一個
        //具體怎麼實現滾動後如何縮小看tapAction
        [self.itemOriginSuperView addSubview:self.currentItem];

    }];


}
- (void)viewDidLoad {
    [super viewDidLoad];

    //彈出大圖瀏覽的視圖控制器
    //創建ScrollView實現圖片瀏覽
    _scrollView=[[UIScrollView alloc]initWithFrame:self.view.bounds];

    _scrollView.contentSize=CGSizeMake(self.view.frame.size.width*_imageList.count, self.view.frame.size.height);

    for (int i=0; i<_imageList.count; i++) {

        UIImageView *imageVie=[[UIImageView alloc]initWithFrame:CGRectMake(self.view.frame.size.width*i, 0, self.view.frame.size.width, self.view.frame.size.height)];

        [_scrollView addSubview:imageVie];

#pragma mark -- 添加單擊手勢 實現恢復動畫
        UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)];

        imageVie.userInteractionEnabled=YES;

        [imageVie addGestureRecognizer:tap];

#pragma mark -- 設置圖片的展示形式 這個方法是設置圖片不拉伸 展現原始比例 
        imageVie.contentMode=UIViewContentModeScaleAspectFit;
     //thumbnail縮略圖 small 小圖 large 大圖
        NSString *largeURL=[_imageList[i]stringByReplacingOccurrencesOfString:@"thumbnail" withString:@"large"];

        [imageVie sd_setImageWithURL:[NSURL URLWithString:largeURL]];
    }

    [_scrollView setPagingEnabled:YES];

    _scrollView.delegate=self;

    _scrollView.hidden=YES;//默認隱藏 當放大動畫結束後顯示

    [_scrollView scrollRectToVisible:CGRectMake(self.currentItem.index *self.view.frame.size.width,0,self.view.frame.size.width,self.view.frame.size.height)
                            animated:NO];

    [self.view addSubview:_scrollView];
}

#pragma mark -- 當點擊屏幕的時候縮小
- (void)tapAction:(UITapGestureRecognizer *)tap{

    //當點擊的時候我們需要知道我們點擊的是哪個item
    //這個currentItem在哪去設置呢?
    //最開始的時候我們是有一個的  當我們滾動的時候還需要去設置一下

    //保存curreItem當 self dismiss self將被釋放 先將他保存一下
    WBImageViewItem *item=self.currentItem;

    //這裏當我們做縮小動畫的時候 需要回到WBImageView中實現 縮小的過程 會出現正在縮小的圖片在小圖片的下面 可以註釋這句話看效果
    [item.superview bringSubviewToFront:item];

    //轉換座標 從當前視圖 轉化爲要顯示視圖上的座標
    CGPoint point=[self.view convertPoint:CGPointZero
                                   toView:self.itemOriginSuperView];

    item.frame=CGRectMake(point.x,point.y,self.view.frame.size.width,self.view.frame.size.height);

    [self dismissViewControllerAnimated:NO completion:^{

        [UIView animateWithDuration:2 animations:^{

            item.frame=item.originFrame;

        }];
    }];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //計算當前位置
    NSInteger currentIndex=scrollView.contentOffset.x/self.view.frame.size.width;

    //改變當前的item當圖片返回的時候使用
    self.currentItem=self.itemOriginSuperView.items[currentIndex];
}


@end

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章