iOS开发之功能模块--根据需求开发横向的子弹盒View

这个需求是本人工作开发中后期需求要添加的新功能,本人模仿UITableView的代理和数据源方法进行了第一阶段的开发。第二阶段是添加丰富的动画。

这个功能需求描述:能上传添加五个待选头像,五个头像分别都可以被设置为app的正式头像和展示封面,五个头像分别都可以删除,这个自定义View最后一个正方形提供可以添加图片的功能,每添加一个图片都排列在前面待选头像的后面。

花费时间:半天

完成之后的评价:1、需要优化,在父View是ScrollView或者UITableView的情况下,移动会不断调用layoutSubviews方法,性能不好,需要通过判断来处理优化这个逻辑。2、可以进入下一阶段实现更炫的交互动画体验,不过这个比较花时间。

第一阶段效果展示:

 

后来在新的项目中也成功的运用了:

 接着上源码吧:

BulletBox.h

 1 //
 2 //  BulletBox.h
 3 //  BulletBox
 4 //
 5 //  Created by HEYANG on 16/8/19.
 6 //  Copyright © 2016年 HeYang. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 /*
11  *********************************************************************************
12  * 🌟🌟🌟 Bullet子弹 🌟🌟🌟
13  * 需求:尽可能的封装,对外提供最简单的需求需要的接口
14  *********************************************************************************
15  */
16 @interface Bullet : UIView
17 
18 @property (nonatomic,weak)UIImageView *bulletImageView;
19 @property (nonatomic,assign)BOOL isDoCircleFrame;// 是否需要设置圆边框
20 
21 @end
22 
23 
24 /*
25  *********************************************************************************
26  * 🌟🌟🌟 BulletBox子弹盒 🌟🌟🌟
27  * 需求:等高等长的的,就用属性设置高度,不等高和长的,用代理方法,这里暂时不写出代理方法
28  * 模仿UITableView封装,公开数据源和代理方法
29  *********************************************************************************
30  */
31 
32 @protocol BulletBoxDataSource;
33 @protocol BulletBoxDelegate;
34 
35 @interface BulletBox : UIView
36 
37 @property (nonatomic,assign)CGFloat bulletBoxHeight;// 内部都是正方形,所以只要设置高
38 @property (nonatomic,weak)id<BulletBoxDataSource> datasource;
39 @property (nonatomic,weak)id<BulletBoxDelegate> delegate;
40 @property (nonatomic,assign)NSInteger bulletMaxCount;
41 @property (nonatomic,strong)NSMutableArray *imageArr;
42 @property (nonatomic,assign)CGFloat bulletSpace;
43 
44 // 更新图片数组,同时内部会根据数组刷新
45 - (void)updateImageArrs:(NSMutableArray*)imageArr;
46 
47 @end
48 
49 #pragma mark - 数据源方法+代理方法
50 @protocol BulletBoxDataSource <NSObject>
51 
52 @required
53 // 创建Bullet的数据源方法
54 - (Bullet*)bulletBox:(BulletBox*)bulletBox bulletIndex:(NSInteger)index;
55 @optional
56 // 创建最后一个额外样式的Bullet的数据源方法
57 - (Bullet*)addLastBulletInbulletBox:(BulletBox*)bulletBox;
58 
59 @end
60 
61 @protocol BulletBoxDelegate <NSObject>
62 
63 // 点击Bullet的代理方法,不包括最后一个额外样式的Bullet
64 - (void)bulletBox:(BulletBox*)bulletBox didSelectIndex:(NSInteger)index;
65 // 点击最后一个额外样式的代理方法
66 - (void)didSelectLastBullet:(BulletBox*)bulletBox;
67 
68 @end

BulletBox.m

  1 //
  2 //  BulletBox.m
  3 //  BulletBox
  4 //
  5 //  Created by HEYANG on 16/8/19.
  6 //  Copyright © 2016年 HeYang. All rights reserved.
  7 //
  8 
  9 #import "BulletBox.h"
 10 
 11 
 12 /*
 13  *********************************************************************************
 14  * 🌟🌟🌟 Bullet子弹 🌟🌟🌟
 15  *********************************************************************************
 16  */
 17 #pragma mark - Bullet
 18 @protocol BulletDelegate;
 19 
 20 @interface Bullet ()
 21 
 22 @property (nonatomic,assign)NSInteger index;
 23 @property (nonatomic,weak)id<BulletDelegate> delegate;
 24 
 25 @end
 26 
 27 @protocol BulletDelegate <NSObject>
 28 
 29 - (void)bullet:(Bullet*)bullet;
 30 
 31 @end
 32 
 33 @implementation Bullet
 34 
 35 - (instancetype)initWithFrame:(CGRect)frame
 36 {
 37     self = [super initWithFrame:frame];
 38     if (self) {
 39         UIImageView *imageView = [UIImageView new];
 40         [self addSubview:imageView];
 41         self.bulletImageView = imageView;
 42         self.backgroundColor = [UIColor clearColor];
 43         _isDoCircleFrame = NO;
 44     }
 45     return self;
 46 }
 47 
 48 - (void)addTapGestureRecognizer{
 49     // hy:先判断当前是否有交互事件,如果没有的话。。。所有gesture的交互事件都会被添加进gestureRecognizers中
 50     if (![self gestureRecognizers]) {
 51         self.userInteractionEnabled = YES;
 52         // hy:添加单击事件
 53         UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
 54         [self addGestureRecognizer:tap];
 55     }
 56 }
 57 
 58 - (void)tap{
 59     if (_delegate && [_delegate respondsToSelector:@selector(bullet:)]) {
 60         [_delegate bullet:self];
 61     }
 62 }
 63 
 64 - (void)layoutSubviews{
 65     self.bulletImageView.frame = self.bounds;
 66     if (_isDoCircleFrame) {
 67         self.bulletImageView.layer.masksToBounds = YES;
 68         self.bulletImageView.layer.cornerRadius = self.bulletImageView.frame.size.width/2;
 69         self.bulletImageView.layer.borderWidth = 1;
 70         self.bulletImageView.layer.borderColor = [UIColor whiteColor].CGColor;
 71     }
 72 }
 73 
 74 
 75 @end
 76 /*
 77  *********************************************************************************
 78  * 🌟🌟🌟 BulletBox子弹盒 🌟🌟🌟
 79  *********************************************************************************
 80 */
 81 #pragma mark - BulletBox
 82 @interface BulletBox () <BulletDelegate>
 83 
 84 
 85 
 86 @end
 87 
 88 @implementation BulletBox
 89 
 90 - (instancetype)initWithFrame:(CGRect)frame
 91 {
 92     
 93     self = [super initWithFrame:frame];
 94     if (self) {
 95         self.backgroundColor = [UIColor clearColor];
 96     }
 97     return self;
 98 }
 99 
