Commit 43b0a017a01f8baa25b8cfc98c108204fa5e9ba8

Authored by 张旭
1 parent 36700c28

完善豪华礼物,连击礼物

Showing 25 changed files with 1245 additions and 342 deletions
LiveVideoCloud/LiveVideoCloud.xcodeproj/project.pbxproj
... ... @@ -125,15 +125,16 @@
125 125 D2029D091E6EAE2E0027CD92 /* Foundation+Log.m in Sources */ = {isa = PBXBuildFile; fileRef = D2029CF21E6EAE2E0027CD92 /* Foundation+Log.m */; };
126 126 D2029D0A1E6EAE2E0027CD92 /* ZXServerUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = D2029CFE1E6EAE2E0027CD92 /* ZXServerUrl.m */; };
127 127 D2029D161E6EB00D0027CD92 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D2029D151E6EB00D0027CD92 /* AppDelegate.m */; };
  128 + D217A24A1E7B76C7003B44CB /* PresentView.m in Sources */ = {isa = PBXBuildFile; fileRef = D217A2471E7B76C7003B44CB /* PresentView.m */; };
  129 + D217A24B1E7B76C7003B44CB /* PresentViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D217A2491E7B76C7003B44CB /* PresentViewCell.m */; };
  130 + D217A24E1E7B77C7003B44CB /* ComboCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D217A24D1E7B77C7003B44CB /* ComboCell.m */; };
128 131 D22830F11E778C0F00627701 /* LiveBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22830F01E778C0F00627701 /* LiveBaseView.m */; };
129 132 D22830FC1E77C2D900627701 /* BottomToolView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22830FB1E77C2D900627701 /* BottomToolView.m */; };
130 133 D22830FF1E77C69E00627701 /* GiftListView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22830FE1E77C69E00627701 /* GiftListView.m */; };
131   - D22831021E77D83C00627701 /* GiftModelView.m in Sources */ = {isa = PBXBuildFile; fileRef = D22831011E77D83C00627701 /* GiftModelView.m */; };
132 134 D22831091E77D8D500627701 /* GiftModel.m in Sources */ = {isa = PBXBuildFile; fileRef = D22831081E77D8D500627701 /* GiftModel.m */; };
133 135 D25530001E7909AC00DF38A5 /* GiftAnimOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D2552FFF1E7909AC00DF38A5 /* GiftAnimOperation.m */; };
134 136 D25530031E79115100DF38A5 /* AnimQueueManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D25530021E79115100DF38A5 /* AnimQueueManager.m */; };
135 137 D25530061E7911A800DF38A5 /* GiftAnimationAction.m in Sources */ = {isa = PBXBuildFile; fileRef = D25530051E7911A800DF38A5 /* GiftAnimationAction.m */; };
136   - D25530091E791A7100DF38A5 /* GiftComboView.m in Sources */ = {isa = PBXBuildFile; fileRef = D25530081E791A7100DF38A5 /* GiftComboView.m */; };
137 138 D255300C1E793F8200DF38A5 /* NHFighterView+animDelegagte.m in Sources */ = {isa = PBXBuildFile; fileRef = D255300B1E793F8200DF38A5 /* NHFighterView+animDelegagte.m */; };
138 139 D2575C461E76857100E3A8FC /* LVCAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D2575C451E76857100E3A8FC /* LVCAnimationManager.m */; };
139 140 D2575C4A1E7685DE00E3A8FC /* UIView+Bubbling.m in Sources */ = {isa = PBXBuildFile; fileRef = D2575C481E7685DE00E3A8FC /* UIView+Bubbling.m */; };
... ... @@ -434,14 +435,19 @@
434 435 D2029CFF1E6EAE2E0027CD92 /* UtilKits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UtilKits.h; sourceTree = "<group>"; };
435 436 D2029D121E6EAF8D0027CD92 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
436 437 D2029D151E6EB00D0027CD92 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
  438 + D217A2451E7B76C7003B44CB /* PresentModelAble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentModelAble.h; sourceTree = "<group>"; };
  439 + D217A2461E7B76C7003B44CB /* PresentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentView.h; sourceTree = "<group>"; };
  440 + D217A2471E7B76C7003B44CB /* PresentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentView.m; sourceTree = "<group>"; };
  441 + D217A2481E7B76C7003B44CB /* PresentViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentViewCell.h; sourceTree = "<group>"; };
  442 + D217A2491E7B76C7003B44CB /* PresentViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentViewCell.m; sourceTree = "<group>"; };
  443 + D217A24C1E7B77C7003B44CB /* ComboCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComboCell.h; sourceTree = "<group>"; };
  444 + D217A24D1E7B77C7003B44CB /* ComboCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ComboCell.m; sourceTree = "<group>"; };
437 445 D22830EF1E778C0F00627701 /* LiveBaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveBaseView.h; sourceTree = "<group>"; };
438 446 D22830F01E778C0F00627701 /* LiveBaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveBaseView.m; sourceTree = "<group>"; };
439 447 D22830FA1E77C2D900627701 /* BottomToolView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BottomToolView.h; sourceTree = "<group>"; };
440 448 D22830FB1E77C2D900627701 /* BottomToolView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BottomToolView.m; sourceTree = "<group>"; };
441 449 D22830FD1E77C69E00627701 /* GiftListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftListView.h; sourceTree = "<group>"; };
442 450 D22830FE1E77C69E00627701 /* GiftListView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiftListView.m; sourceTree = "<group>"; };
443   - D22831001E77D83C00627701 /* GiftModelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftModelView.h; sourceTree = "<group>"; };
444   - D22831011E77D83C00627701 /* GiftModelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiftModelView.m; sourceTree = "<group>"; };
445 451 D22831071E77D8D500627701 /* GiftModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftModel.h; sourceTree = "<group>"; };
446 452 D22831081E77D8D500627701 /* GiftModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiftModel.m; sourceTree = "<group>"; };
447 453 D2552FFE1E7909AC00DF38A5 /* GiftAnimOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftAnimOperation.h; sourceTree = "<group>"; };
... ... @@ -450,8 +456,6 @@
450 456 D25530021E79115100DF38A5 /* AnimQueueManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnimQueueManager.m; sourceTree = "<group>"; };
451 457 D25530041E7911A800DF38A5 /* GiftAnimationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftAnimationAction.h; sourceTree = "<group>"; };
452 458 D25530051E7911A800DF38A5 /* GiftAnimationAction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiftAnimationAction.m; sourceTree = "<group>"; };
453   - D25530071E791A7100DF38A5 /* GiftComboView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiftComboView.h; sourceTree = "<group>"; };
454   - D25530081E791A7100DF38A5 /* GiftComboView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiftComboView.m; sourceTree = "<group>"; };
455 459 D255300A1E793F8200DF38A5 /* NHFighterView+animDelegagte.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NHFighterView+animDelegagte.h"; sourceTree = "<group>"; };
456 460 D255300B1E793F8200DF38A5 /* NHFighterView+animDelegagte.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NHFighterView+animDelegagte.m"; sourceTree = "<group>"; };
457 461 D2575C441E76857100E3A8FC /* LVCAnimationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LVCAnimationManager.h; path = ../LVCAnimationManager.h; sourceTree = "<group>"; };
... ... @@ -1186,13 +1190,25 @@
1186 1190 path = AppDelegate;
1187 1191 sourceTree = "<group>";
1188 1192 };
  1193 + D217A2441E7B76C7003B44CB /* Present */ = {
  1194 + isa = PBXGroup;
  1195 + children = (
  1196 + D217A2451E7B76C7003B44CB /* PresentModelAble.h */,
  1197 + D217A2461E7B76C7003B44CB /* PresentView.h */,
  1198 + D217A2471E7B76C7003B44CB /* PresentView.m */,
  1199 + D217A2481E7B76C7003B44CB /* PresentViewCell.h */,
  1200 + D217A2491E7B76C7003B44CB /* PresentViewCell.m */,
  1201 + D217A24C1E7B77C7003B44CB /* ComboCell.h */,
  1202 + D217A24D1E7B77C7003B44CB /* ComboCell.m */,
  1203 + );
  1204 + path = Present;
  1205 + sourceTree = "<group>";
  1206 + };
