九宫格排列与浏览的简单功能

一、九宫格布局

  在浏览各种微博、QQ空间、在网购等时候都可以注意到显示的图片是由九宫格来布局完成的。开发者为其限定了最大个数--9。当然,有一张就添加一张,最多不过九张。那就拿微博为例来实现其功能。以下是其初始的图。

二、代码及实现效果

(1)步骤:

  1. 新建一个工程,并创建一个WBImageView的类,使其继承于UIView。
  2. 创建一个WBImageItem类,继承于UIImageIView。
  3. 根据设置的背景图片循环创建九个imageView的位置。计算每个iamgeView的位置和大小(包括高度的计算)。
  4. 而后,给ImageItem添加手势,可以放大浏览,放大的时候需要记录原始的frame,方便恢复原样。还可以缩小回原图原位置,方法的要获取新的坐标系统的frame。这一些代码可以写在item里面。
  5. 关于图片滑动,就是将图片加载到scrollView上,滑动之后获取对应的index,在缩小(返回原始)的时候恢复在对应的位置。如图

  在做的过程中需要注意的地方就是:1.数据的传值问题(_imageList数组);2.在放大之后又要返回,则需要记住其原始的位置和大小;3.在变换的时候需要用到转换坐标系方法--- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;);4.图片都是放在scrollView上的,可以进行放大缩小滑动;5.在放大之后,注意一些细节问题--隐藏的要显示,而后将其放回原父视图上;6.缩小的道理只是将放大过程逆向返回。

  读者看到的放大过程,就是图片放大了,达到一定的大小之后就隐藏了(右侧图),而已经添加到scrollView上的就会显示出来(左侧图),这就是错觉,以为是一张图,其实是两张。所以要隐藏,完成放大之后要显示。同样 缩小的也是这个原理。

    

 (2)导入的头文件:

1 //WBImageView.h 中
2 #import "WBImageView.h"
3 #import "WBImageItem.h"
4 #import "UIImageView+WebCache.h"//针对于ImageView的第三方
1 //WBImageViewController中
2 #import "WBImageViewController.h"
3 #import "WBImageView.h"
4 #import "UIImageView+WebCache.h"

(3)主要代码