100 - (void)layoutSubviews{
101     [super layoutSubviews];
102     DLog(@"重新布局");
103     NSInteger bulletCount = 0;
104     CGFloat bBH = 0.f;
105     if (_imageArr) {
106         // 获取子弹的数量
107         bulletCount = self.imageArr.count;
108         bulletCount = bulletCount>_bulletMaxCount?_bulletMaxCount:bulletCount;
109         _imageArr = [NSMutableArray arrayWithArray:[_imageArr subarrayWithRange:NSMakeRange(0, bulletCount)]];
110         DLog(@"%ld个子弹",bulletCount);
111         // 重新设置子弹盒的高度和长度
112         bBH = self.bulletBoxHeight;
113         CGRect frame = self.frame;
114         frame.size.height = bBH;
115         frame.size.width = (bBH+_bulletSpace) * bulletCount - _bulletSpace;
116         self.frame = frame;
117         // 添加子View之前,需要移除之前所有的子View
118         for (UIView* subview in self.subviews) {
119             [subview removeFromSuperview];
120         }
121         if (_datasource && [_datasource respondsToSelector:@selector(bulletBox:bulletIndex:)]){
122             for (NSInteger i=0; i<bulletCount; i++) {
123                 Bullet *bullet = [_datasource bulletBox:self bulletIndex:i];
124                 if (bullet) {
125                     [bullet addTapGestureRecognizer];
126                     bullet.delegate = self;
127                     bullet.index = i;
128                     bullet.frame = CGRectMake(i*(bBH+_bulletSpace), 0, bBH, bBH);
129                     [self addSubview:bullet];
130                 }
131             }
132         }
133     }
134     // 根据需求添加最后一个View,但是如果达到了Max,这个最后一个就不需要显示了
135     if (bulletCount < _bulletMaxCount) {
136         if (_datasource && [_datasource respondsToSelector:@selector(addLastBulletInbulletBox:)]){
137             Bullet *bullet = [_datasource addLastBulletInbulletBox:self];
138             if (bullet) {
139                 CGRect frame = self.frame;
140                 frame.size.width = (bBH+_bulletSpace) * (bulletCount+1) - _bulletSpace;
141                 self.frame = frame;
142                 if (![bullet gestureRecognizers]) {
143                     bullet.userInteractionEnabled = YES;
144                     // hy:添加单击事件
145                     UITapGestureRecognizer *bulletBoxTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(bulletBoxTap)];
146                     [bullet addGestureRecognizer:bulletBoxTap];
147                     bullet.frame = CGRectMake(bulletCount*(bBH+_bulletSpace), 0, bBH, bBH);
148                     [self addSubview:bullet];
149                 }
150             }
151         }
152     }
153     if (self.superview) {
154         CGPoint center = self.center;
155         center.x = self.superview.bounds.size.width*0.5;
156         self.center = center;
157     }
158 }
159 
160 #pragma mark - 代理方法
161 -(void)bullet:(Bullet *)bullet{
162     if (_delegate && [_delegate respondsToSelector:@selector(bulletBox:didSelectIndex:)]) {
163         [_delegate bulletBox:self didSelectIndex:bullet.index];
164     }
165 }
166 
167 #pragma mark - 懒加载
168 - (CGFloat)bulletBoxHeight{
169     if (_bulletBoxHeight <= 0) {
170         _bulletBoxHeight = 50;
171     }
172     return _bulletBoxHeight;
173 }
174 
175 #pragma mark - 私有方法
176 - (void)bulletBoxTap{
177     if (_delegate && [_delegate respondsToSelector:@selector(didSelectLastBullet:)]) {
178         [_delegate didSelectLastBullet:self];
179     }
180 }
181 
182 #pragma mark - public 
183 //- (void)removeBulletIndex:(NSInteger)index{
184 //    [self.imageArr removeObjectAtIndex:index];
185 //    [self setNeedsLayout];
186 //}
187 //- (void)insertBulletInLast:(NSString*)bulletImage{
188 //    [self.imageArr addObject:bulletImage];
189 //    [self setNeedsLayout];
190 //}
191 - (void)updateImageArrs:(NSMutableArray*)imageArr{
192     for (NSString *strURL in imageArr) {
193         DLog(@"str:%@",strURL);
194     }
195     self.imageArr = imageArr;
196     [self setNeedsLayout];
197 }
198 
199 
200 @end

 

posted @ 2016-08-20 03:37  何杨  阅读(417)  评论(0编辑  收藏  举报