iOS開發之功能模塊--根據需求開發橫向的子彈盒View

這個需求是本人工做開發中後期需求要添加的新功能,本人模仿UITableView的代理和數據源方法進行了第一階段的開發。第二階段是添加豐富的動畫。數組

這個功能需求描述:能上傳添加五個待選頭像,五個頭像分別均可以被設置爲app的正式頭像和展現封面,五個頭像分別均可以刪除,這個自定義View最後一個正方形提供能夠添加圖片的功能,每添加一個圖片都排列在前面待選頭像的後面。app

花費時間:半天佈局

完成以後的評價:一、須要優化,在父View是ScrollView或者UITableView的狀況下,移動會不斷調用layoutSubviews方法,性能很差,須要經過判斷來處理優化這個邏輯。二、能夠進入下一階段實現更炫的交互動畫體驗,不過這個比較花時間。性能

第一階段效果展現:優化

 

後來在新的項目中也成功的運用了:動畫

 接着上源碼吧:ui

BulletBox.hatom

 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.mspa

  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
相關文章
相關標籤/搜索