1189 1207 D22830F51E77C24900627701 /* GiftViews */ = {
1190 1208 isa = PBXGroup;
1191 1209 children = (
1192 1210 D22830FD1E77C69E00627701 /* GiftListView.h */,
1193 1211 D22830FE1E77C69E00627701 /* GiftListView.m */,
1194   - D22831001E77D83C00627701 /* GiftModelView.h */,
1195   - D22831011E77D83C00627701 /* GiftModelView.m */,
1196 1212 );
1197 1213 path = GiftViews;
1198 1214 sourceTree = "<group>";
... ... @@ -1267,8 +1283,7 @@
1267 1283 D2575C681E76A42B00E3A8FC /* Gift */ = {
1268 1284 isa = PBXGroup;
1269 1285 children = (
1270   - D25530071E791A7100DF38A5 /* GiftComboView.h */,
1271   - D25530081E791A7100DF38A5 /* GiftComboView.m */,
  1286 + D217A2441E7B76C7003B44CB /* Present */,
1272 1287 D25530041E7911A800DF38A5 /* GiftAnimationAction.h */,
1273 1288 D25530051E7911A800DF38A5 /* GiftAnimationAction.m */,
1274 1289 D25530011E79115100DF38A5 /* AnimQueueManager.h */,
... ... @@ -1563,7 +1578,6 @@
1563 1578 isa = PBXSourcesBuildPhase;
1564 1579 buildActionMask = 2147483647;
1565 1580 files = (
1566   - D25530091E791A7100DF38A5 /* GiftComboView.m in Sources */,
1567 1581 D2029CC31E6EADE10027CD92 /* UIImageView+HighlightedWebCache.m in Sources */,
1568 1582 D22830FF1E77C69E00627701 /* GiftListView.m in Sources */,
1569 1583 D2029CC01E6EADE10027CD92 /* UIImage+GIF.m in Sources */,
... ... @@ -1603,6 +1617,7 @@
1603 1617 D2029CA11E6EADE10027CD92 /* NSString+MJExtension.m in Sources */,
1604 1618 D2029BCB1E6EADD70027CD92 /* BaseTableViewCell.m in Sources */,
1605 1619 D2029CAA1E6EADE10027CD92 /* MJRefreshBackGifFooter.m in Sources */,
  1620 + D217A24B1E7B76C7003B44CB /* PresentViewCell.m in Sources */,
1606 1621 D2029C9B1E6EADE10027CD92 /* MJPropertyKey.m in Sources */,
1607 1622 D2029CBF1E6EADE10027CD92 /* UIButton+WebCache.m in Sources */,
1608 1623 810B64E31E779AFE00133E15 /* LVCLivePlayerController.m in Sources */,
... ... @@ -1617,7 +1632,6 @@
1617 1632 D2029CA31E6EADE10027CD92 /* MJRefreshBackFooter.m in Sources */,
1618 1633 D255300C1E793F8200DF38A5 /* NHFighterView+animDelegagte.m in Sources */,
1619 1634 D2575C4A1E7685DE00E3A8FC /* UIView+Bubbling.m in Sources */,
1620   - D22831021E77D83C00627701 /* GiftModelView.m in Sources */,
1621 1635 D2029CA61E6EADE10027CD92 /* MJRefreshHeader.m in Sources */,
1622 1636 D2029CC41E6EADE10027CD92 /* UIImageView+WebCache.m in Sources */,
1623 1637 D2029CC81E6EADE10027CD92 /* SVProgressAnimatedView.m in Sources */,
... ... @@ -1661,6 +1675,7 @@
1661 1675 D2029CCA1E6EADE10027CD92 /* SVProgressHUD.m in Sources */,
1662 1676 D2029CA81E6EADE10027CD92 /* MJRefreshAutoNormalFooter.m in Sources */,
1663 1677 D2029C891E6EADE10027CD92 /* AFSecurityPolicy.m in Sources */,
  1678 + D217A24A1E7B76C7003B44CB /* PresentView.m in Sources */,
1664 1679 D22830F11E778C0F00627701 /* LiveBaseView.m in Sources */,
1665 1680 D2029CBA1E6EADE10027CD92 /* SDWebImageDecoder.m in Sources */,
1666 1681 8112D4311E7927A5002E00F6 /* LVCPlayerLoadingView.m in Sources */,
... ... @@ -1673,6 +1688,7 @@
1673 1688 D2888D9E1E6EBF1B003A77C8 /* LVCLiveViewController.m in Sources */,
1674 1689 D2029C951E6EADE10027CD92 /* UIWebView+AFNetworking.m in Sources */,
1675 1690 810B650A1E77B39D00133E15 /* LVCFullScreenPlayerController.m in Sources */,
  1691 + D217A24E1E7B77C7003B44CB /* ComboCell.m in Sources */,
1676 1692 D2029CBD1E6EADE10027CD92 /* SDWebImageManager.m in Sources */,
1677 1693 D2029CB41E6EADE10027CD92 /* UIView+MJExtension.m in Sources */,
1678 1694 81FB5B3C1E7A6FFC00F98E1D /* SevenSwitch.m in Sources */,
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/AnimQueueManager.h
... ... @@ -9,11 +9,9 @@
9 9 #import <Foundation/Foundation.h>
10 10  
11 11 @class GiftModel;
  12 +@class PresentView;
12 13 @interface AnimQueueManager : NSObject
13 14  
14   -@property (nonatomic, assign)NSInteger maxTop; //初始位置(需要根据显示设置最低位置在哪里)
15   -//@property (nonatomic, strong)NSMutableArray *arGiftArray; //横幅的数量,用于轨道计算(现在结构是一维数组,因为轨道中的弹道只有1个,如果是多个的话需要变为二维数组)
16   -
17 15 /**
18 16 初始化管理类
19 17 @return 当前manager
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/AnimQueueManager.m
... ... @@ -9,10 +9,13 @@
9 9 #import "AnimQueueManager.h"
10 10 #import "GiftAnimOperation.h"
11 11 #import "GiftModel.h"
  12 +#import "PresentView.h"
  13 +
  14 +#import "LiveBaseView.h"
  15 +#import "PresentView.h"
12 16  
13 17 @interface AnimQueueManager ()
14 18  
15   -@property (nonatomic, assign)NSInteger maxOperationCount; //并发数
16 19 @property (nonatomic,strong) NSOperationQueue *comboAnimationQueue; //连击动画队列
17 20 @property (nonatomic,strong) NSOperationQueue *expenAnimationQueue; //豪华礼物动画队列
18 21  
... ... @@ -31,26 +34,11 @@
31 34 static dispatch_once_t onceToken;
32 35 dispatch_once(&onceToken, ^{
33 36 manager = [[AnimQueueManager alloc] init];
34   - manager.maxOperationCount = 2;
35   -// manager.arGiftArray = [NSMutableArray arrayWithObjects:@200,@240,@280, nil];
36 37 });
37 38 return manager;
38 39 }
39 40  
40 41 /**
41   - 连击动画队列
42   -
43   - @return 队列obj
44   - */
45   -- (NSOperationQueue *)comboAnimationQueue{
46   - if (_comboAnimationQueue == nil) {
47   - _comboAnimationQueue = [[NSOperationQueue alloc] init];
48   - _comboAnimationQueue.maxConcurrentOperationCount = 3;
49   - }
50   - return _comboAnimationQueue;
51   -}
52   -
53   -/**
54 42 豪华动画队列
55 43  
56 44 @return 队列obj
... ... @@ -70,27 +58,27 @@
70 58 */
71 59 - (void)addAnimationWithModel:(GiftModel *)model animContentView:(UIView *)animContentView{
72 60  
73   - GiftAnimOperation *op = [GiftAnimOperation addGiftAnimOperationWithGiftModel:model animContentView:animContentView maxTop:self.maxTop];
74   - NSInteger index = self.comboAnimationQueue.operationCount;
75   - NSLog(@"index:%zd",index);
76 61 switch (model.giftStyle) {
77 62 case GiftStylePorsch:
  63 + {
  64 + GiftAnimOperation *op = [GiftAnimOperation addGiftAnimOperationWithGiftModel:model animContentView:animContentView];
78 65 [self.expenAnimationQueue addOperation:op];
  66 + }
79 67 break;
80 68 // case GiftStyleFighter:
81 69 // [self.expenAnimationQueue addOperation:op];
82 70 // break;
83 71 case GiftStylePlane:
  72 + {
  73 + GiftAnimOperation *op = [GiftAnimOperation addGiftAnimOperationWithGiftModel:model animContentView:animContentView];
84 74 [self.expenAnimationQueue addOperation:op];
  75 + }
85 76 break;
  77 +
86 78 case GiftStyleCombo:
87 79 {
88   - [self.comboAnimationQueue addOperation:op];
89   -// int i = rand()%4;
90   -// op.name = i >0 ? @"张三_love" : @"李四_flower";//name imagename
91   -// self.comboAnimationQueue.suspended;
92   - }
93   -
  80 + [(PresentView *)animContentView insertPresentMessages:@[model] showShakeAnimation:YES];
  81 + }
94 82 break;
95 83 default:
96 84 break;
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftAnimOperation.h
... ... @@ -13,6 +13,6 @@
13 13  
14 14 @interface GiftAnimOperation : NSOperation
15 15  
16   -+ (GiftAnimOperation *)addGiftAnimOperationWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView maxTop:(NSInteger)maxTop;
  16 ++ (GiftAnimOperation *)addGiftAnimOperationWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView;
17 17  
18 18 @end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftAnimOperation.m
... ... @@ -8,7 +8,6 @@
8 8  
9 9 #import "GiftAnimOperation.h"
10 10 #import "GiftModel.h"
11   -#import "GiftComboView.h"
12 11 #import "NHCarViews.h"
13 12 #import "NHPlaneViews.h"
14 13 #import "GiftAnimationAction.h"
... ... @@ -21,24 +20,19 @@
21 20 BOOL _executing; //队列任务开始执行
22 21 }
23 22  
24   -@property (nonatomic, strong)GiftComboView *giftComboView; //连击动画
25 23 @property (nonatomic, strong)NHCarViews *giftCarView; //跑车动画
26 24 //@property (nonatomic, strong)NHFighterView *giftFighterView; //歼灭机动画
27 25 @property (nonatomic, strong)NHPlaneViews *giftPlaneView; //客机动画
28   -
29 26 @property (nonatomic, strong)GiftModel *model; //model
30 27 @property (nonatomic,strong) UIView *animContentView; //需要显示动画的view
31   -@property (nonatomic, assign)NSInteger maxTop; //初始位置(需要根据显示设置最低位置在哪里)
32   -@property (nonatomic ,strong) NSArray * _Nullable defaultTrajory;//默认轨迹数组
33   -@property (nonatomic ,strong) NSMutableArray * _Nullable emptyTrajory;//当前空轨迹数组
34 28  
35 29 @end
36 30  
37 31 @implementation GiftAnimOperation
38 32  
39   -+ (GiftAnimOperation *)addGiftAnimOperationWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView maxTop:(NSInteger)maxTop{
  33 ++ (GiftAnimOperation *)addGiftAnimOperationWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView{
40 34  
41   - GiftAnimOperation *giftAnimOperation = [[GiftAnimOperation alloc]initWithGiftModel:model animContentView:animContentView maxTop:maxTop];
  35 + GiftAnimOperation *giftAnimOperation = [[GiftAnimOperation alloc]initWithGiftModel:model animContentView:animContentView];
42 36 return giftAnimOperation;
43 37 }
44 38  
... ... @@ -49,12 +43,11 @@
49 43 @param animContentView 需要把动画view添加到的view
50 44 @return obj
51 45 */
52   -- (instancetype)initWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView maxTop:(NSInteger)maxTop{
  46 +- (instancetype)initWithGiftModel:(GiftModel *)model animContentView:(UIView *)animContentView{
53 47 self = [super init];
54 48 if (self) {
55 49 self.model = model;
56 50 self.animContentView = animContentView;
57   - self.maxTop = maxTop;
58 51 }
59 52 return self;
60 53 }
... ... @@ -85,9 +78,7 @@
85 78 case GiftStylePlane:
86 79 [self planeAnimation];
87 80 break;
88   - case GiftStyleCombo:
89   - [self comboViewAnimation];
90   - break;
  81 +
91 82 default:
92 83 break;
93 84 }
... ... @@ -141,6 +132,7 @@
141 132  
142 133 [self.giftPlaneView addAnimationsMoveToPoint:CGPointMake(SCREEN_WIDTH, 100) endPoint:CGPointMake(-500, 410)];
143 134 [self.animContentView addSubview:self.giftPlaneView];
  135 +
144 136 [self.giftPlaneView startPlaneAnimationWithCompletion:^{
145 137  
146 138 [self willChangeValueForKey:@"isFinished"];
... ... @@ -153,70 +145,6 @@
153 145 });
154 146 }
155 147  
156   -static long currentCompleteIndex = 0;
157   -/**
158   - 连击动画
159   - */
160   -- (void)comboViewAnimation{
161   -
162   - __weak GiftAnimOperation *weakSelf = self;
163   -// currentCompleteIndex ++;
164   -
165   -// if (self.emptyTrajory.count == 0)//index = 0
166   -// {
167   -// currentCompleteIndex = 0;
168   -//
169   -// }else if (self.emptyTrajory.count < 3)//从emptyArr取空的index并赋值 index
170   -// {
171   -//
172   -//
173   -// }else// = 3已满 index = 0
174   -// {
175   -// currentCompleteIndex = 0;
176   -// }
177   -// self.name = @"111";
178   - dispatch_async(dispatch_get_main_queue(), ^{
179   - [weakSelf.animContentView addSubview:weakSelf.giftComboView];
180   -
181   - weakSelf.giftComboView.top = [self.defaultTrajory[currentCompleteIndex] integerValue];
182   -
183   - NSLog(@"top:%zd,index%ld",[self.defaultTrajory[currentCompleteIndex] integerValue],currentCompleteIndex);
184   - currentCompleteIndex ++;
185   - if (currentCompleteIndex == 3)
186   - {
187   - currentCompleteIndex = 0;
188   - }
189   -// if ([self.name isEqualToString:@"李四_flower"]) {
190   -//// currentCompleteIndex = 0;
191   -// self.
192   -// }
193   - [weakSelf.giftComboView startComboAnimationWithCompletion:^{
194   - NSLog(@"complet top:%zd,index%zd",[self.defaultTrajory[currentCompleteIndex] integerValue],currentCompleteIndex);
195   - //empty存当前顺序
196   -// [self.emptyTrajory replaceObjectAtIndex:<#(NSUInteger)#> withObject:<#(nonnull id)#>];
197   - [weakSelf.giftComboView removeFromSuperview];
198   -
199   - [weakSelf willChangeValueForKey:@"isFinished"];
200   -
201   - _finished = YES;
202   -
203   - [weakSelf didChangeValueForKey:@"isFinished"];
204   - }];
205   - });
206   -}
207   -
208   -/**
209   - 连击动画
210   -
211   - @return 连击view
212   - */
213   -- (GiftComboView *)giftComboView{
214   - if (_giftComboView == nil) {
215   - _giftComboView = [GiftComboView comboView];
216   - }
217   - return _giftComboView;
218   -}
219   -
220 148 /**
221 149 跑车动画
222 150  
... ... @@ -260,24 +188,6 @@ static long currentCompleteIndex = 0;
260 188 return _giftPlaneView;
261 189 }
262 190  
263   -- (NSArray *)defaultTrajory
264   -{
265   - if (!_defaultTrajory)
266   - {
267   - _defaultTrajory = [[NSArray alloc] initWithObjects:@200,@240,@280, nil];
268   - }
269   - return _defaultTrajory;
270   -}
271   -
272   -- (NSMutableArray *)emptyTrajory
273   -{
274   - if (!_emptyTrajory)
275   - {
276   - _emptyTrajory = [[NSMutableArray alloc] init];
277   - }
278   - return _emptyTrajory;
279   -}
280   -
281 191 // 提示:To be deprecated; use and override 'asynchronous' below
282 192 //之前用的isConcurrent
283 193 /**
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftAnimationAction.h
... ... @@ -18,11 +18,6 @@ typedef void(^giftAnimationCompletion)();
18 18 }
19 19  
20 20 /**
21   - 连击动画
22   - */
23   -- (void)startComboAnimationWithCompletion:(giftAnimationCompletion)Completion;
24   -
25   -/**
26 21 跑车动画
27 22 */
28 23 - (void)startPorschAnimationWithCompletion:(giftAnimationCompletion)Completion;
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftAnimationAction.m
... ... @@ -15,7 +15,6 @@
15 15 */
16 16 - (void)startComboAnimationWithCompletion:(giftAnimationCompletion)Completion{
17 17 _giftAnimationCompletion = Completion;
18   - NSLog(@"self.width:%f",self.width);
19 18 [self animationWithDuration:4
20 19 YValues:@[@(0 - self.width), @(115), @(110), @(110), @(0 - self.width)]
21 20 keyTimes:@[@0.0, @0.2, @0.3, @0.8, @1.0]
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftComboView.h deleted 100644 → 0
1   -//
2   -// GiftComboView.h
3   -// LiveVideoCloud
4   -//
5   -// Created by 张旭 on 2017/3/15.
6   -// Copyright © 2017年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "GiftAnimationAction.h"
10   -
11   -@class GiftModel;
12   -@interface GiftComboView : GiftAnimationAction
13   -
14   -/**
15   - 动画开始
16   -
17   - @param model 对应的动画解析model
18   - @param animationCompletion 动画完成回调(用于控制队列)
19   - */
20   -- (void)startAnimationWithModel:(GiftModel *)model withAnimationCompletion: (giftAnimationCompletion)animationCompletion;
21   -
22   -+ (instancetype)comboView;
23   -
24   -@end
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftComboView.m deleted 100644 → 0
1   -//
2   -// GiftComboView.m
3   -// LiveVideoCloud
4   -//
5   -// Created by 张旭 on 2017/3/15.
6   -// Copyright © 2017年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "GiftComboView.h"
10   -#import "GiftModel.h"
11   -
12   -@interface GiftComboView (){
13   - GiftModel *_model;//礼物model
14   -}
15   -
16   -@end
17   -
18   -@implementation GiftComboView
19   -
20   -/**
21   - 动画开始
22   -
23   - @param model 对应的动画解析model
24   - @param animationCompletion 动画完成回调(用于控制队列)
25   - */
26   -- (void)startAnimationWithModel:(GiftModel *)model withAnimationCompletion: (giftAnimationCompletion)animationCompletion
27   -{
28   - _giftAnimationCompletion = animationCompletion;
29   - _model = model;
30   -
31   - [self startComboAnimationWithCompletion:animationCompletion];
32   -}
33   -
34   -
35   -/**
36   - 初始化连击View
37   -
38   - @return 初始化连击ComboView
39   - */
40   -+ (instancetype)comboView
41   -{
42   - GiftComboView *comboView = [[GiftComboView alloc] initWithFrame:CGRectMake(0, 0, 180, 30)];
43   - comboView.backgroundColor = [UIColor blueColor];
44   -
45   - return comboView;
46   -}
47   -
48   -/*
49   -// Only override drawRect: if you perform custom drawing.
50   -// An empty implementation adversely affects performance during animation.
51   -- (void)drawRect:(CGRect)rect {
52   - // Drawing code
53   -}
54   -*/
55   -
56   -@end
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftModel/GiftModel.h
... ... @@ -7,7 +7,7 @@
7 7 //
8 8  
9 9 #import "BaseModel.h"
10   -
  10 +#import "PresentModelAble.h"
11 11 typedef NS_ENUM(NSInteger, GiftStyle) {//礼物类型
12 12 GiftStyleCombo = 1,//普通可连击礼物
13 13 GiftStylePorsch ,//豪华跑车礼物
... ... @@ -15,21 +15,28 @@ typedef NS_ENUM(NSInteger, GiftStyle) {//礼物类型
15 15 GiftStylePlane ,//豪华客机礼物
16 16 };
17 17  
18   -@interface GiftModel : BaseModel
  18 +@interface GiftModel : BaseModel <PresentModelAble>
  19 +@property (copy, nonatomic) NSString *_Nullable sender;//送礼人
  20 +@property (copy, nonatomic) NSString *_Nullable giftName;//礼物名称
  21 +@property (copy, nonatomic) NSString *_Nullable icon;//送礼头像
  22 +@property (copy, nonatomic) NSString *_Nullable giftImageName;//礼物图片名字
  23 +@property (assign, nonatomic) NSInteger giftNumber;//礼物数量
19 24  
20   -@property (nonatomic ,copy ) NSString * _Nullable image;
  25 +//可本地处理
21 26 @property (nonatomic ,copy ) NSString * _Nullable price;
22   -
23   -@property (nonatomic ) NSInteger index;//索引
24 27 @property (nonatomic ) GiftStyle giftStyle;//动画类型
25   -@property (nonatomic, copy ) NSString * _Nullable giftname;//礼物名字
26   -@property (nonatomic, strong) NSArray * _Nullable giftIconArray;//礼物图片数组
27   -@property (nonatomic, copy ) NSString * _Nullable giftNum;//礼物数量
28   -@property (nonatomic, copy ) NSString * _Nullable giftRusername;//接受礼物的人
29   -@property (nonatomic, copy ) NSString * _Nullable giftRuserId;//接受礼物的人id
30   -@property (nonatomic, copy ) NSString * _Nullable giftGusername;//送礼物的人
31   -@property (nonatomic, copy ) NSString * _Nullable giftGuserId;//送礼物的id
  28 +@property (nonatomic ) NSInteger index;//索引和giftname一样
  29 +
  30 +//@property (nonatomic, copy ) NSString * _Nullable giftname;//礼物名字
  31 +//@property (nonatomic, strong) NSArray * _Nullable giftIconArray;//礼物图片数组
  32 +//@property (nonatomic, copy ) NSString * _Nullable giftNum;//礼物数量
  33 +//@property (nonatomic, copy ) NSString * _Nullable giftRusername;//接受礼物的人
  34 +//@property (nonatomic, copy ) NSString * _Nullable giftRuserId;//接受礼物的人id
  35 +//@property (nonatomic, copy ) NSString * _Nullable giftGusername;//送礼物的人
  36 +//@property (nonatomic, copy ) NSString * _Nullable giftGuserId;//送礼物的id
32 37  
33 38 //@property (nonatomic, strong) NSString *_Nullable pushId;//跳转id
34 39  
  40 ++ (instancetype _Nonnull)modelWithSender:(NSString *_Nonnull)sender giftName:(NSString *_Nonnull)giftName icon:(NSString *_Nonnull)icon giftImageName:(NSString *_Nonnull)giftImageName;
  41 +
35 42 @end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftModel/GiftModel.m
... ... @@ -9,5 +9,13 @@
9 9 #import "GiftModel.h"
10 10  
11 11 @implementation GiftModel
12   -
  12 ++ (instancetype)modelWithSender:(NSString *)sender giftName:(NSString *)giftName icon:(NSString *)icon giftImageName:(NSString *)giftImageName
  13 +{
  14 + GiftModel *model = [[GiftModel alloc] init];
  15 + model.sender = sender;
  16 + model.giftName = giftName;
  17 + model.icon = icon;
  18 + model.giftImageName = giftImageName;
  19 + return model;
  20 +}
13 21 @end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftResource/NHCarViews.m
... ... @@ -138,7 +138,7 @@
138 138 [self.layer removeAllAnimations];
139 139 [self removeFromSuperview];
140 140  
141   - _giftAnimationCompletion(-1);
  141 + _giftAnimationCompletion();
142 142 NSLog(@"删除动画");
143 143 // [self.animations removeObjectAtIndex:0];
144 144  
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftResource/NHPlaneViews.m
... ... @@ -80,7 +80,7 @@
80 80 -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
81 81 [self.layer removeAllAnimations];
82 82 [self removeFromSuperview];
83   - _giftAnimationCompletion(-1);
  83 + _giftAnimationCompletion();
84 84 }
85 85  
86 86  
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftViews/GiftListView.m
... ... @@ -16,10 +16,10 @@
16 16  
17 17 @interface GiftListView ()
18 18  
19   -@property (nonatomic ,strong) NSArray <GiftModel *>* _Nullable giftArray;
20   -@property (nonatomic ,weak) LiveBaseView * _Nullable liveBaseView;
21   -@property (nonatomic, strong) AnimQueueManager *animQueueManager;
22   -@property (nonatomic ,strong) GiftModel * _Nullable model;
  19 +@property (nonatomic ,strong) NSArray <GiftModel *>* _Nullable giftArray;
  20 +@property (nonatomic ,weak ) LiveBaseView * _Nullable liveBaseView;
  21 +@property (nonatomic, strong) AnimQueueManager * animQueueManager;
  22 +@property (nonatomic ,strong) GiftModel * _Nullable model;
23 23  
24 24 @end
25 25  
... ... @@ -30,7 +30,6 @@
30 30 if (self = [super initWithFrame:frame]) {
31 31 self.liveBaseView = liveBaseView;
32 32 self.animQueueManager = [AnimQueueManager sharedAnimQueueManager];
33   - self.animQueueManager.maxTop = 200;
34 33  
35 34 UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height - 30)];
36 35 scrollView.contentSize = CGSizeMake(self.width *(self.giftArray.count/(MAX_ROW_COUNT*MAX_LINE_COUNT) + 1), self.height - 30);
... ... @@ -63,7 +62,8 @@
63 62  
64 63 UIView *giftView = [self giftViewWithFrame:CGRectMake(giftX, giftY, giftWidth, giftHeight) model:self.giftArray[i]];
65 64  
66   - UIImageView *picImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.giftArray[i].image]];
  65 + //礼物图片
  66 + UIImageView *picImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.giftArray[i].giftImageName]];
67 67 picImg.centerX = giftView.width * 0.5;
68 68 picImg.centerY = giftView.height * 0.5;
69 69 [giftView addSubview:picImg];
... ... @@ -86,11 +86,12 @@
86 86 {
87 87 UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(giftView.width - 17, 3, 15, 15)];
88 88 imageView.backgroundColor = ZXRandomColor;
89   - [giftView addSubview:imageView];
  89 + [giftView addSubview:imageView];//右上角连击标识
90 90 }else
91 91 {
92 92  
93 93 }
  94 + //礼物价格lbl