viewController.m 

 1 //在viewDidLoad中
 2 WBImageView *wbImageView = [[WBImageView alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 300)];
 3     
 4     wbImageView.backgroundColor = [UIColor orangeColor];
 5     //图片的链接
 6     wbImageView.imageList = @[
 7                               @"http://a.vpimg2.com/upload/merchandise/20348/W-TU-3122934087-33-1.jpg",
 8                               @"http://img.kumi.cn/photo/5a/15/b7/5a15b7cb955fb13e.jpg",
 9                               @"http://pic.nipic.com/2007-11-09/2007119122519868_2.jpg",
10                               @"http://pic.nipic.com/2007-11-09/200711912230489_2.jpg",
11                               @"http://www.xxjxsj.cn/article/UploadPic/2009-10/2009101018545196251.jpg",
12                               @"http://pica.nipic.com/2008-03-19/2008319183523380_2.jpg",
13                               @"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg",
14                               @"http://h.hiphotos.baidu.com/image/pic/item/9d82d158ccbf6c812f9fe0e1be3eb13533fa400b.jpg",
15                               @"http://pic27.nipic.com/20130201/3789536_092151001379_2.jpg"                              
16                               ];
17     
18     [self.view addSubview:wbImageView];

 WBImageIvew.m 

 1 #warning 用class 声明一下  否则会循环引用
 2 @class WBImageItem;
 3 @interface WBImageView : UIView
 4 @property (nonatomic, copy) NSArray *imageList;//存放图片的数组
 5 /**
 6  *  方法说明:返回做缩小动画时  获取做动画的item
 7  *
 8  *  @param  currentIndex:大图浏览时浏览到的图片的位置
 9  *
10  *  @return
11  */
12 - (WBImageItem *)getItemForIndex:(int)currentIndex;

 WBImageIvew.h中要设置一个NSArray属性,来保存外部传入的URL。

 1 #define kItemWH (self.frame.size.width -20)/3
 2 #define kItemSpace 10
 3 
 4 @implementation WBImageView
 5 {    
 6     WBImageItem *_item;
 7 }
 8 - (id)initWithFrame:(CGRect)frame {
 9     if (self = [super initWithFrame:frame]) {
10     }
11     return self;
12 }
13 
14 - (void)setImageList:(NSArray *)imageList {
15     _imageList = imageList;
16     [self creatSubviews];
17 }
18 
19 //创建图片
20 - (void)creatSubviews {
21     int  index = 0;
22     for (NSString *url in _imageList) {
23         _item = [[WBImageItem alloc] initWithFrame:[self getItemFrameAtIndex:index]];
24 //        [_item setImageWithURL:[NSURL URLWithString:url]];        
25         _item.backgroundColor = [UIColor greenColor];        
26         _item.tag = 1000 + index;
27         
28         //传值给item的imageList属性
29         _item.imageList = _imageList;
30         
31         //需要给 原始的赋值才可以显示在controller中
32         _item.originFrame = _item.frame;
33         _item.originSupview = self;
34         _item.index = index;
35         
36         [self addSubview:_item];        
37         index ++;
38     }    
39     CGFloat height = [self getWBImageViewHeight:(int)_imageList.count];    
40     CGRect frame = self.frame;
41     frame.size.height = height;    
42     self.frame = frame;
43     
44 }
45 
46 - (CGRect)getItemFrameAtIndex:(int)index {
47     /*
48      0-2  x: index*(宽+间距)
49           y: 0     
50      3-5  x: (index%3)*(宽+间距)
51           y: (高+间距)     
52      6-8  x: (index%3)*(宽+间距)
53           y:(index/3)(高+间距)
54      */      
55     CGFloat x = index % 3 * (kItemWH + kItemSpace);
56     CGFloat y = index / 3 * (kItemWH + kItemSpace);
57     
58     return CGRectMake(x, y, kItemWH, kItemWH);
59 }
60 + (CGFloat)getWBImageViewHeight:(int)count {
61         /*
62      1-3 1*kItemWH
63      4-6 2*kItemWH + 1*kItemSpace
64      7-9 3*kItemWH + 2*kItemSpace     
65      */    
66     CGFloat height = ((count - 1) / 3 +1 ) * kItemWH + (count - 1) / 3 * kItemSpace;    
67     return height;
68 }
WBImageView

 WBImageItem.h设置一些属性用于存储接收等。

 1 //避免循环引用
 2 @class WBImageView;
 3 @interface WBImageItem : UIImageView
 4 @property (nonatomic, copy)NSArray *imageList;//存放图片的数组
 5 @property (nonatomic, assign) int index;// item在父视图上的位置
 6 @property (nonatomic, assign) CGRect originFrame;//在原始父视图上的原始坐标
 7 @property (nonatomic, strong) WBImageView *originSupview;//item原始的父视图
 8 /**
 9  *  方法说明: 获取item 在新的坐标系统 (新的界面)上的frame
10  *
11  *  @param  originFrame:item原始的frame
12  *
13  *  @return
14  */
15 - (CGRect)getItemFrameAtWindow:(CGRect)originFrame;

WBImageItem.m的代码如下。

 1 #import "WBImageItem.h"
 2 #import "WBImageViewController.h"
 3 #import "UIView+UIViewController.h"
 4 
 5 @implementation WBImageItem
 6 - (id)initWithFrame:(CGRect)frame {    
 7     if (self = [super initWithFrame:frame]) {
 8         //开启触摸
 9         self.userInteractionEnabled = YES;
10         //禁止拉伸
11         self.contentMode = UIViewContentModeScaleAspectFit;        
12         [self addGesture];        
13     }
14     return self;    
15 }
16 
17 //点击手势
18 - (void)addGesture {    
19     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];    
20     //添加点击手势
21     [self addGestureRecognizer:tap];    
22 }
23 
24 - (void)tapAction {    
25     WBImageViewController *controler = [[WBImageViewController alloc] init];    
26     controler.imageList = _imageList;    
27     //将点击的图片设置为大图,浏览当前图片,用来做动画
28     controler.currentItem = self;
29     controler.currentIndex = self.index;    
30     [self.viewController presentViewController:controler animated:NO completion:nil];
31 }
32 - (void)setImageList:(NSArray *)imageList {    
33     _imageList = imageList;
34 }
35 /**
36  *  方法说明: 获取item 在新的坐标系统 (新的界面)上的frame
37  *
38  *  @param  originFrame:item原始的frame
39  *
40  *  @return
41  */
42 - (CGRect)getItemFrameAtWindow:(CGRect)originFrame {
43     
44     CGRect newFrame = [self.superview convertRect:originFrame toView:self.window];
45     
46     return newFrame;
47 }
48 @end

