前言
图片浏览器大家应该都用过,这方面的第三方也有很多,不过有时候第三方会跟我们的需求有一些出入,这就需要我们要么对第三方进行修改要么自己重新定制。我是比较喜欢自己重新定制的,在这给大家简单介绍一下我定制的图片浏览器,算是给大家提供一个思路,可以在此基础上进行修改完善。

实现原理
通过弹出uiviewcontroller的形式来展示图片,使用uicollectionview并添加手势来实现图片浏览时图片的间隔。
首先创建一个继承于uiviewcontroller的控制器,来作为图片浏览器的控制器,并实现相应的代码如下:
示例代码
?| 1 2 3 4 5 |
#import <uikit/uikit.h>
#import "rhphotobrowser.h"
@interface rhphotobrowsercontroller : uiviewcontroller
- (instancetype)initwithtype:(rhphotosourcetype)type imagearr:(nsarray *)imagearr selectindex:(nsinteger)selectindex;
@end
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
#import "rhphotobrowsercontroller.h"
#import "rhphotobrowsercell.h"
#define cell_photobrowser @"cell_photobrowser"
#define photospace 10 // 图片间距
@interface rhphotobrowsercontroller () <uicollectionviewdatasource, uicollectionviewdelegate, uicollectionviewdelegateflowlayout>
@property (nonatomic, strong) uicollectionview * collection;
@property (nonatomic, strong) uipagecontrol * pagecontrol;
@property (nonatomic, strong) nsmutablearray * dataarr;
@property (nonatomic, assign) rhphotosourcetype type;
@property (nonatomic, assign) nsinteger selectindex;
@property (nonatomic, assign) cgfloat pancenterx;
@property (nonatomic, assign) cgfloat startoffsetx;
@property (nonatomic, assign) cgfloat offsetx;
@property (nonatomic, assign) cgfloat panx;
@end
@implementation rhphotobrowsercontroller
- (instancetype)initwithtype:(rhphotosourcetype)type imagearr:(nsarray *)imagearr selectindex:(nsinteger)selectindex {
self = [super init];
if (self) {
[self.dataarr removeallobjects];
[self.dataarr addobjectsfromarray:imagearr];
_type = type;
_selectindex = selectindex;
}
return self;
}
- (void)viewdidload {
[super viewdidload];
// do any additional setup after loading the view.
[self addsubviews];
[self makeconstraintsforui];
}
#pragma mark - add subviews
- (void)addsubviews {
self.view.backgroundcolor = [uicolor blackcolor];
[self.view addsubview:self.collection];
[self.view addsubview:self.pagecontrol];
}
- (void)makeconstraintsforui {
[_collection mas_makeconstraints:^(masconstraintmaker *make) {
make.top.left.right.bottom.mas_equalto(0);
}];
[_pagecontrol mas_makeconstraints:^(masconstraintmaker *make) {
make.left.right.mas_equalto(0);
make.bottom.mas_equalto(-ss(50));
make.height.mas_equalto(20);
}];
[self performselector:@selector(setcollectioncontentoffset) withobject:nil afterdelay:0.1];
}
- (void)setcollectioncontentoffset {
rhweakself;
dispatch_async(dispatch_get_main_queue(), ^{
[weakself.collection setcontentoffset:cgpointmake((screen_width + photospace) * _selectindex, 0) animated:no];
weakself.pagecontrol.numberofpages = weakself.dataarr.count;
weakself.pagecontrol.currentpage = _selectindex;
});
_startoffsetx = _collection.contentoffset.x;
}
#pragma mark - gesturerecognizer event
- (void)pancollection:(uipangesturerecognizer *)pan {
_pancenterx = [pan translationinview:self.collection].x;
if (pan.state == uigesturerecognizerstatebegan) {
_startoffsetx = _collection.contentoffset.x;
_offsetx = 0;
_panx = 0;
}
if (_selectindex == 0) {
if (_pancenterx > 0) {
cgfloat s = (screen_width - _pancenterx) / screen_width;
_offsetx += (_pancenterx - _panx) * s;
_panx = _pancenterx;
[self.collection setcontentoffset:cgpointmake(-_offsetx, 0) animated:no];
} else {
if (self.dataarr.count == 1) {
cgfloat s = (screen_width + _pancenterx) / screen_width;
_offsetx += (_pancenterx - _panx) * s;
_panx = _pancenterx;
[self.collection setcontentoffset:cgpointmake(-_offsetx, 0) animated:no];
} else {
[self.collection setcontentoffset:cgpointmake(_startoffsetx - _pancenterx, 0) animated:no];
}
}
} else if (_selectindex == self.dataarr.count - 1) {
if (_pancenterx < 0) {
cgfloat s = (screen_width + _pancenterx) / screen_width;
_offsetx += (_pancenterx - _panx) * s;
_panx = _pancenterx;
[self.collection setcontentoffset:cgpointmake(_startoffsetx - _offsetx, 0) animated:no];
} else {
[self.collection setcontentoffset:cgpointmake(_startoffsetx - _pancenterx, 0) animated:no];
}
} else {
[self.collection setcontentoffset:cgpointmake(_startoffsetx - _pancenterx, 0) animated:no];
}
if (pan.state == uigesturerecognizerstateended) {
if ([self absolutevalue:_pancenterx] > screen_width/3) {
if (_pancenterx < 0) {
_selectindex += 1;
} else {
_selectindex -= 1;
}
if (_selectindex == self.dataarr.count) {
_selectindex = self.dataarr.count - 1;
} else if (_selectindex == -1) {
_selectindex = 0;
}
[self.collection setcontentoffset:cgpointmake((screen_width + photospace) * _selectindex, 0) animated:yes];
self.pagecontrol.currentpage = _selectindex;
} else {
[self.collection setcontentoffset:cgpointmake(_startoffsetx, 0) animated:yes];
}
}
}
- (void)swipecollection:(uiswipegesturerecognizer *)swipe {
if (swipe.direction == uiswipegesturerecognizerdirectionleft) {
_selectindex += 1;
} else if (swipe.direction == uiswipegesturerecognizerdirectionright) {
_selectindex -= 1;
}
if (_selectindex == self.dataarr.count) {
_selectindex = self.dataarr.count - 1;
} else if (_selectindex == -1) {
_selectindex = 0;
}
self.pagecontrol.currentpage = _selectindex;
[self.collection setcontentoffset:cgpointmake((screen_width + photospace) * _selectindex, 0) animated:yes];
}
// 返回value的绝对值
- (cgfloat)absolutevalue:(cgfloat)value {
if (value < 0) {
return -value;
}
return value;
}
#pragma mark - collection delegate
- (nsinteger)collectionview:(uicollectionview *)collectionview numberofitemsinsection:(nsinteger)section {
return self.dataarr.count;
}
- (uicollectionviewcell *)collectionview:(uicollectionview *)collectionview cellforitematindexpath:(nsindexpath *)indexpath {
rhphotobrowsercell * cell = [collectionview dequeuereusablecellwithreuseidentifier:cell_photobrowser forindexpath:indexpath];
if (indexpath.row < self.dataarr.count) {
if (_type == rhphotosourcetypeimage) {
uiimage * image = [self.dataarr objectatindex:indexpath.row];
[cell configcellwithimage:image];
} else if (_type == rhphotosourcetypeurl) {
nsstring * url = [self.dataarr objectatindex:indexpath.row];
[cell configcellwithurl:url];
} else if (_type == rhphotosourcetypefilepath) {
nsstring * filepath = [self.dataarr objectatindex:indexpath.row];
[cell configcellwithfilepath:filepath];
} else if (_type == rhphotosourcetypefilename) {
nsstring * filename = [self.dataarr objectatindex:indexpath.row];
[cell configcellwithfilename:filename];
}
}
return cell;
}
- (cgsize)collectionview:(uicollectionview *)collectionview layout:(uicollectionviewlayout *)collectionviewlayout sizeforitematindexpath:(nsindexpath *)indexpath {
return cgsizemake(screen_width, screen_height);
}
- (cgfloat)collectionview:(uicollectionview *)collectionview layout:(uicollectionviewlayout *)collectionviewlayout minimumlinespacingforsectionatindex:(nsinteger)section {
return photospace;
}
- (cgfloat)collectionview:(uicollectionview *)collectionview layout:(uicollectionviewlayout *)collectionviewlayout minimuminteritemspacingforsectionatindex:(nsinteger)section {
return 0;
}
- (void)collectionview:(uicollectionview *)collectionview didselectitematindexpath:(nsindexpath *)indexpath {
[self dismissviewcontrolleranimated:yes completion:nil];
}
#pragma mark - setter and getter
- (uicollectionview *)collection {
if (!_collection) {
uicollectionviewflowlayout * layout = [[uicollectionviewflowlayout alloc] init];
layout.scrolldirection = uicollectionviewscrolldirectionhorizontal;
uicollectionview * cv = [[uicollectionview alloc] initwithframe:cgrectzero collectionviewlayout:layout];
cv.backgroundcolor = [uicolor blackcolor];
cv.delegate = self;
cv.datasource = self;
cv.showshorizontalscrollindicator = no;
[cv registerclass:[rhphotobrowsercell class] forcellwithreuseidentifier:cell_photobrowser];
uipangesturerecognizer * pan = [[uipangesturerecognizer alloc] initwithtarget:self action:@selector(pancollection:)];
[cv addgesturerecognizer:pan];
uiswipegesturerecognizer * swipel = [[uiswipegesturerecognizer alloc] initwithtarget:self action:@selector(swipecollection:)];
swipel.direction = uiswipegesturerecognizerdirectionleft;
[cv addgesturerecognizer:swipel];
uiswipegesturerecognizer * swiper = [[uiswipegesturerecognizer alloc] initwithtarget:self action:@selector(swipecollection:)];
swiper.direction = uiswipegesturerecognizerdirectionright;
[cv addgesturerecognizer:swiper];
_collection = cv;
}
return _collection;
}
- (uipagecontrol *)pagecontrol {
if (!_pagecontrol) {
uipagecontrol * pagecontrol = [[uipagecontrol alloc] init];
pagecontrol.pageindicatortintcolor = [[uicolor lightgraycolor] colorwithalphacomponent:0.9];
pagecontrol.currentpageindicatortintcolor = [uicolor whitecolor];
pagecontrol.userinteractionenabled = no;
_pagecontrol = pagecontrol;
}
return _pagecontrol;
}
- (nsmutablearray *)dataarr {
if (!_dataarr) {
_dataarr = [nsmutablearray array];
}
return _dataarr;
}
@end
|
其实到此基本已经结束了,大家实现一个相对应的cell就可以了。使用时直接通过外漏的方法创建该控制器对象并弹出该控制器即可。
为了更加方便的调用,我又增加了一个nsobject的类来控制以上控制器的调用。如下:
?| 1 2 3 4 5 6 7 8 9 10 11 |
#import <foundation/foundation.h>
typedef ns_enum(nsuinteger, rhphotosourcetype) {
rhphotosourcetypeimage = 0,
rhphotosourcetypeurl = 1,
rhphotosourcetypefilepath = 2,
rhphotosourcetypefilename = 3
};
@interface rhphotobrowser : nsobject
+ (rhphotobrowser *)shared;
- (void)browseimagewithtype:(rhphotosourcetype)type imagearr:(nsarray *)imagearr selectindex:(nsinteger)selectindex;
@end
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#import "rhphotobrowser.h"
#import "rhphotobrowsercontroller.h"
@implementation rhphotobrowser
+ (rhphotobrowser *)shared {
static rhphotobrowser * helper = nil;
static dispatch_once_t oncetoken;
dispatch_once(&oncetoken, ^{
helper = [[rhphotobrowser alloc] init];
});
return helper;
}
- (void)browseimagewithtype:(rhphotosourcetype)type imagearr:(nsarray *)imagearr selectindex:(nsinteger)selectindex {
if (selectindex > imagearr.count - 1) {
selectindex = 0;
}
uiviewcontroller * rootvc = [uiapplication sharedapplication].delegate.window.rootviewcontroller;
rhphotobrowsercontroller * browser = [[rhphotobrowsercontroller alloc] initwithtype:type imagearr:imagearr selectindex:selectindex];
[rootvc presentviewcontroller:browser animated:yes completion:nil];
}
@end
|
这样使用的时候只需要使用该类就可以了。这里大家可以将单例去掉,将对象方法直接改为类方法即可。我是习惯了,所以这样写了。
再给大家看一下使用方法一步调用:
?| 1 |
[[rhphotobrowser shared] browseimagewithtype:rhphotosourcetypefilename imagearr:@[@"c006", @"c007", @"c008", @"c009", @"c010"] selectindex:2];
|
效果如下:

最后,还是希望能够帮助到有需要的朋友们,愿我们能够一起学习进步,在开发的道路上越走越顺利!!!
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://www.jianshu.com/p/336121d1280f








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。