94 95 UILabel *priceLbl = [[UILabel alloc] initWithFrame:CGRectMake(0, giftView.height - 15, 40, 14)];
95 96 priceLbl.font = [UIFont systemFontOfSize:kDetailContentFont];
96 97 priceLbl.textColor = [UIColor greenColor];
... ... @@ -99,7 +100,7 @@
99 100 priceLbl.height = [priceLbl labelSize].height;
100 101 priceLbl.centerX = giftView.width * 0.5 - 4;
101 102 [giftView addSubview:priceLbl];
102   -
  103 + //礼物价格图标
103 104 UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"littleHeart2"]];
104 105 image.left = priceLbl.right + 3;
105 106 image.centerY = priceLbl.centerY;
... ... @@ -114,7 +115,14 @@
114 115 NSInteger tag = gesture.view.tag - 10;
115 116 NSLog(@"%zd",tag);
116 117 //右上角添加✔️,再次点击去掉✔️
117   - [self.animQueueManager addAnimationWithModel:self.giftArray[tag] animContentView:self.liveBaseView];
  118 + GiftModel *model = self.giftArray[tag];
  119 + if (model.giftStyle == GiftStyleCombo) {
  120 +
  121 + [self.animQueueManager addAnimationWithModel:self.giftArray[tag] animContentView:(UIView *)self.liveBaseView.presentView];
  122 + }else
  123 + {
  124 + [self.animQueueManager addAnimationWithModel:self.giftArray[tag] animContentView:self.liveBaseView];
  125 + }