WBImageViewController.h设置属性

1 @property (nonatomic, copy) NSArray *imageList;
2 @property (nonatomic, strong) WBImageItem *currentItem;//点击的图片显示在当前页面
3 @property (nonatomic, assign) int currentIndex;//当前在浏览界面看到的图片位置属性
4 // 1. 刚刚进入时 currentItem.index
5 // 2. 根据scrollView  的滚动的偏移量计算

WBImageViewController.m双击放大(缩小)要返回图片,利用图片的tag值(- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView)来获取。

  1 #define kSelfViewWidth self.view.frame.size.width
  2 #define kSelfViewHeight self.view.frame.size.height
  3 @interface WBImageViewController ()
  4 {
  5     UIScrollView *_supScrollView;//图片的滚动浏览视图    
  6     NSMutableArray *_subScroollViews; 
  7 }
  8 @end
  9 
 10 @implementation WBImageViewController
 11 - (void)viewDidLoad {
 12     [super viewDidLoad];    
 13     //把当前页面的item 放到当前的页面
 14     self.currentItem.frame = [self.currentItem getItemFrameAtWindow:self.currentItem.originFrame];    
 15     [self.view.window addSubview:self.currentItem];
 16 #warning 需要在 item中给原始的originFrame赋值    
 17     [self.view addSubview:self.currentItem];    
 18     [self createSubviews];   
 19 }
 20 
 21 - (void)viewDidAppear:(BOOL)animated {
 22     [super viewDidAppear:animated];
 23     //放大动画
 24     [UIView animateWithDuration:.35 animations:^{        
 25         self.currentItem.frame = self.view.bounds;
 26     }  completion:^(BOOL finished) {        
 27         //动画结束之后,显示
 28         _supScrollView.hidden = NO;        
 29         //放回原父视图上
 30         self.currentItem.frame = self.currentItem.originFrame;
 31 #warning 虽然在.h中已经导入,但是还需导入
 32         WBImageView *wbImageView = self.currentItem.originSupview;        
 33         [wbImageView addSubview:self.currentItem];
 34     }];    
 35 }
 36 
 37 //获取imageList的传值 不调用set的话 ,可以直接使用 _imageList = self.imageList;
 38 - (void)setImageList:(NSArray *)imageList {    
 39     _imageList = imageList;
 40 }
 41 
 42 - (void)createSubviews {    
 43 //   1. 初始化图片浏览的scrollView
 44     _supScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];    
 45     _supScrollView.delegate = self;    
 46     _supScrollView.pagingEnabled = YES;//翻页    
 47     //默认隐藏,否则会出现两张图片
 48     _supScrollView.hidden = YES;    
 49     _supScrollView.contentSize = CGSizeMake(kSelfViewWidth * _imageList.count, kSelfViewHeight);    
 50     _supScrollView.contentOffset = CGPointMake(kSelfViewWidth * self.currentIndex, 0);    
 51     [self.view addSubview:_supScrollView];    
 52 //   2.创建图片的显示控件    
 53     _subScroollViews = [[NSMutableArray alloc] init];    
 54     int index = 0;
 55     for (NSString *url in _imageList) {        
 56         //第一层scrollView
 57         UIScrollView *subScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(kSelfViewWidth * index, 0, kSelfViewWidth, kSelfViewHeight)];
 58         subScrollView.contentSize = CGSizeMake(kSelfViewWidth, kSelfViewHeight);        
 59         subScrollView.delegate = self;        
 60         //设置放大缩小倍数
 61         subScrollView.maximumZoomScale = 2.f;
 62         subScrollView.minimumZoomScale = .5f;        
 63         [_supScrollView addSubview:subScrollView];
 64         [_subScroollViews addObject:subScrollView];       
 65         UIImageView *imageView = [[UIImageView alloc] initWithFrame:subScrollView.bounds];
 66         //禁止图片拉伸
 67         imageView.contentMode = UIViewContentModeScaleAspectFit;
 68         //默认是关闭的
 69         imageView.userInteractionEnabled = YES;        
 70         imageView.tag = 20001;        
 71         UIImageView *smallImageView = [[UIImageView alloc] initWithFrame:imageView.bounds];
 72         [smallImageView setImageWithURL:[NSURL URLWithString:url]];        
 73         NSString *largeImageUrl = [url stringByReplacingOccurrencesOfString:@"thumbnail" withString:@"large"];        
 74         [imageView setImageWithURL:[NSURL URLWithString:largeImageUrl] placeholderImage:smallImageView.image];        
 75         [smallImageView removeFromSuperview];
 76         smallImageView = nil;        
 77         [subScrollView addSubview:imageView];        
 78         //添加点击手势
 79         UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
 80         [imageView addGestureRecognizer:tap1];
 81         //双击手势
 82         UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapActionTwo)];        
 83         //numberOfTapsRequired 点击的次数
 84         tap2.numberOfTapsRequired = 2;
 85         //numberOfTouchesRequired 触摸点的个数
 86         tap2.numberOfTouchesRequired = 1;
 87         [imageView addGestureRecognizer:tap2];
 88         //双击优先
 89         [tap1 requireGestureRecognizerToFail:tap2];
 90         index ++;
 91     }
 92 }
 93 
 94 //双击放大
 95 - (void)tapActionTwo {    
 96     UIScrollView *scrollView = [_subScroollViews objectAtIndex:self.currentIndex];    
 97     [UIView animateWithDuration:.35 animations:^{        
 98         scrollView.zoomScale = scrollView.zoomScale == 1.0f ? 2.0f : 1.0f;        
 99     }];   
100 }
101 
102 //给图片一个点击手势,使其返回
103 - (void)dismiss {    
104     [self dismissViewControllerAnimated:NO completion:nil];    
105     //缩小动画实现
106     WBImageView *wbImageView = self.currentItem.originSupview;    
107     WBImageItem *item = [wbImageView getItemForIndex:self.currentIndex];    
108     //再次将图片放回到原来View上
109     CGPoint newPoint = [self.view convertPoint:CGPointZero toView:wbImageView];
110     //大小
111     CGRect frame = item.frame;
112     //位置=新的位置
113     frame.origin = newPoint;
114     //大小=屏幕大小
115     frame.size = self.view.frame.size;
116     //重新复制给item
117     item.frame = frame;    
118 //    动画实现
119     [wbImageView bringSubviewToFront:item];    
120     [UIView animateWithDuration:.35 animations:^{        
121         item.frame = item.originFrame;
122     }];
123 }
124 
125 #pragma mark- UIScrollViewDelegate
126 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
127         if (scrollView != _supScrollView) {        
128         return [scrollView viewWithTag:20001];
129     }
130     return nil;
131 }
132 //此方法实现的是点击缩小之后,恢复到对应的原位置
133 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
134     //要分清楚
135     if (scrollView == _supScrollView) {
136         //获得最新滚动的界面的index属性
137         int newIndex = (int)scrollView.contentOffset.x/kSelfViewWidth;        
138         if (self.currentIndex == newIndex) {            
139             return;
140         }else {            
141             self.currentIndex = newIndex;
142         }
143     }    
144 }
145 
146 @end
View Code

另外,在WBImageView.m中写一个方法,并开放出来,在WBImageViewController中缩小的时候使用。

 1 /**
 2  *  方法说明:返回做缩小动画时  获取做动画的item
 3  *
 4  *  @param  currentIndex:大图浏览时浏览到的图片的位置
 5  *
 6  *  @return
 7  */
 8 - (WBImageItem *)getItemForIndex:(int)currentIndex {    
 9     WBImageItem *item = (WBImageItem *)[self viewWithTag:1000 + currentIndex];    
10     return item;    
11 }

以上需要第三方的文档。代码下载路径http://pan.baidu.com/s/1o6KQYAQ

实现效果如下图 

可以看到,图片大小不一样,这是设置了图片禁止拉伸的原因(self.contentMode = UIViewContentModeScaleAspectFit;

    UIViewContentModeScaleToFill,//以宽为基准,对高度进行对应比例拉伸或压缩

    UIViewContentModeScaleAspectFit,//不改变原来大小 

    UIViewContentModeScaleAspectFill,//以高为基准,对宽度进行对应比例拉伸或压缩

以上文章是博主原创文章,转载请标明出处。

原文地址:https://www.cnblogs.com/david-han/p/4902529.html