118 126 }
119 127  
120 128 #pragma mark - getter
... ... @@ -125,37 +133,35 @@
125 133 {
126 134 NSArray *images = [NSArray arrayWithObjects:@"love",@"love",@"love",@"love",@"love",@"love",@"love",@"love",@"love",@"love",nil];
127 135 NSArray *types = [NSArray arrayWithObjects:@2,@3,@1,@1,@1,@1,@1,@1,@1,@1, nil];
  136 + NSArray *senders = [NSArray arrayWithObjects:@"张三",@"李四",@"王五",@"宋刘",@"老七",@"老八",@"老九",@"老十",@"老师",@"小十七", nil];
128 137 NSArray *prices = [NSArray arrayWithObjects:@"300000000",@"3000",@"300000",@"30",@"3",@"3",@"1",@"3",@"1",@"3", nil];
129 138  
130 139 NSMutableArray *tempArr = [NSMutableArray array];
131 140 for (int i = 0; i < images.count; i ++) {
132   - GiftModel *model = [GiftModel new];
133   - model.giftname = @"鲜花";
134   - model.giftIconArray = @[[UIImage imageNamed:@"love"]];
135   - model.giftNum = @"5";
136   - model.giftRusername = @"啊啊啊啊啊啊啊啊啊啊啊啊";
137   - model.giftRuserId = @"10000";
138   - model.giftGusername = @"按时大多数阿萨德 爱傻傻的爱的";
139   - model.giftGuserId = @"20000";
140   - model.image = images[i];
  141 +
141 142 int type = [types[i] intValue];
142 143 if (type == 1) {
143   - model.giftStyle = GiftStyleCombo;
144   - }else if (type == 2)
145   - {
146   - model.giftStyle = GiftStylePorsch;
147   - }
148   -// else if (type == 3)
149   -// {
150   -// model.giftStyle = GiftStyleFighter;
151   -// }
152   - else if (type == 3)
153   - {
154   - model.giftStyle = GiftStylePlane;
155   - }
  144 + //combo
  145 + GiftModel *model1 = [GiftModel modelWithSender:senders[i] giftName:@"大大的爱心" icon:@"love" giftImageName:images[i]];
  146 + model1.giftStyle = GiftStyleCombo;
  147 + model1.price = prices[i];
  148 + [tempArr addObject:model1];
  149 +
  150 + }else
  151 + {//expen
  152 + GiftModel *model = [GiftModel modelWithSender:senders[i] giftName:@"豪华礼物" icon:@"love" giftImageName:@"love"];
156 153  
157   - model.price = prices[i];
158   - [tempArr addObject:model];
  154 + if (type == 2) {
  155 + model.giftStyle = GiftStylePorsch;
  156 + model.giftName = @"跑车";
  157 + }
  158 + if (type == 3) {
  159 + model.giftStyle = GiftStylePlane;
  160 + model.giftName = @"客机";
  161 + }
  162 + model.price = prices[i];
  163 + [tempArr addObject:model];
  164 + }
159 165 }
160 166 _giftArray = [[NSArray alloc] initWithArray:tempArr];
161 167 }
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftViews/GiftModelView.m deleted 100644 → 0
1   -//
2   -// GiftModelView.m
3   -// LiveVideoCloud
4   -//
5   -// Created by 张旭 on 2017/3/14.
6   -// Copyright © 2017年 cnlive. All rights reserved.
7   -//
8   -
9   -#import "GiftModelView.h"
10   -#import "GiftModel.h"
11   -
12   -@implementation GiftModelView
13   -
14   -//+ (instancetype)giftViewWithModel:(GiftModel *)giftModel
15   -//{
16   -// GiftModelView *view = [[GiftModelView alloc] init];
17   -// view
18   -// return ;
19   -//}
20   -
21   -/*
22   -// Only override drawRect: if you perform custom drawing.
23   -// An empty implementation adversely affects performance during animation.
24   -- (void)drawRect:(CGRect)rect {
25   - // Drawing code
26   -}
27   -*/
28   -
29   -@end
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftViews/GiftModelView.h renamed to LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/ComboCell.h
1 1 //
2   -// GiftModelView.h
  2 +// ComboCell.h
3 3 // LiveVideoCloud
4 4 //
5   -// Created by 张旭 on 2017/3/14.
  5 +// Created by 张旭 on 2017/3/17.
6 6 // Copyright © 2017年 cnlive. All rights reserved.
7 7 //
8 8  
9   -#import "BaseView.h"
10   -
  9 +#import "PresentViewCell.h"
11 10 @class GiftModel;
12   -@interface GiftModelView : BaseView
13 11  
14   -+ (instancetype)giftViewWithModel:(GiftModel *)giftModel;
  12 +@interface ComboCell : PresentViewCell
  13 +
  14 +@property (nonatomic ,strong) GiftModel * _Nullable model;
15 15 @end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/ComboCell.m 0 → 100644
  1 +//
  2 +// ComboCell.m
  3 +// LiveVideoCloud
  4 +//
  5 +// Created by 张旭 on 2017/3/17.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import "ComboCell.h"
  10 +#import "GiftModel.h"
  11 +
  12 +@interface ComboCell ()
  13 +
  14 +@property (nonatomic ,strong) UIView * _Nullable bgView;
  15 +@property (nonatomic ,strong) UIImageView * _Nullable icon;
  16 +@property (nonatomic ,strong) UILabel * _Nullable senderNameLbl;
  17 +@property (nonatomic ,strong) UILabel * _Nullable giftNameLbl;
  18 +@property (nonatomic ,strong) UIImageView * _Nullable giftImage;
  19 +
  20 +@end
  21 +
  22 +@implementation ComboCell
  23 +
  24 +- (instancetype)initWithRow:(NSInteger)row
  25 +{
  26 + if (self = [super initWithRow:row]) {
  27 +
  28 + [self addSubview:self.bgView];
  29 + [self addSubview:self.icon];
  30 + [self addSubview:self.senderNameLbl];
  31 + [self addSubview:self.giftNameLbl];
  32 + [self addSubview:self.giftImage];
  33 + }
  34 + return self;
  35 +}
  36 +
  37 +- (void)setModel:(GiftModel *)model
  38 +{
  39 + _model = model;
  40 + self.icon.image = [UIImage imageNamed:model.icon];
  41 + self.senderNameLbl.text = model.sender;
  42 + self.giftNameLbl.text = [NSString stringWithFormat:@"送一个%@",model.giftName];
  43 + self.senderNameLbl.size = [self.senderNameLbl labelSize];
  44 + self.giftNameLbl.size = [self.giftNameLbl labelSize];
  45 + self.bgView.frame = CGRectMake(0, 0, self.width, self.height);
  46 + self.bgView.layer.cornerRadius = self.height * 0.5;
  47 + self.giftImage.frame = CGRectMake(self.width - self.height, 0, self.height, self.height);
  48 + self.giftImage.image = [UIImage imageNamed:model.giftImageName];
  49 +}
  50 +
  51 +//自定义cell的展示动画
  52 +- (void)customDisplayAnimationOfShowShakeAnimation:(BOOL)flag
  53 +{
  54 + //这里是直接使用父类中的动画,如果用户想自定义可这里实现动画,不调用父类的方法(这个方法在UIView动画的animations回调中执行)
  55 + [super customDisplayAnimationOfShowShakeAnimation:flag];
  56 +}
  57 +
  58 +//自定义cell的隐藏动画
  59 +- (void)customHideAnimationOfShowShakeAnimation:(BOOL)flag
  60 +{
  61 + [super customHideAnimationOfShowShakeAnimation:flag];
  62 +}
  63 +
  64 +#pragma mark - getter
  65 +- (UILabel *)senderNameLbl
  66 +{
  67 + if (!_senderNameLbl)
  68 + {
  69 + _senderNameLbl = [[UILabel alloc] initWithFrame:CGRectMake(self.icon.right + 5, 0, 100, 20)];
  70 + _senderNameLbl.font = [UIFont systemFontOfSize:kContentFont];
  71 + _senderNameLbl.textColor = [UIColor blackColor];
  72 + }
  73 + return _senderNameLbl;
  74 +}
  75 +
  76 +- (UILabel *)giftNameLbl
  77 +{
  78 + if (!_giftNameLbl)
  79 + {
  80 + _giftNameLbl = [[UILabel alloc] initWithFrame:CGRectMake(self.icon.right + 5, self.senderNameLbl.bottom , 100, 20)];
  81 + _giftNameLbl.font = [UIFont systemFontOfSize:kContentFont];
  82 + _giftNameLbl.textColor = [UIColor blackColor];
  83 + }
  84 + return _giftNameLbl;
  85 +}
  86 +
  87 +- (UIImageView *)icon
  88 +{
  89 + if (!_icon)
  90 + {
  91 + _icon = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
  92 + _icon.clipsToBounds = YES;
  93 + _icon.layer.cornerRadius = 20;
  94 + _icon.layer.borderWidth = 1;
  95 + _icon.layer.borderColor = [UIColor cyanColor].CGColor;
  96 +
  97 + }
  98 + return _icon;
  99 +}
  100 +
  101 +- (UIImageView *)giftImage
  102 +{
  103 + if (!_giftImage)
  104 + {
  105 + _giftImage = [[UIImageView alloc] init];
  106 + }
  107 + return _giftImage;
  108 +}
  109 +
  110 +- (UIView *)bgView
  111 +{
  112 + if (!_bgView)
  113 + {
  114 + _bgView = [[UIView alloc] init];
  115 + _bgView.backgroundColor = [UIColor yellowColor];
  116 + _bgView.clipsToBounds = YES;
  117 + }
  118 + return _bgView;
  119 +}
  120 +
  121 +/*
  122 +// Only override drawRect: if you perform custom drawing.
  123 +// An empty implementation adversely affects performance during animation.
  124 +- (void)drawRect:(CGRect)rect {
  125 + // Drawing code
  126 +}
  127 +*/
  128 +
  129 +@end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/PresentModelAble.h 0 → 100755
  1 +//
  2 +// PresentModelAble.h
  3 +// PresentDemo
  4 +//
  5 +// Created by 阮思平 on 16/10/2.
  6 +// Copyright © 2016年 阮思平. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +// 日志
  12 +
  13 +#ifdef DEBUG
  14 +
  15 +#ifndef DebugLog
  16 +#define DebugLog(fmt, ...) NSLog((@"[%s Line %d]" fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
  17 +#endif
  18 +
  19 +#else
  20 +
  21 +#ifndef DebugLog
  22 +#define DebugLog(fmt, ...)
  23 +#endif
  24 +
  25 +#define NSLog
  26 +
  27 +
  28 +#endif
  29 +
  30 +/**
  31 + * 礼物模型必须遵守的协议
  32 + */
  33 +@protocol PresentModelAble <NSObject>
  34 +
  35 +@required
  36 +/**
  37 + * 发送者
  38 + */
  39 +@property (copy, nonatomic) NSString *sender;
  40 +/**
  41 + * 礼物名(或礼物编号)
  42 + */
  43 +@property (copy, nonatomic) NSString *giftName;
  44 +
  45 +@optional
  46 +
  47 +/**
  48 + 需要展示的礼物连乘数 默认为0
  49 +
  50 + @discussion 用于解决当前礼物消息消息展示到一半时,新加入到聊天室的人看到的礼物消息不是从1开始,如果要使用,消息体中必须包含当前礼物个数
  51 + */
  52 +@property (assign, nonatomic) NSInteger giftNumber;
  53 +
  54 +@end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/PresentView.h 0 → 100755
  1 +//
  2 +// PresentView.h
  3 +// PresentDemo
  4 +//
  5 +// Created by 阮思平 on 16/10/2.
  6 +// Copyright © 2016年 阮思平. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import "PresentViewCell.h"
  11 +
  12 +@protocol PresentViewDelegate;
  13 +
  14 +@interface PresentView : UIView
  15 +
  16 +/**
  17 + * cell高度(默认40)
  18 + */
  19 +@property (assign, nonatomic) CGFloat cellHeight;
  20 +/**
  21 + * 礼物动画展示时间(默认3秒)
  22 + */
  23 +@property (assign, nonatomic)NSTimeInterval showTime;
  24 +/**
  25 + * 轨道总数
  26 + */
  27 +@property (assign, nonatomic, readonly) NSInteger rows;
  28 +@property (weak, nonatomic) id<PresentViewDelegate> delegate;
  29 +/**
  30 + * 获取对应轨道上的cell
  31 + */
  32 +- (__kindof PresentViewCell *)cellForRowAtIndex:(NSUInteger)index;
  33 +/**
  34 + * 插入送礼消息
  35 + *
  36 + * @param models 礼物模型数组中的模型必须遵守PresentModelAble协议
  37 + * @param flag 是否需要连乘动画
  38 + */
  39 +- (void)insertPresentMessages:(NSArray<id <PresentModelAble>> *)models showShakeAnimation:(BOOL)flag;
  40 +/**
  41 + 释放相关引用变量
  42 + */
  43 +- (void)releaseVariable;
  44 +
  45 +@end
  46 +
  47 +@protocol PresentViewDelegate <NSObject>
  48 +
  49 +@required
  50 +/**
  51 + * 返回自定义cell样式
  52 + */
  53 +- (PresentViewCell *)presentView:(PresentView *)presentView cellOfRow:(NSInteger)row;
  54 +/**
  55 + * 礼物动画即将展示的时调用,根据礼物消息类型为自定义的cell设置对应的模型数据用于展示
  56 + *
  57 + * @param cell 用来展示动画的cell
  58 + * @param model 礼物模型
  59 + */
  60 +- (void)presentView:(PresentView *)presentView
  61 + configCell:(PresentViewCell *)cell
  62 + model:(id<PresentModelAble>)model;
  63 +
  64 +@optional
  65 +
  66 +/**
  67 + * cell点击事件
  68 + */
  69 +- (void)presentView:(PresentView *)presentView didSelectedCellOfRowAtIndex:(NSUInteger)index;
  70 +
  71 +/**
  72 + 一组连乘动画执行完成回调
  73 + */
  74 +- (void)presentView:(PresentView *)presentView animationCompleted:(NSInteger)shakeNumber model:(id<PresentModelAble>)model;
  75 +
  76 +@end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/PresentView.m 0 → 100755
  1 +//
  2 +// PresentView.m
  3 +// PresentDemo
  4 +//
  5 +// Created by 阮思平 on 16/10/2.
  6 +// Copyright © 2016年 阮思平. All rights reserved.
  7 +//
  8 +
  9 +#import "PresentView.h"
  10 +
  11 +#define Margin 20
  12 +
  13 +@interface PresentView ()<PresentViewCellDelegate>
  14 +
  15 +/**
  16 + * 带连乘动画的消息缓存数组
  17 + */
  18 +@property (strong, nonatomic) NSMutableArray *dataCaches;
  19 +/**
  20 + * 不带连城动画的消息缓存数组
  21 + */
  22 +@property (strong, nonatomic)NSMutableArray *nonshakeDataCaches;
  23 +/**
  24 + * 记录presentView上的cell
  25 + */
  26 +@property (strong, nonatomic) NSMutableArray *showCells;
  27 +
  28 +@end
  29 +
  30 +@implementation PresentView
  31 +
  32 +#pragma mark - Setter/Getter
  33 +
  34 +- (void)setCellHeight:(CGFloat)cellHeight
  35 +{
  36 + _cellHeight = cellHeight;
  37 +
  38 + [self setNeedsDisplay];
  39 +}
  40 +
  41 +- (NSMutableArray *)dataCaches
  42 +{
  43 + if (!_dataCaches) {
  44 + _dataCaches = [NSMutableArray array];
  45 + }
  46 + return _dataCaches;
  47 +}
  48 +
  49 +- (NSMutableArray *)nonshakeDataCaches
  50 +{
  51 + if (!_nonshakeDataCaches) {
  52 + _nonshakeDataCaches = [NSMutableArray array];
  53 + }
  54 + return _nonshakeDataCaches;
  55 +}
  56 +
  57 +- (NSMutableArray *)showCells
  58 +{
  59 + if (!_showCells) {
  60 + _showCells = [NSMutableArray array];
  61 + }
  62 + return _showCells;
  63 +}
  64 +
  65 +#pragma mark - Initial
  66 +
  67 +- (instancetype)init
  68 +{
  69 + if (self = [super init]) {
  70 + self.userInteractionEnabled = NO;
  71 + }
  72 + return self;
  73 +}
  74 +
  75 +- (void)awakeFromNib
  76 +{
  77 + [super awakeFromNib];
  78 +
  79 + self.userInteractionEnabled = NO;
  80 +}
  81 +
  82 +- (void)drawRect:(CGRect)rect
  83 +{
  84 + [super drawRect:rect];
  85 +
  86 + //初始值
  87 + self.showTime = 3;
  88 +
  89 + //添加cell
  90 + self.cellHeight = self.cellHeight ? self.cellHeight : 40;
  91 + _rows = (int)floor(rect.size.height / (self.cellHeight + Margin));
  92 + CGFloat inset = rect.size.height - (self.cellHeight + Margin) * _rows + Margin;
  93 + inset = MAX(0, inset) * 0.5;
  94 + for (int index = 0; index < _rows; index++) {
  95 + CGFloat w = rect.size.width;
  96 + CGFloat y = inset + (self.cellHeight + Margin) * index;
  97 + CGFloat x = -w;
  98 + PresentViewCell *cell = [self.delegate presentView:self cellOfRow:index];
  99 + cell.frame = CGRectMake(x, y, w, self.cellHeight);
  100 + cell.delegate = self;
  101 + [self addSubview:cell];
  102 + [self.showCells addObject:cell];
  103 + }
  104 +}
  105 +
  106 +- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  107 +{
  108 + UITouch *touch = touches.anyObject;
  109 + CGPoint point = [touch locationInView:self];
  110 + for (int index = 0; index < self.showCells.count; index++) {
  111 + PresentViewCell *cell = self.showCells[index];
  112 + if (CGRectContainsPoint(cell.frame, point)) {
  113 + if ([self.delegate respondsToSelector:@selector(presentView:didSelectedCellOfRowAtIndex:)]) {
  114 + [self.delegate presentView:self didSelectedCellOfRowAtIndex:index];
  115 + }
  116 + break;
  117 + }
  118 + }
  119 +}
  120 +
  121 +#pragma mark - Private
  122 +
  123 +//问题一:如果展示动画还在执行,就收到了新的连乘动画消息,这时会判定为去执行连乘动画,因为展示动画还没有执行完成,所以连乘lable还没有被创建,所以会导致连乘动画会消失
  124 +//解决办法:等连展示动画执行完成了,才能开始连乘动画,否则连乘动画消息就被缓存
  125 +
  126 +//问题二:点击礼物4,等礼物4快要消失的时候,点击礼物1。会出现两个礼物1,并且下面的cell不会消失,导致礼物1的消息都会被缓存起来
  127 +//问题原因:当礼物4将要隐藏时,这时接收到礼物1的消息,就会利用空闲的cell来展示礼物1,但这是没有马上删除礼物1的缓存,而是等到礼物1展示完成才删除的,所以礼物4展示完成就会检测缓存,这时礼物1并没有被删除,所以这里又会展示礼物1,这就导致了礼物一被展示了两次
  128 +//解决办法:当礼物4执行完成了,去取缓存的时候,如果取到了缓存,还需要判断这个缓存当前有没有在展示,如果在展示就不做处理,如果没有在展示就利用当前的cell去展示它
  129 +
  130 +//问题三:连续快速点击礼物1,会分两次动画展示
  131 +//问题原因:因为两次送的礼物相同,如果快速点击,会发生用于展示第一个礼物的cell还处在AnimationStateShowing状态时,就收到第二个礼物,这个是时候的逻辑处理是将第二个消息缓存了起来(为了解决上述的问题一)
  132 +
  133 +/**
  134 + * 插入带连乘动画的消息
  135 + */
  136 +- (void)insertShowShakeAnimationMessages:(NSArray<id<PresentModelAble>> *)models
  137 +{
  138 + for (int index = 0; index < models.count; index++) {
  139 + id<PresentModelAble> obj = models[index];
  140 + PresentViewCell *cell = [self examinePresentingCell:obj];
  141 + if (cell) {
  142 + if (cell.state == AnimationStateShowing) {
  143 + //在执行展示动画期间如果收到了连乘动画礼物消息,就将消息缓存
  144 + [self.dataCaches addObject:obj];
  145 + }else {
  146 + if ([obj giftNumber] > 0) {
  147 + [cell shakeAnimationWithModels:@[obj]];
  148 + } else {
  149 + [cell shakeAnimationWithNumber:1];
  150 + }
  151 + }
  152 + }else {
  153 + [self.dataCaches addObject:obj];//将当前消息加到缓存中
  154 + NSArray *cells = [self examinePresentViewCells];
  155 + if (cells.count) {
  156 + cell = cells.firstObject;
  157 + //设置后,再次展示的动画才会生效
  158 + cell.showTime = self.showTime;
  159 + __weak typeof(self) ws = self;
  160 + [cell showAnimationWithModel:obj showShakeAnimation:YES prepare:^{
  161 + if ([ws.delegate respondsToSelector:@selector(presentView:configCell:model:)]) {
  162 + [ws.delegate presentView:ws configCell:cell model:obj];
  163 + }
  164 + } completion:^(BOOL flag) {
  165 + if (flag) {
  166 + //如果相同礼物类型的消息缓存在执行展示动画之前就删除了,这就会造成在cell执行展示动画期间收到的相同类型的消息会被缓存到下一个cell中展示
  167 + if ([obj giftNumber] > 0) {
  168 + [cell shakeAnimationWithModels:[self subarrayWithObj:obj]];
  169 + }else {
  170 + [cell shakeAnimationWithNumber:[self subarrayWithObj:obj].count];
  171 + }
  172 + }
  173 + }];
  174 + }
  175 + }
  176 + }
  177 +}
  178 +
  179 +/**
  180 + * 插入不带连城动画的消息
  181 + */
  182 +- (void)insertNonshakeAnimationMessages:(NSArray<id<PresentModelAble>> *)models
  183 +{
  184 + if (models) {
  185 + [self.nonshakeDataCaches addObjectsFromArray:models];
  186 + }
  187 + NSArray *freeCells = [self examinePresentViewCells];
  188 + if (self.nonshakeDataCaches.count > 0 && freeCells.count > 0) {
  189 + id<PresentModelAble> obj = self.nonshakeDataCaches.firstObject;
  190 + [self.nonshakeDataCaches removeObjectAtIndex:0];
  191 + PresentViewCell *cell = freeCells.firstObject;
  192 + cell.showTime = self.showTime;
  193 + __weak typeof(self) ws = self;
  194 + [cell showAnimationWithModel:obj showShakeAnimation:NO prepare:^{
  195 + if ([ws.delegate respondsToSelector:@selector(presentView:configCell:model:)]) {
  196 + [ws.delegate presentView:ws configCell:cell model:obj];
  197 + }
  198 + } completion:^(BOOL flag) {
  199 + if (!flag) {
  200 + [cell performSelector:@selector(hiddenAnimationOfShowShake:) withObject:@(NO) afterDelay:self.showTime];
  201 + }
  202 + }];
  203 + }
  204 +}
  205 +
  206 +/**
  207 + * 检测插入的消息模型
  208 + */
  209 +- (NSArray *)checkElementOfModels:(NSArray<id<PresentModelAble>> *)models
  210 +{
  211 + NSMutableArray *siftArray = [NSMutableArray array];
  212 + for (id obj in models) {
  213 + if (![obj conformsToProtocol:@protocol(PresentModelAble)]) {
  214 + DebugLog(@"%@对象没有遵守PresentModelAble协议", obj);
  215 + }else {
  216 + [siftArray addObject:obj];
  217 + }
  218 + }
  219 + return siftArray;
  220 +}
  221 +
  222 +/**
  223 + * 检测当前是否有obj类型的礼物消息在展示
  224 + */
  225 +- (PresentViewCell *)examinePresentingCell:(id<PresentModelAble>)obj
  226 +{
  227 + for (PresentViewCell *cell in self.showCells) {
  228 + if ([cell.sender isEqualToString:[obj sender]] && [cell.giftName isEqualToString:[obj giftName]]) {
  229 + //当前正在展示动画并且不是隐藏动画
  230 + if (cell.state != AnimationStateNone && cell.state != AnimationStateHiding ) return cell;
  231 + }
  232 + }
  233 + return nil;
  234 +}
  235 +
  236 +/**
  237 + * 检测空闲cell
  238 + */
  239 +- (NSArray<PresentViewCell *> *)examinePresentViewCells
  240 +{
  241 + NSMutableArray *freeCells = [NSMutableArray array];
  242 + for (PresentViewCell *cell in self.showCells) {
  243 + if (cell.state == AnimationStateNone) {
  244 + [freeCells addObject:cell];
  245 + }
  246 + }
  247 + return freeCells;
  248 +}
  249 +
  250 +/**
  251 + * 从缓存中截取与obj类型相同的消息
  252 + */
  253 +- (NSArray<id<PresentModelAble>> *)subarrayWithObj:(id<PresentModelAble>)obj
  254 +{
  255 + NSMutableArray *array = [NSMutableArray array];
  256 + for (id<PresentModelAble> cache in self.dataCaches) {
  257 + if ([[cache sender] isEqualToString:[obj sender]] && [[cache giftName] isEqualToString:[obj giftName]]) {
  258 + [array addObject:cache];
  259 + }
  260 + }
  261 + [self.dataCaches removeObjectsInArray:array];//取出的数据从缓存中移除
  262 + return array;
  263 +}
  264 +
  265 +#pragma mark - Public
  266 +
  267 +- (void)insertPresentMessages:(NSArray<id<PresentModelAble>> *)models showShakeAnimation:(BOOL)flag
  268 +{
  269 + NSArray *siftArray = [self checkElementOfModels:models];
  270 + if (!siftArray.count) return;
  271 + if (flag) {
  272 + [self insertShowShakeAnimationMessages:siftArray];
  273 + }else {
  274 + [self insertNonshakeAnimationMessages:siftArray];
  275 + }
  276 +}
  277 +
  278 +- (PresentViewCell *)cellForRowAtIndex:(NSUInteger)index
  279 +{
  280 + if (index < self.showCells.count)
  281 + {
  282 + return self.showCells[index];
  283 + }
  284 + return nil;
  285 +}
  286 +
  287 +- (void)releaseVariable
  288 +{
  289 + [self.dataCaches removeAllObjects];
  290 + [self.nonshakeDataCaches removeAllObjects];
  291 + [self.showCells makeObjectsPerformSelector:@selector(removeFromSuperview)];
  292 + [self.showCells removeAllObjects];
  293 +}
  294 +
  295 +#pragma mark - PresentViewCellDelegate
  296 +
  297 +- (void)presentViewCell:(PresentViewCell *)cell showShakeAnimation:(BOOL)flag shakeNumber:(NSInteger)number
  298 +{
  299 + if ([self.delegate respondsToSelector:@selector(presentView:animationCompleted:model:)]) {
  300 + [self.delegate presentView:self animationCompleted:number model:cell.baseModel];
  301 + }
  302 + if (self.dataCaches.count) {
  303 + id<PresentModelAble> obj = self.dataCaches.firstObject;
  304 + if (![self examinePresentingCell:obj]) {
  305 + //取到的缓存当前没有在展示
  306 + __weak typeof(self) ws = self;
  307 + [cell showAnimationWithModel:obj showShakeAnimation:YES prepare:^{
  308 + if ([ws.delegate respondsToSelector:@selector(presentView:configCell:model:)]) {
  309 + [ws.delegate presentView:ws configCell:cell model:obj];
  310 + }
  311 + } completion:^(BOOL flag) {
  312 + if (flag) {
  313 + if ([obj giftNumber] > 0) {
  314 + [cell shakeAnimationWithModels:[self subarrayWithObj:obj]];
  315 + }else {
  316 + [cell shakeAnimationWithNumber:[self subarrayWithObj:obj].count];
  317 + }
  318 + }
  319 + }];
  320 + }
  321 + }else if (self.nonshakeDataCaches.count) {
  322 + //带连乘的缓存优先处理
  323 + [self insertNonshakeAnimationMessages:nil];
  324 + }else {
  325 + [cell releaseVariable];
  326 + }
  327 +}
  328 +
  329 +@end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/PresentViewCell.h 0 → 100755
  1 +//
  2 +// PresentViewCell.h
  3 +// PresentDemo
  4 +//
  5 +// Created by 阮思平 on 16/10/2.
  6 +// Copyright © 2016年 阮思平. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import "PresentModelAble.h"
  11 +
  12 +//动画状态
  13 +typedef NS_ENUM(NSUInteger, AnimationState) {
  14 + AnimationStateNone = 0,
  15 + AnimationStateShowing,
  16 + AnimationStateShaking,
  17 + AnimationStateShaked,
  18 + AnimationStateHiding
  19 +};
  20 +
  21 +@protocol PresentViewCellDelegate;
  22 +
  23 +@interface PresentViewCell : UIView
  24 +
  25 +@property (weak, nonatomic) id<PresentViewCellDelegate> delegate;
  26 +/**
  27 + * cell展示时间
  28 + */
  29 +@property (assign, nonatomic)NSTimeInterval showTime;
  30 +/**
  31 + * 轨道编号
  32 + */
  33 +@property (assign, nonatomic, readonly) NSInteger row;
  34 +/**
  35 + * cell当前的动画状态
  36 + */
  37 +@property (assign, nonatomic, readonly) AnimationState state;
  38 +/**
  39 + 礼物模型
  40 + */
  41 +@property (strong, nonatomic, readonly)id<PresentModelAble> baseModel;
  42 +/**
  43 + * 礼物发送者
  44 + */
  45 +@property (copy, nonatomic, readonly) NSString *sender;
  46 +/**
  47 + * 礼物名
  48 + */
  49 +@property (copy, nonatomic, readonly) NSString *giftName;
  50 +
  51 +- (instancetype)initWithRow:(NSInteger)row;
  52 +/**
  53 + * 显示cell动画
  54 + *
  55 + * @param model 礼物模型
  56 + * @param flag 是否带连乘动画
  57 + * @param prepare 准备动画回调
  58 + * @param completion 动画完成回调
  59 + */
  60 +- (void)showAnimationWithModel:(id<PresentModelAble> )model
  61 + showShakeAnimation:(BOOL)flag
  62 + prepare:(void (^)(void))prepare
  63 + completion:(void (^)(BOOL flag))completion;
  64 +/**
  65 + * 连乘动画
  66 + *
  67 + * @param number 连乘次数
  68 + */
  69 +- (void)shakeAnimationWithNumber:(NSInteger)number;
  70 +/**
  71 + 连乘动画
  72 +
  73 + @discussion 当礼物模型中拥有礼物个数时,才调用此接口
  74 + @param model 礼物模型
  75 + */
  76 +- (void)shakeAnimationWithModels:(NSArray<id<PresentModelAble>> *)models;
  77 +/**
  78 + * 隐藏cell动画
  79 + *
  80 + * @param flag 是否带有连城动画
  81 + */
  82 +- (void)hiddenAnimationOfShowShake:(BOOL)flag;
  83 +/**
  84 + * 释放引用变量
  85 + */
  86 +- (void)releaseVariable;
  87 +
  88 +@end
  89 +
  90 +
  91 +
  92 +//供子类重写的接口
  93 +@interface PresentViewCell (OverWrite)
  94 +
  95 +/**
  96 + * 自定义展示动画
  97 + *
  98 + * @param flag 是否带有连乘动画
  99 + */
  100 +- (void)customDisplayAnimationOfShowShakeAnimation:(BOOL)flag;
  101 +/**
  102 + * 自定义隐藏动画
  103 + *
  104 + * @param flag 是否带有连乘动画
  105 + */
  106 +- (void)customHideAnimationOfShowShakeAnimation:(BOOL)flag;
  107 +
  108 +@end
  109 +
  110 +
  111 +
  112 +@interface PresentLable : UILabel
  113 +
  114 +/**
  115 + * 数字描边颜色
  116 + */
  117 +@property (strong, nonatomic) UIColor *borderColor;
  118 +/**
  119 + * 开始连乘动画
  120 + *
  121 + * @param interval 动画时间
  122 + * @param completion 动画完成回调
  123 + */
  124 +- (void)startAnimationDuration:(NSTimeInterval)interval
  125 + completion:(void (^)(BOOL finish))completion;
  126 +
  127 +@end
  128 +
  129 +
  130 +
  131 +@protocol PresentViewCellDelegate <NSObject>
  132 +
  133 +@optional
  134 +/**
  135 + * 一组动画组完成回调
  136 + *
  137 + * @param flag 是否带连乘动画
  138 + * @param number 最终连乘数,如果flag为NO number就为0
  139 + */
  140 +- (void)presentViewCell:(PresentViewCell *)cell
  141 + showShakeAnimation:(BOOL)flag
  142 + shakeNumber:(NSInteger)number;
  143 +
  144 +@end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/Present/PresentViewCell.m 0 → 100755
  1 +//
  2 +// PresentViewCell.m
  3 +// PresentDemo
  4 +//
  5 +// Created by 阮思平 on 16/10/2.
  6 +// Copyright © 2016年 阮思平. All rights reserved.
  7 +//
  8 +
  9 +#import "PresentViewCell.h"
  10 +
  11 +#define Duration 0.3
  12 +
  13 +@interface PresentViewCell ()
  14 +
  15 +@property (weak, nonatomic) PresentLable *shakeLable;
  16 +/**
  17 + * 记录礼物连乘数
  18 + */
  19 +@property (assign, nonatomic) NSInteger number;
  20 +/**
  21 + * 记录cell最初始的frame(即开始展示动画前的frame)
  22 + */
  23 +@property (assign, nonatomic) CGRect originalFrame;
  24 +/**
  25 + * shake动画的缓存数组
  26 + */
  27 +@property (strong, nonatomic) NSMutableArray *caches;
  28 +/**
  29 + shake动画模型的缓存数组
  30 + */
  31 +@property (strong, nonatomic) NSMutableArray *modelCaches;
  32 +
  33 +@end
  34 +
  35 +@implementation PresentViewCell
  36 +
  37 +#pragma mark - Setter/Getter
  38 +
  39 +- (NSMutableArray *)caches
  40 +{
  41 + if (!_caches) {
  42 + _caches = [NSMutableArray array];
  43 + }
  44 + return _caches;
  45 +}
  46 +
  47 +- (NSMutableArray *)modelCaches
  48 +{
  49 + if (!_modelCaches) {
  50 + _modelCaches = [NSMutableArray array];
  51 + }
  52 + return _modelCaches;
  53 +}
  54 +
  55 +#pragma mark - Initial
  56 +
  57 +- (instancetype)initWithRow:(NSInteger)row
  58 +{
  59 + if (self = [super init]) {
  60 + _row = row;
  61 + _state = AnimationStateNone;
  62 + }
  63 + return self;
  64 +}
  65 +
  66 +#pragma mark - Private
  67 +
  68 +/**
  69 + * 添加连乘lable
  70 + */
  71 +- (void)addShakeLable
  72 +{
  73 + PresentLable *lable = [[PresentLable alloc] init];
  74 + lable.backgroundColor = [UIColor clearColor];
  75 + lable.borderColor = [UIColor yellowColor];
  76 + lable.textColor = [UIColor greenColor];
  77 + lable.font = [UIFont systemFontOfSize:17.0];
  78 + lable.textAlignment = NSTextAlignmentCenter;
  79 + lable.alpha = 0.0;
  80 + CGFloat w = 60;
  81 + CGFloat h = 20;
  82 + CGFloat x = CGRectGetWidth(self.frame);
  83 + CGFloat y = - h * 0.5 + self.frame.size.height * 0.5;
  84 + lable.frame = CGRectMake(x, y, w, h);
  85 + self.shakeLable = lable;
  86 + [self addSubview:lable];
  87 +}
  88 +
  89 +/**
  90 + * 开始连乘动画(利用递归实现连乘动画)
  91 + *
  92 + * @param number 连乘次数
  93 + * @param block 当前number次连乘动画执行完成回调
  94 + */
  95 +- (void)startShakeAnimationWithNumber:(NSInteger)number completion:(void (^)(BOOL finished))block
  96 +{
  97 + self.superview.userInteractionEnabled = YES;
  98 + _state = AnimationStateShaking;
  99 + self.shakeLable.text = [NSString stringWithFormat:@"X%ld", ++self.number];
  100 + __weak typeof(self) ws = self;
  101 + [self.shakeLable startAnimationDuration:Duration completion:^(BOOL finish) {
  102 + if (number > 1) {
  103 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  104 + [ws startShakeAnimationWithNumber:(number - 1) completion:block];
  105 + });
  106 + }else {
  107 + _state = AnimationStateShaked;
  108 + if (block) {
  109 + block(YES);
  110 + }
  111 + }
  112 + }];
  113 +}
  114 +
  115 +#pragma mark - Public
  116 +
  117 +- (void)showAnimationWithModel:(id<PresentModelAble>)model showShakeAnimation:(BOOL)flag prepare:(void (^)(void))prepare completion:(void (^)(BOOL))completion
  118 +{
  119 + _state = AnimationStateShowing;
  120 + _baseModel = model;
  121 + _sender = [model sender];
  122 + _giftName = [model giftName];
  123 + self.originalFrame = self.frame;
  124 + self.number = 0;
  125 + if (prepare) {
  126 + prepare();
  127 + }
  128 + [UIView animateWithDuration:Duration delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  129 + [self customDisplayAnimationOfShowShakeAnimation:flag];
  130 + } completion:^(BOOL finished) {
  131 + if (flag) {
  132 + if (!self.shakeLable) {
  133 + [self addShakeLable];
  134 + }
  135 + self.shakeLable.alpha = 1.0;
  136 + }
  137 + if (completion) {
  138 + completion(flag);
  139 + }
  140 + }];
  141 +}
  142 +
  143 +- (void)shakeAnimationWithNumber:(NSInteger)number
  144 +{
  145 + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hiddenAnimationOfShowShake:) object:@(YES)];
  146 + [self performSelector:@selector(hiddenAnimationOfShowShake:) withObject:@(YES) afterDelay:self.showTime];
  147 + if (number > 0) [self.caches addObject:@(number)];
  148 + if (self.caches.count > 0 && _state != AnimationStateShaking) {
  149 + NSInteger cache = [self.caches.firstObject integerValue];
  150 + [self.caches removeObjectAtIndex:0];//不能删除对象,因为可能有相同的对象
  151 + __weak typeof(self) ws = self;//
  152 + [self startShakeAnimationWithNumber:cache completion:^(BOOL finished) {
  153 + [ws shakeAnimationWithNumber:-1];//传-1是为了缓存不被重复添加
  154 + }];
  155 + }
  156 +}
  157 +
  158 +- (void)shakeAnimationWithModels:(NSArray<id<PresentModelAble>> *)models
  159 +{
  160 + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hiddenAnimationOfShowShake:) object:@(YES)];
  161 + [self performSelector:@selector(hiddenAnimationOfShowShake:) withObject:@(YES) afterDelay:self.showTime];
  162 + if (models.count > 0) [self.modelCaches addObjectsFromArray:models];
  163 + if (self.modelCaches.count > 0 && _state != AnimationStateShaking) {
  164 + _state = AnimationStateShaking;
  165 + id<PresentModelAble> obj = self.modelCaches.firstObject;
  166 + self.shakeLable.text = [NSString stringWithFormat:@"X%ld", [obj giftNumber]];
  167 + [self.modelCaches removeObjectAtIndex:0];
  168 + __weak typeof(self) ws = self;
  169 + [self.shakeLable startAnimationDuration:Duration completion:^(BOOL finish) {
  170 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  171 + _state = AnimationStateShaked;
  172 + if (ws.modelCaches.count > 0) {
  173 + [ws shakeAnimationWithModels:nil];
  174 + }
  175 + });
  176 + }];
  177 + }
  178 +}
  179 +
  180 +- (void)hiddenAnimationOfShowShake:(BOOL)flag
  181 +{
  182 + self.superview.userInteractionEnabled = NO;
  183 + _state = AnimationStateHiding;
  184 + [UIView animateWithDuration:Duration delay:0 usingSpringWithDamping:1.0 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  185 + [self customHideAnimationOfShowShakeAnimation:flag];
  186 + } completion:^(BOOL finished) {
  187 +
  188 + //恢复cell的初始状态
  189 + self.frame = self.originalFrame;
  190 + _state = AnimationStateNone;
  191 + self.shakeLable.alpha = 0.0;
  192 + [self.caches removeAllObjects];
  193 + [self.modelCaches removeAllObjects];
  194 +
  195 + //通知代理
  196 + if ([self.delegate respondsToSelector:@selector(presentViewCell:showShakeAnimation:shakeNumber:)]) {
  197 + [self.delegate presentViewCell:self showShakeAnimation:flag shakeNumber:self.number];
  198 +
  199 + }
  200 + }];
  201 +}
  202 +
  203 +//目前还没有使用
  204 +- (void)releaseVariable
  205 +{
  206 +// [self.shakeLable removeFromSuperview];
  207 +}
  208 +
  209 +@end
  210 +
  211 +@implementation PresentViewCell (OverWrite)
  212 +
  213 +- (void)customDisplayAnimationOfShowShakeAnimation:(BOOL)flag
  214 +{
  215 + self.alpha = 1.0;
  216 + CGRect selfF = self.frame;
  217 + selfF.origin.x = 0;
  218 + self.frame = selfF;
  219 +}
  220 +
  221 +- (void)customHideAnimationOfShowShakeAnimation:(BOOL)flag
  222 +{
  223 + self.alpha = 0.0;
  224 + CGRect selfF = self.frame;
  225 + selfF.origin.y -= (CGRectGetHeight(selfF) * 0.5);
  226 + self.frame = selfF;
  227 +}
  228 +
  229 +@end
  230 +
  231 +@implementation PresentLable
  232 +
  233 +- (void)drawTextInRect:(CGRect)rect
  234 +{
  235 + UIColor *textColor = self.textColor;
  236 +
  237 + CGContextRef c = UIGraphicsGetCurrentContext();
  238 + CGContextSetLineWidth(c, 5);
  239 + CGContextSetLineJoin(c, kCGLineJoinRound);
  240 +
  241 + CGContextSetTextDrawingMode(c, kCGTextStroke);
  242 + self.textColor = self.borderColor;
  243 + [super drawTextInRect:rect];
  244 +
  245 + CGContextSetTextDrawingMode(c, kCGTextFill);
  246 + self.textColor = textColor;
  247 + self.shadowOffset = CGSizeMake(0, 0);
  248 + [super drawTextInRect:rect];
  249 +}
  250 +
  251 +- (void)startAnimationDuration:(NSTimeInterval)interval completion:(void (^)(BOOL finish))completion
  252 +{
  253 + [UIView animateKeyframesWithDuration:interval delay:0 options:0 animations:^{
  254 +
  255 + [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1/2.0 animations:^{
  256 + self.transform = CGAffineTransformMakeScale(4, 4);
  257 + }];
  258 + [UIView addKeyframeWithRelativeStartTime:1/2.0 relativeDuration:1/2.0 animations:^{
  259 + self.transform = CGAffineTransformMakeScale(0.8, 0.8);
  260 + }];
  261 +
  262 + } completion:^(BOOL finished) {
  263 +
  264 + [UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:10 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  265 + self.transform = CGAffineTransformMakeScale(1.0, 1.0);
  266 + } completion:^(BOOL finished) {
  267 + if (completion) {
  268 + completion(finished);
  269 + }
  270 + }];
  271 +
  272 + }];
  273 +}
  274 +
  275 +@end
  276 +
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/LiveBaseView.h
... ... @@ -7,9 +7,11 @@
7 7 //
8 8  
9 9 #import "BaseView.h"
  10 +@class PresentView;
10 11  
11 12 @interface LiveBaseView : BaseView
12 13  
13 14 @property (nonatomic ,strong) UIViewController * _Nullable viewController;
14   -
  15 +@property (nonatomic ,strong ,readonly) PresentView * _Nullable presentView;
  16 +@property (nonatomic ,strong ,readonly) UIView * _Nullable animationBaseView;
15 17 @end
... ...
LiveVideoCloud/LiveVideoCloud/Classes/Sections/InteractionSections/LiveBaseView.m
... ... @@ -11,13 +11,25 @@
11 11 #import "BottomToolView.h"
12 12 #import "GiftListView.h"
13 13 #import "GiftModel.h"
14   -@interface LiveBaseView ()<bottomBtnDeledate>
  14 +#import "PresentView.h"
  15 +#import "ComboCell.h"
15 16  
16   -@property (nonatomic ,strong) UIScrollView * _Nullable scrollView;
17   -@property (nonatomic ,strong) BottomToolView* _Nullable bottomToolView;
18   -@property (nonatomic ,strong) UIButton * _Nullable closeBtn;
19   -@property (nonatomic ,strong) UIView * _Nullable currentPopView;
  17 +typedef NS_ENUM(NSInteger, PopType) {//弹窗类型
  18 + PopTypeGift = 1,//礼物弹窗
  19 + PopTypeChat ,//聊天弹窗
  20 + PopTypePriMessage //私信弹窗
  21 +};
20 22  
  23 +@interface LiveBaseView ()<bottomBtnDeledate,PresentViewDelegate,UIScrollViewDelegate>
  24 +
  25 +@property (nonatomic ,strong ) UIScrollView * _Nullable scrollView;
  26 +@property (nonatomic ,strong ,readwrite) UIView * _Nullable animationBaseView;//展示层View
  27 +@property (nonatomic ,strong ) BottomToolView* _Nullable bottomToolView;
  28 +@property (nonatomic ,strong ) UIButton * _Nullable closeBtn;
  29 +@property (nonatomic ,strong ) UIView * _Nullable giftPopView;
  30 +@property (nonatomic ,strong ,readwrite) PresentView * _Nullable presentView;//连击View
  31 +
  32 +@property (nonatomic ,assign ) PopType popType;
21 33 @end
22 34  
23 35 @implementation LiveBaseView
... ... @@ -27,7 +39,9 @@
27 39 if (self = [super initWithFrame:frame]) {
28 40  
29 41 [self addSubview:self.scrollView];
30   - [self.scrollView addSubview:self.bottomToolView];
  42 + [self.scrollView addSubview:self.animationBaseView];
  43 + [self.animationBaseView addSubview:self.bottomToolView];
  44 + [self.animationBaseView addSubview:self.presentView];
31 45 [self addSubview:self.closeBtn];
32 46 [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureClick:)]];
33 47 }
... ... @@ -41,20 +55,22 @@
41 55 switch (btnType) {
42 56 case BtnClickTypeChat:
43 57 {
44   -
  58 + self.popType = PopTypeChat;
45 59 }
46 60 break;
47 61 case BtnClickTypePriChat:
48 62 {
49   -
  63 + self.popType = PopTypePriMessage;
50 64 }
51 65 break;
52 66 case BtnClickTypeGift:
53 67 {
  68 + self.popType = PopTypeGift;
  69 +
54 70 GiftListView *giftListView = [[GiftListView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - 230, SCREEN_WIDTH, 230) liveBaseView:self];
55 71 giftListView.backgroundColor = [UIColor lightGrayColor];
56 72 [self addSubview:giftListView];
57   - self.currentPopView = giftListView;
  73 + self.giftPopView = giftListView;
58 74  
59 75 }
60 76 break;
... ... @@ -71,13 +87,56 @@
71 87  
72 88 - (void)clearCurrentPopView
73 89 {
74   - [UIView animateWithDuration:0.25 animations:^{
75   -
76   - self.currentPopView.frame = CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
77   - [self hiddenView:NO];
78   - } completion:^(BOOL finished) {
79   - [self.currentPopView removeFromSuperview];
80   - }];
  90 + switch (self.popType) {
  91 + case PopTypeGift:
  92 + {
  93 + [UIView animateWithDuration:0.25 animations:^{
  94 +
  95 + self.giftPopView.frame = CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
  96 + [self hiddenView:NO];
  97 + } completion:^(BOOL finished) {
  98 + [self.giftPopView removeFromSuperview];
  99 + }];
  100 + }
  101 + break;
  102 + case PopTypeChat:
  103 + {
  104 +
  105 + }
  106 + break;
  107 + case PopTypePriMessage:
  108 + {
  109 +
  110 + }
  111 + break;
  112 + default:
  113 + break;
  114 + }
  115 +
  116 +}
  117 +#pragma mark - PresentViewDelegate
  118 +
  119 +- (PresentViewCell *)presentView:(PresentView *)presentView cellOfRow:(NSInteger)row
  120 +{
  121 + return [[ComboCell alloc] initWithRow:row];
  122 +}
  123 +
  124 +- (void)presentView:(PresentView *)presentView configCell:(PresentViewCell *)cell model:(id<PresentModelAble>)model
  125 +{
  126 + ComboCell *comboCell = (ComboCell *)cell;
  127 + comboCell.model = (GiftModel *)model;
  128 +}
  129 +
  130 +- (void)presentView:(PresentView *)presentView didSelectedCellOfRowAtIndex:(NSUInteger)index
  131 +{
  132 + ComboCell *cell = [presentView cellForRowAtIndex:index];
  133 + NSLog(@"你点击了:%@", cell.model.giftName);
  134 +}
  135 +
  136 +- (void)presentView:(PresentView *)presentView animationCompleted:(NSInteger)shakeNumber model:(id<PresentModelAble>)model
  137 +{
  138 +// self.number = 5;
  139 + NSLog(@"%@礼物的连送动画执行完成", model.giftName);
81 140 }
82 141  
83 142 #pragma mark - buttonClick
... ... @@ -91,6 +150,12 @@
91 150 [self.viewController.navigationController popViewControllerAnimated:YES];
92 151 }
93 152  
  153 +#pragma mark - UIScrollViewDelegate
  154 +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  155 +{
  156 + [self clearCurrentPopView];
  157 +}
  158 +
94 159 #pragma mark - setter
95 160 -(void)setViewController:(UIViewController *)viewController
96 161 {
... ... @@ -110,15 +175,38 @@
110 175 _scrollView.showsVerticalScrollIndicator = NO;
111 176 _scrollView.showsHorizontalScrollIndicator = NO;
112 177 _scrollView.backgroundColor = [UIColor clearColor];
  178 + _scrollView.delegate = self;
113 179 }
114 180 return _scrollView;
115 181 }
116 182  
  183 +- (UIView *)animationBaseView
  184 +{
  185 + if (!_animationBaseView)
  186 + {
  187 + _animationBaseView = [[UIView alloc] initWithFrame:CGRectMake(self.scrollView.width, 0, self.scrollView.width, self.scrollView.height)];
  188 + _animationBaseView.backgroundColor = [UIColor redColor];
  189 + _animationBaseView.clipsToBounds = YES;
  190 + }
  191 + return _animationBaseView;
  192 +}
  193 +
  194 +- (PresentView *)presentView
  195 +{
  196 + if (!_presentView)
  197 + {
  198 + _presentView = [[PresentView alloc] initWithFrame:CGRectMake(0, 200, 220, 200)];
  199 + _presentView.delegate = self;
  200 + _presentView.backgroundColor = [UIColor clearColor];
  201 + }
  202 + return _presentView;
  203 +}
  204 +
117 205 - (BottomToolView *)bottomToolView
118 206 {
119 207 if (!_bottomToolView)
120 208 {
121   - _bottomToolView = [[BottomToolView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT - 60, SCREEN_WIDTH, 60)];
  209 + _bottomToolView = [[BottomToolView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - 60, SCREEN_WIDTH, 60)];
122 210 _bottomToolView.delegate = self;
123 211 _bottomToolView.backgroundColor = [UIColor lightGrayColor];
124 212 _bottomToolView.alpha = 0.7;
... ...
LiveVideoCloud/LiveVideoCloud/animation.xcassets/LaunchImage.launchimage/Contents.json
... ... @@ -3,43 +3,30 @@
3 3 {
4 4 "orientation" : "portrait",
5 5 "idiom" : "ipad",
6   - "minimum-system-version" : "7.0",
7 6 "extent" : "full-screen",
8   - "scale" : "2x"
9   - },
10   - {
11   - "orientation" : "landscape",
12   - "idiom" : "ipad",
13 7 "minimum-system-version" : "7.0",
14   - "extent" : "full-screen",
15 8 "scale" : "1x"
16 9 },
17 10 {
18 11 "orientation" : "landscape",
19 12 "idiom" : "ipad",
20   - "minimum-system-version" : "7.0",
21 13 "extent" : "full-screen",
22   - "scale" : "2x"
23   - },
24   - {
25   - "orientation" : "portrait",
26   - "idiom" : "iphone",
27 14 "minimum-system-version" : "7.0",
28   - "scale" : "2x"
  15 + "scale" : "1x"
29 16 },
30 17 {
31 18 "orientation" : "portrait",
32   - "idiom" : "iphone",
  19 + "idiom" : "ipad",
  20 + "extent" : "full-screen",
33 21 "minimum-system-version" : "7.0",
34   - "subtype" : "retina4",
35 22 "scale" : "2x"
36 23 },
37 24 {
38   - "orientation" : "portrait",
  25 + "orientation" : "landscape",
39 26 "idiom" : "ipad",
40   - "minimum-system-version" : "7.0",
41 27 "extent" : "full-screen",
42   - "scale" : "1x"
  28 + "minimum-system-version" : "7.0",
  29 + "scale" : "2x"
43 30 }
44 31 ],
45 32 "info" : {
... ...