Commit 45591957daf3701d38c3f935e54af931dea15bbc
1 parent
e98d288e
完成弹幕逻辑,修改AppId
Showing
26 changed files
with
694 additions
and
1012 deletions
LiveVideoCloud/LiveVideoCloud.xcodeproj/project.pbxproj
| ... | ... | @@ -26,10 +26,8 @@ |
| 26 | 26 | 811BB6851E8106AF005C6291 /* CNLivePlayerSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 811BB6821E8106A2005C6291 /* CNLivePlayerSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; |
| 27 | 27 | 811BB6881E8107B4005C6291 /* LVCChatViewTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 811BB6871E8107B4005C6291 /* LVCChatViewTableViewCell.m */; }; |
| 28 | 28 | 811BB68E1E8116C8005C6291 /* NSString+StringSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 811BB68D1E8116C8005C6291 /* NSString+StringSize.m */; }; |
| 29 | - 8128E26E1E8A3AFE00B40E75 /* LVCDanmuUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E26D1E8A3AFE00B40E75 /* LVCDanmuUtil.m */; }; | |
| 30 | - 8128E2711E8A3BF000B40E75 /* LVCDanmuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E2701E8A3BF000B40E75 /* LVCDanmuView.m */; }; | |
| 31 | - 8128E2741E8A3C1900B40E75 /* LVCDanmuLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E2731E8A3C1900B40E75 /* LVCDanmuLabel.m */; }; | |
| 32 | - 8128E2771E8A3CD700B40E75 /* LVCDanmuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E2761E8A3CD700B40E75 /* LVCDanmuManager.m */; }; | |
| 29 | + 8128E2881E8A6A3600B40E75 /* CNBarrageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E2851E8A6A3600B40E75 /* CNBarrageManager.m */; }; | |
| 30 | + 8128E2891E8A6A3600B40E75 /* CNBarrageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8128E2871E8A6A3600B40E75 /* CNBarrageView.m */; }; | |
| 33 | 31 | 8130911E1E84C0F0005F0BFF /* LVCMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 8130911D1E84C0F0005F0BFF /* LVCMessage.m */; }; |
| 34 | 32 | 81A1B9A91E8277410079FF5F /* LVCInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A1B9A81E8277410079FF5F /* LVCInputView.m */; }; |
| 35 | 33 | 81A482F51E88ACC80097A80A /* LVCTelevisionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A482F41E88ACC80097A80A /* LVCTelevisionView.m */; }; |
| ... | ... | @@ -282,14 +280,10 @@ |
| 282 | 280 | 811BB6871E8107B4005C6291 /* LVCChatViewTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCChatViewTableViewCell.m; sourceTree = "<group>"; }; |
| 283 | 281 | 811BB68C1E8116C8005C6291 /* NSString+StringSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+StringSize.h"; sourceTree = "<group>"; }; |
| 284 | 282 | 811BB68D1E8116C8005C6291 /* NSString+StringSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+StringSize.m"; sourceTree = "<group>"; }; |
| 285 | - 8128E26C1E8A3AFE00B40E75 /* LVCDanmuUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCDanmuUtil.h; sourceTree = "<group>"; }; | |
| 286 | - 8128E26D1E8A3AFE00B40E75 /* LVCDanmuUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCDanmuUtil.m; sourceTree = "<group>"; }; | |
| 287 | - 8128E26F1E8A3BF000B40E75 /* LVCDanmuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCDanmuView.h; sourceTree = "<group>"; }; | |
| 288 | - 8128E2701E8A3BF000B40E75 /* LVCDanmuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCDanmuView.m; sourceTree = "<group>"; }; | |
| 289 | - 8128E2721E8A3C1900B40E75 /* LVCDanmuLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCDanmuLabel.h; sourceTree = "<group>"; }; | |
| 290 | - 8128E2731E8A3C1900B40E75 /* LVCDanmuLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCDanmuLabel.m; sourceTree = "<group>"; }; | |
| 291 | - 8128E2751E8A3CD700B40E75 /* LVCDanmuManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCDanmuManager.h; sourceTree = "<group>"; }; | |
| 292 | - 8128E2761E8A3CD700B40E75 /* LVCDanmuManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCDanmuManager.m; sourceTree = "<group>"; }; | |
| 283 | + 8128E2841E8A6A3600B40E75 /* CNBarrageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNBarrageManager.h; sourceTree = "<group>"; }; | |
| 284 | + 8128E2851E8A6A3600B40E75 /* CNBarrageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNBarrageManager.m; sourceTree = "<group>"; }; | |
| 285 | + 8128E2861E8A6A3600B40E75 /* CNBarrageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNBarrageView.h; sourceTree = "<group>"; }; | |
| 286 | + 8128E2871E8A6A3600B40E75 /* CNBarrageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNBarrageView.m; sourceTree = "<group>"; }; | |
| 293 | 287 | 8130911C1E84C0F0005F0BFF /* LVCMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCMessage.h; sourceTree = "<group>"; }; |
| 294 | 288 | 8130911D1E84C0F0005F0BFF /* LVCMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LVCMessage.m; sourceTree = "<group>"; }; |
| 295 | 289 | 81A1B9A71E8277410079FF5F /* LVCInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LVCInputView.h; sourceTree = "<group>"; }; |
| ... | ... | @@ -725,19 +719,15 @@ |
| 725 | 719 | path = ../ChatView; |
| 726 | 720 | sourceTree = "<group>"; |
| 727 | 721 | }; |
| 728 | - 8128E26B1E8A3AD400B40E75 /* Danmu */ = { | |
| 722 | + 8128E2831E8A6A3600B40E75 /* Barrage */ = { | |
| 729 | 723 | isa = PBXGroup; |
| 730 | 724 | children = ( |
| 731 | - 8128E26C1E8A3AFE00B40E75 /* LVCDanmuUtil.h */, | |
| 732 | - 8128E26D1E8A3AFE00B40E75 /* LVCDanmuUtil.m */, | |
| 733 | - 8128E26F1E8A3BF000B40E75 /* LVCDanmuView.h */, | |
| 734 | - 8128E2701E8A3BF000B40E75 /* LVCDanmuView.m */, | |
| 735 | - 8128E2721E8A3C1900B40E75 /* LVCDanmuLabel.h */, | |
| 736 | - 8128E2731E8A3C1900B40E75 /* LVCDanmuLabel.m */, | |
| 737 | - 8128E2751E8A3CD700B40E75 /* LVCDanmuManager.h */, | |
| 738 | - 8128E2761E8A3CD700B40E75 /* LVCDanmuManager.m */, | |
| 725 | + 8128E2841E8A6A3600B40E75 /* CNBarrageManager.h */, | |
| 726 | + 8128E2851E8A6A3600B40E75 /* CNBarrageManager.m */, | |
| 727 | + 8128E2861E8A6A3600B40E75 /* CNBarrageView.h */, | |
| 728 | + 8128E2871E8A6A3600B40E75 /* CNBarrageView.m */, | |
| 739 | 729 | ); |
| 740 | - path = Danmu; | |
| 730 | + path = Barrage; | |
| 741 | 731 | sourceTree = "<group>"; |
| 742 | 732 | }; |
| 743 | 733 | 812E504E1E7699B9004F5FCD /* CNLiveSDK */ = { |
| ... | ... | @@ -1667,7 +1657,7 @@ |
| 1667 | 1657 | D2888DAA1E6EC014003A77C8 /* View */ = { |
| 1668 | 1658 | isa = PBXGroup; |
| 1669 | 1659 | children = ( |
| 1670 | - 8128E26B1E8A3AD400B40E75 /* Danmu */, | |
| 1660 | + 8128E2831E8A6A3600B40E75 /* Barrage */, | |
| 1671 | 1661 | 811BB67B1E80F858005C6291 /* ChatView */, |
| 1672 | 1662 | 810B64DE1E779AE900133E15 /* LVCPlayer.h */, |
| 1673 | 1663 | 810B64DF1E779AE900133E15 /* LVCPlayer.m */, |
| ... | ... | @@ -1922,7 +1912,6 @@ |
| 1922 | 1912 | D2029D011E6EAE2E0027CD92 /* UIColor+HexString.m in Sources */, |
| 1923 | 1913 | D2029CA41E6EADE10027CD92 /* MJRefreshComponent.m in Sources */, |
| 1924 | 1914 | D2575C7A1E76A4F300E3A8FC /* NHCarViews.m in Sources */, |
| 1925 | - 8128E26E1E8A3AFE00B40E75 /* LVCDanmuUtil.m in Sources */, | |
| 1926 | 1915 | D2029CBC1E6EADE10027CD92 /* SDWebImageDownloaderOperation.m in Sources */, |
| 1927 | 1916 | D2029CA51E6EADE10027CD92 /* MJRefreshFooter.m in Sources */, |
| 1928 | 1917 | D22830FC1E77C2D900627701 /* BottomToolView.m in Sources */, |
| ... | ... | @@ -1933,6 +1922,7 @@ |
| 1933 | 1922 | D2029CD01E6EADE10027CD92 /* SearchPresenter.m in Sources */, |
| 1934 | 1923 | D2888DB71E6EC1B8003A77C8 /* LVCMyViewController.m in Sources */, |
| 1935 | 1924 | D2029CBE1E6EADE10027CD92 /* SDWebImagePrefetcher.m in Sources */, |
| 1925 | + 8128E2891E8A6A3600B40E75 /* CNBarrageView.m in Sources */, | |
| 1936 | 1926 | D2A803081E80BD6F009D6F1C /* TopToolView.m in Sources */, |
| 1937 | 1927 | D2B7B2571E8261EF00ED084E /* ChatBarrOperation.m in Sources */, |
| 1938 | 1928 | 810B65011E779B1F00133E15 /* MASLayoutConstraint.m in Sources */, |
| ... | ... | @@ -1970,6 +1960,7 @@ |
| 1970 | 1960 | D2029CB61E6EADE10027CD92 /* MKAnnotationView+WebCache.m in Sources */, |
| 1971 | 1961 | D2B2ED801E88FC5200F7538A /* LVCUGCLiveEndView.m in Sources */, |
| 1972 | 1962 | 810B64FE1E779B1F00133E15 /* MASCompositeConstraint.m in Sources */, |
| 1963 | + 8128E2881E8A6A3600B40E75 /* CNBarrageManager.m in Sources */, | |
| 1973 | 1964 | D2029C981E6EADE10027CD92 /* MJExtensionConst.m in Sources */, |
| 1974 | 1965 | D2575C671E76A25400E3A8FC /* LVCInteractionController.m in Sources */, |
| 1975 | 1966 | D2029CAE1E6EADE10027CD92 /* MJRefreshNormalHeader.m in Sources */, |
| ... | ... | @@ -1978,7 +1969,6 @@ |
| 1978 | 1969 | D2029CC61E6EADE10027CD92 /* SSKeychain.m in Sources */, |
| 1979 | 1970 | 811BB68E1E8116C8005C6291 /* NSString+StringSize.m in Sources */, |
| 1980 | 1971 | D2029C8B1E6EADE10027CD92 /* AFURLResponseSerialization.m in Sources */, |
| 1981 | - 8128E2711E8A3BF000B40E75 /* LVCDanmuView.m in Sources */, | |
| 1982 | 1972 | D2029C921E6EADE10027CD92 /* UIImageView+AFNetworking.m in Sources */, |
| 1983 | 1973 | D224B1971E826ED800CC61D0 /* ChatBarrageAnimAction.m in Sources */, |
| 1984 | 1974 | D2029C9E1E6EADE10027CD92 /* NSObject+MJCoding.m in Sources */, |
| ... | ... | @@ -1997,7 +1987,6 @@ |
| 1997 | 1987 | D2888DB11E6EC05F003A77C8 /* TempViewController.m in Sources */, |
| 1998 | 1988 | 81A483011E88B0130097A80A /* LVCBannerModel.m in Sources */, |
| 1999 | 1989 | 810B65021E779B1F00133E15 /* MASViewAttribute.m in Sources */, |
| 2000 | - 8128E2771E8A3CD700B40E75 /* LVCDanmuManager.m in Sources */, | |
| 2001 | 1990 | D2B7B2511E8247D400ED084E /* ChatBarrageManager.m in Sources */, |
| 2002 | 1991 | D2029CAC1E6EADE10027CD92 /* MJRefreshBackStateFooter.m in Sources */, |
| 2003 | 1992 | D2029CB11E6EADE10027CD92 /* MJRefreshConst.m in Sources */, |
| ... | ... | @@ -2007,7 +1996,6 @@ |
| 2007 | 1996 | D2029D051E6EAE2E0027CD92 /* UILabel+labelFitSize.m in Sources */, |
| 2008 | 1997 | D2029CB21E6EADE10027CD92 /* UIScrollView+MJExtension.m in Sources */, |
| 2009 | 1998 | D29D88481E88C53300543A03 /* LVCUGCLivePrepareView.m in Sources */, |
| 2010 | - 8128E2741E8A3C1900B40E75 /* LVCDanmuLabel.m in Sources */, | |
| 2011 | 1999 | D2029D091E6EAE2E0027CD92 /* Foundation+Log.m in Sources */, |
| 2012 | 2000 | D2029C8E1E6EADE10027CD92 /* AFImageDownloader.m in Sources */, |
| 2013 | 2001 | 81A483201E88F4BF0097A80A /* LVCProgramModel.m in Sources */, |
| ... | ... | @@ -2217,7 +2205,7 @@ |
| 2217 | 2205 | "$(inherited)", |
| 2218 | 2206 | "$(PROJECT_DIR)/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftResource", |
| 2219 | 2207 | ); |
| 2220 | - PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video; | |
| 2208 | + PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.shixunyun; | |
| 2221 | 2209 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 2222 | 2210 | }; |
| 2223 | 2211 | name = Debug; |
| ... | ... | @@ -2240,7 +2228,7 @@ |
| 2240 | 2228 | "$(inherited)", |
| 2241 | 2229 | "$(PROJECT_DIR)/LiveVideoCloud/Classes/Sections/InteractionSections/Gift/GiftResource", |
| 2242 | 2230 | ); |
| 2243 | - PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video; | |
| 2231 | + PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.shixunyun; | |
| 2244 | 2232 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 2245 | 2233 | }; |
| 2246 | 2234 | name = Release; | ... | ... |
LiveVideoCloud/LiveVideoCloud/AppDelegate/AppDelegate.m
| ... | ... | @@ -23,23 +23,28 @@ |
| 23 | 23 | self.window.rootViewController = [[ZXTabBarController alloc] init]; |
| 24 | 24 | |
| 25 | 25 | //初始化直播SDK |
| 26 | -// [[CNLiveWebcastManager manager] initWithAppId:AppId appKey:AppKey]; | |
| 26 | + [[CNLiveWebcastManager manager] initWithAppId:AppId appKey:AppKey]; | |
| 27 | 27 | |
| 28 | 28 | //初始化聊天SDK并连接服务器 |
| 29 | 29 | [[CNLiveChatManager sharedCNLiveChatManager] initWithAppKey:AppKey appId:AppId]; |
| 30 | -// [[CNLiveChatManager sharedCNLiveChatManager] connectServerSuccess:^{ | |
| 31 | -// NSLog(@"连接服务器-----success"); | |
| 32 | -// } error:^(CNLiveChatConnectErrorCode errors) { | |
| 33 | -// NSLog(@"连接服务器失败-----%ld", errors); | |
| 34 | -// }]; | |
| 35 | - // 20170327 20170328 | |
| 36 | - CNLiveChatUserInfo *userInfo = [[CNLiveChatUserInfo alloc] initWithUserId:@"20170328" name:@"20170328" portrait:@""]; | |
| 37 | - [[CNLiveChatManager sharedCNLiveChatManager] loginServer:userInfo success:^(NSString *userId) { | |
| 38 | - NSLog(@"连接服务器-----success"); | |
| 39 | - | |
| 30 | + | |
| 31 | + [[CNLiveChatManager sharedCNLiveChatManager] connectServerSuccess:^{ | |
| 32 | + NSLog(@"连接服务器-----success"); | |
| 40 | 33 | } error:^(CNLiveChatConnectErrorCode errors) { |
| 41 | 34 | NSLog(@"连接服务器失败-----%ld", errors); |
| 42 | 35 | }]; |
| 36 | + /* | |
| 37 | + */ | |
| 38 | + // 20170327 20170328 | |
| 39 | + /* | |
| 40 | + CNLiveChatUserInfo *userInfo = [[CNLiveChatUserInfo alloc] initWithUserId:@"20170328" name:@"20170328" portrait:@""]; | |
| 41 | + [[CNLiveChatManager sharedCNLiveChatManager] loginServer:userInfo success:^(NSString *userId) { | |
| 42 | + NSLog(@"连接服务器-----success"); | |
| 43 | + | |
| 44 | + } error:^(CNLiveChatConnectErrorCode errors) { | |
| 45 | + NSLog(@"连接服务器失败-----%ld", errors); | |
| 46 | + }]; | |
| 47 | + */ | |
| 43 | 48 | [self.window makeKeyAndVisible]; |
| 44 | 49 | |
| 45 | 50 | return YES; | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/LiveSections/Controller/LVCLiveViewController.m
| ... | ... | @@ -14,10 +14,6 @@ |
| 14 | 14 | #import "LiveBaseView.h" |
| 15 | 15 | #import "LVCUGCLiveEndView.h" |
| 16 | 16 | |
| 17 | - | |
| 18 | -#define KAppId @"60_irn9edco29" | |
| 19 | -#define KAppKey @"69fe70bda67e059286ad509d9f5377f815955645b52f94" | |
| 20 | - | |
| 21 | 17 | @interface LVCLiveViewController ()<UIGestureRecognizerDelegate> { |
| 22 | 18 | |
| 23 | 19 | BOOL _isStreaming; |
| ... | ... | @@ -61,8 +57,6 @@ |
| 61 | 57 | [self.view addSubview:self.openFlashButton]; |
| 62 | 58 | [self.view addSubview:self.filterView]; |
| 63 | 59 | |
| 64 | - [[CNLiveWebcastManager manager] initWithAppId:KAppId appKey:KAppKey]; | |
| 65 | - | |
| 66 | 60 | // 初始化推流 |
| 67 | 61 | NSString *activityId = [NSString stringWithFormat:@"%d%d%d%d%d",arc4random()%9,arc4random()%9,arc4random()%9,arc4random()%9,arc4random()%9]; |
| 68 | 62 | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/ChatView/LVCChatView.h
| ... | ... | @@ -7,9 +7,18 @@ |
| 7 | 7 | // |
| 8 | 8 | |
| 9 | 9 | #import <UIKit/UIKit.h> |
| 10 | +#import "chatMsgModel.h" | |
| 11 | + | |
| 12 | +@class LVCChatView; | |
| 13 | +@protocol LVCChatViewDelegate <NSObject> | |
| 14 | + | |
| 15 | +- (void)lvcChatView:(LVCChatView *)chatView sendBarrageWithModel:(chatMsgModel *)model; | |
| 16 | + | |
| 17 | +@end | |
| 10 | 18 | |
| 11 | 19 | @interface LVCChatView : UIView |
| 12 | 20 | @property (nonatomic, strong) UITableView *tableView; |
| 21 | +@property (nonatomic, assign) id<LVCChatViewDelegate> delegate; | |
| 13 | 22 | |
| 14 | 23 | - (instancetype)initWithFrame:(CGRect)frame roomId:(NSString *)roomId; |
| 15 | 24 | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/ChatView/LVCChatView.m
| ... | ... | @@ -69,16 +69,23 @@ |
| 69 | 69 | { |
| 70 | 70 | [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:message type:CNLive_ConversationType_CHATROOM targetId:_roomId success:^(CNLiveChatMessage *message) { |
| 71 | 71 | |
| 72 | - LVCMessage *msg = [LVCMessage messageWihtContent:message isRight:YES]; | |
| 72 | + chatMsgModel *model = [[chatMsgModel alloc] init]; | |
| 73 | + model.content = message.messageContent; | |
| 74 | + model.isMine = YES; | |
| 73 | 75 | |
| 76 | + LVCMessage *msg = [LVCMessage messageWihtContent:message isRight:YES]; | |
| 74 | 77 | dispatch_sync(dispatch_get_main_queue(), ^{ |
| 75 | 78 | [self addData:msg]; |
| 79 | + if (self.delegate && [self.delegate respondsToSelector:@selector(lvcChatView:sendBarrageWithModel:)]) { | |
| 80 | + [self.delegate lvcChatView:self sendBarrageWithModel:model]; | |
| 81 | + } | |
| 76 | 82 | }); |
| 77 | 83 | |
| 78 | 84 | NSLog(@"电视台--发送消息---success-(%@)",msg.content); |
| 79 | 85 | |
| 80 | 86 | } error:^(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId) { |
| 81 | 87 | NSLog(@"电视台--发送消息---failed-(%ld)",(long)errors); |
| 88 | + | |
| 82 | 89 | }]; |
| 83 | 90 | } |
| 84 | 91 | |
| ... | ... | @@ -100,8 +107,16 @@ |
| 100 | 107 | dispatch_queue_t globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); |
| 101 | 108 | dispatch_async(globalQueue, ^{ |
| 102 | 109 | LVCMessage *msg = [LVCMessage messageWihtContent:message isRight:NO]; |
| 110 | + | |
| 111 | + chatMsgModel *model = [[chatMsgModel alloc] init]; | |
| 112 | + model.content = message.messageContent; | |
| 113 | + model.isMine = NO; | |
| 114 | + | |
| 103 | 115 | dispatch_sync(dispatch_get_main_queue(), ^{ |
| 104 | 116 | [self addData:msg]; |
| 117 | + if (self.delegate && [self.delegate respondsToSelector:@selector(lvcChatView:sendBarrageWithModel:)]) { | |
| 118 | + [self.delegate lvcChatView:self sendBarrageWithModel:model]; | |
| 119 | + } | |
| 105 | 120 | }); |
| 106 | 121 | }); |
| 107 | 122 | } | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/ChatView/LVCInputView.m
| ... | ... | @@ -45,7 +45,7 @@ |
| 45 | 45 | [self.delegate lvcInputView:self sendMessage:_inputTextField.text]; |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | -// [self endEditing:YES]; | |
| 48 | + [self endEditing:YES]; | |
| 49 | 49 | _inputTextField.text = @""; |
| 50 | 50 | |
| 51 | 51 | } |
| ... | ... | @@ -64,7 +64,7 @@ |
| 64 | 64 | [self.delegate lvcInputView:self sendMessage:_inputTextField.text]; |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | -// [self endEditing:YES]; | |
| 67 | + [self endEditing:YES]; | |
| 68 | 68 | textField.text = @""; |
| 69 | 69 | return YES; |
| 70 | 70 | } | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/ChatView/LVCMessage.m
| ... | ... | @@ -39,7 +39,9 @@ |
| 39 | 39 | msg.nikename = content.userInfo.name; |
| 40 | 40 | msg.portraits = content.userInfo.portraitUri; |
| 41 | 41 | |
| 42 | - CGRect rect = [msg.content boundingRectWithSize:CGSizeMake((SCREEN_WIDTH-60)*0.8, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil]; | |
| 42 | + CGFloat width = SCREEN_WIDTH > SCREEN_HEIGHT ? SCREEN_HEIGHT : SCREEN_WIDTH; | |
| 43 | + | |
| 44 | + CGRect rect = [msg.content boundingRectWithSize:CGSizeMake((width-60)*0.8, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil]; | |
| 43 | 45 | CGRect frameOfLabel = CGRectZero; |
| 44 | 46 | |
| 45 | 47 | frameOfLabel.size = rect.size; | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/Controller/LVCLivePlayerController.h
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/Controller/LVCLivePlayerController.m
| ... | ... | @@ -12,7 +12,11 @@ |
| 12 | 12 | #import "LVCInputView.h" |
| 13 | 13 | #import "LVCChatView.h" |
| 14 | 14 | |
| 15 | -@interface LVCLivePlayerController ()<LVCPlayerDelegate,LVCInputViewDelegate> | |
| 15 | +#import "CNBarrageManager.h" | |
| 16 | +#import "CNBarrageView.h" | |
| 17 | +#import "chatMsgModel.h" | |
| 18 | + | |
| 19 | +@interface LVCLivePlayerController ()<LVCPlayerDelegate,LVCInputViewDelegate,LVCChatViewDelegate> | |
| 16 | 20 | { |
| 17 | 21 | BOOL isHiddenStatusBar; //记录状态的隐藏显示 |
| 18 | 22 | CGRect playerFrame; //播放器原始位置 |
| ... | ... | @@ -29,6 +33,9 @@ |
| 29 | 33 | @property (nonatomic, strong) NSTimer *timer; |
| 30 | 34 | @property (nonatomic, assign) NSTimeInterval countTime; |
| 31 | 35 | |
| 36 | +@property (nonatomic, strong) CNBarrageManager *barrageManager; //弹幕管理者 | |
| 37 | +@property (nonatomic ,strong) UIView *barrageBaseView; //弹幕总View | |
| 38 | + | |
| 32 | 39 | @end |
| 33 | 40 | |
| 34 | 41 | @implementation LVCLivePlayerController |
| ... | ... | @@ -73,14 +80,20 @@ |
| 73 | 80 | }; |
| 74 | 81 | |
| 75 | 82 | [self makeConstraints]; |
| 76 | - | |
| 77 | 83 | [_player autoHideControlView]; //自动隐藏工具条 |
| 78 | - | |
| 79 | 84 | |
| 85 | + self.barrageManager.generateBarrageBlock = ^(CNBarrageView *barrageView) { | |
| 86 | + [weakSelf addBarrageView:barrageView]; | |
| 87 | + }; | |
| 80 | 88 | |
| 89 | + [self.player.contentView addSubview:self.barrageBaseView]; | |
| 81 | 90 | |
| 82 | 91 | } |
| 83 | - | |
| 92 | +- (void)addBarrageView:(CNBarrageView *)barrageView { | |
| 93 | + barrageView.frame = CGRectMake(self.player.width+50, barrageView.trajectory, barrageView.width, barrageView.height); | |
| 94 | + [self.barrageBaseView addSubview:barrageView]; | |
| 95 | + [barrageView startAnimation]; | |
| 96 | +} | |
| 84 | 97 | |
| 85 | 98 | - (void)addObservers |
| 86 | 99 | { |
| ... | ... | @@ -148,11 +161,16 @@ |
| 148 | 161 | //当键盘出现 |
| 149 | 162 | - (void)keyboardWillShow:(NSNotification *)aNotification{ |
| 150 | 163 | //获取键盘的高度 |
| 151 | - | |
| 164 | + NSDictionary *userInfo = [aNotification userInfo]; | |
| 165 | + NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; | |
| 166 | + CGRect keyboardRect = [aValue CGRectValue]; | |
| 167 | + int height = keyboardRect.size.height; | |
| 168 | + _inputView.frame = CGRectMake(0, SCREEN_HEIGHT-49-height, SCREEN_WIDTH, 49); | |
| 169 | + | |
| 152 | 170 | } |
| 153 | 171 | |
| 154 | 172 | - (void)keyboardWillHide:(NSNotification *)aNotification{ |
| 155 | - _inputView.frame = CGRectMake(0, SCREEN_HEIGHT-50, SCREEN_WIDTH, 50); | |
| 173 | + _inputView.frame = CGRectMake(0, SCREEN_HEIGHT-49, SCREEN_WIDTH, 49); | |
| 156 | 174 | } |
| 157 | 175 | |
| 158 | 176 | #pragma mark - |
| ... | ... | @@ -177,6 +195,18 @@ |
| 177 | 195 | [UIView animateWithDuration:0.3 animations:^{ |
| 178 | 196 | self.player.transform = CGAffineTransformMakeRotation(0); |
| 179 | 197 | }]; |
| 198 | + | |
| 199 | + //是否显示弹幕 | |
| 200 | + if ([_player displayBarrage]) { | |
| 201 | + [self.player.contentView addSubview:self.barrageBaseView]; | |
| 202 | + [self.player.contentView insertSubview:self.barrageBaseView atIndex:1]; | |
| 203 | + self.barrageManager.isStopBarrage = NO; | |
| 204 | + } else { | |
| 205 | + self.barrageManager.isStopBarrage = YES; | |
| 206 | + [self.barrageManager stopBarrage]; | |
| 207 | + [self.barrageBaseView removeFromSuperview]; | |
| 208 | + } | |
| 209 | + | |
| 180 | 210 | }]; |
| 181 | 211 | |
| 182 | 212 | } |
| ... | ... | @@ -198,9 +228,24 @@ |
| 198 | 228 | [UIView animateWithDuration:0.3 animations:^{ |
| 199 | 229 | self.player.transform = CGAffineTransformMakeRotation(0); |
| 200 | 230 | }]; |
| 231 | + | |
| 232 | + self.barrageManager.isStopBarrage = YES; | |
| 233 | + [self.barrageManager stopBarrage]; | |
| 234 | + [self.barrageBaseView removeFromSuperview]; | |
| 235 | + | |
| 201 | 236 | }]; |
| 202 | 237 | } |
| 203 | 238 | |
| 239 | + | |
| 240 | +#pragma mark - | |
| 241 | +#pragma mark - LVCChatViewDelegate | |
| 242 | +- (void)lvcChatView:(LVCChatView *)chatView sendBarrageWithModel:(chatMsgModel *)model | |
| 243 | +{ | |
| 244 | + if (_player.isFullScreen) { | |
| 245 | + [self.barrageManager startBarrageWithNewArray:[NSMutableArray arrayWithObject:model]]; | |
| 246 | + } | |
| 247 | +} | |
| 248 | + | |
| 204 | 249 | #pragma mark - |
| 205 | 250 | #pragma mark - LVCPlayerDelegate |
| 206 | 251 | - (void)lvcPlayer:(LVCPlayer *)player clickedBackBtn:(UIButton *)backBtn |
| ... | ... | @@ -220,7 +265,7 @@ |
| 220 | 265 | } |
| 221 | 266 | } |
| 222 | 267 | |
| 223 | -- (void)lvcPlayer:(LVCPlayer *)player clicketullScreenBtn:(UIButton *)fullScreenBtn | |
| 268 | +- (void)lvcPlayer:(LVCPlayer *)player clickedFullScreenBtn:(UIButton *)fullScreenBtn | |
| 224 | 269 | { |
| 225 | 270 | if (_player.isFullScreen) {//全屏 |
| 226 | 271 | [self toHalfScreenWithrotationAngle:M_PI_2]; |
| ... | ... | @@ -236,13 +281,28 @@ |
| 236 | 281 | |
| 237 | 282 | } |
| 238 | 283 | |
| 284 | +- (void)lvcPlayer:(LVCPlayer *)player barrageSwitch:(BOOL)on | |
| 285 | +{ | |
| 286 | + if (on) { //开启弹幕 | |
| 287 | + [self.player.contentView addSubview:self.barrageBaseView]; | |
| 288 | + [self.player.contentView insertSubview:self.barrageBaseView atIndex:1]; | |
| 289 | + self.barrageManager.isStopBarrage = NO; | |
| 290 | + | |
| 291 | + } else { //关闭弹幕 | |
| 292 | + self.barrageManager.isStopBarrage = YES; | |
| 293 | + [self.barrageManager stopBarrage]; | |
| 294 | + [self.barrageBaseView removeFromSuperview]; | |
| 295 | + } | |
| 296 | +} | |
| 297 | + | |
| 239 | 298 | #pragma mark - |
| 240 | 299 | #pragma mark - LVCInputViewDelegate |
| 241 | 300 | - (void)lvcInputView:(LVCInputView *)inputView sendMessage:(NSString *)message |
| 242 | 301 | { |
| 243 | - NSLog(@"发送消息(%@)",message); | |
| 302 | + [_chatView sendMsgWithMessage:message]; | |
| 244 | 303 | |
| 245 | -// [_chatView sendMsgWithMessage:message]; | |
| 304 | + if (!_player.isFullScreen) return; | |
| 305 | + inputView.hidden = YES; | |
| 246 | 306 | } |
| 247 | 307 | |
| 248 | 308 | - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event |
| ... | ... | @@ -273,6 +333,7 @@ |
| 273 | 333 | }]; |
| 274 | 334 | _inputView.frame = CGRectMake(0, SCREEN_HEIGHT-50, SCREEN_WIDTH, 49); |
| 275 | 335 | |
| 336 | + _barrageBaseView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | |
| 276 | 337 | } else { //半屏 |
| 277 | 338 | [self.player mas_remakeConstraints:^(MASConstraintMaker *make) { |
| 278 | 339 | make.top.mas_equalTo(20); |
| ... | ... | @@ -289,7 +350,7 @@ |
| 289 | 350 | - (LVCPlayer *)player |
| 290 | 351 | { |
| 291 | 352 | if (!_player) { |
| 292 | - _player = [[LVCPlayer alloc] init]; | |
| 353 | + _player = [[LVCPlayer alloc] initWithFrame:CGRectZero playerModel:self.model]; | |
| 293 | 354 | _player.delegate = self; |
| 294 | 355 | } |
| 295 | 356 | return _player; |
| ... | ... | @@ -316,10 +377,29 @@ |
| 316 | 377 | { |
| 317 | 378 | if (!_chatView) { |
| 318 | 379 | _chatView = [[LVCChatView alloc] initWithFrame:CGRectMake(0, SCREEN_WIDTH*9/16+20, SCREEN_WIDTH, SCREEN_HEIGHT-SCREEN_WIDTH*9/16-20-49) roomId:_roomId]; |
| 380 | + _chatView.delegate = self; | |
| 319 | 381 | } |
| 320 | 382 | return _chatView; |
| 321 | 383 | } |
| 322 | 384 | |
| 385 | +- (UIView *)barrageBaseView | |
| 386 | +{ | |
| 387 | + if (!_barrageBaseView) { | |
| 388 | + _barrageBaseView = [[UIView alloc] init]; | |
| 389 | + _barrageBaseView.backgroundColor = [UIColor clearColor]; | |
| 390 | + [self.view addSubview:_barrageBaseView]; | |
| 391 | + } | |
| 392 | + return _barrageBaseView; | |
| 393 | +} | |
| 394 | + | |
| 395 | +- (CNBarrageManager *)barrageManager | |
| 396 | +{ | |
| 397 | + if (!_barrageManager) | |
| 398 | + { | |
| 399 | + self.barrageManager = [[CNBarrageManager alloc] init]; | |
| 400 | + } | |
| 401 | + return _barrageManager; | |
| 402 | +} | |
| 323 | 403 | |
| 324 | 404 | - (void)didReceiveMemoryWarning { |
| 325 | 405 | [super didReceiveMemoryWarning]; | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Barrage/CNBarrageManager.h
0 → 100644
| 1 | +// | |
| 2 | +// CNBarrageManager.h | |
| 3 | +// personalXmppChatDemo | |
| 4 | +// | |
| 5 | +// Created by 张旭 on 2016/12/10. | |
| 6 | +// Copyright © 2016年 cnlive. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | +#import "chatMsgModel.h" | |
| 11 | + | |
| 12 | +@class CNBarrageView; | |
| 13 | + | |
| 14 | +@interface CNBarrageManager : NSObject | |
| 15 | + | |
| 16 | +@property (nonatomic, copy) void(^generateBarrageBlock)(CNBarrageView *view);//生成弹幕View回调 | |
| 17 | +@property (nonatomic) BOOL isStopBarrage;//是否关闭了弹幕 | |
| 18 | +/** | |
| 19 | + 开始弹幕根据新消息数组 | |
| 20 | + | |
| 21 | + @param newBarrageArray 新消息数组 | |
| 22 | + */ | |
| 23 | +- (void)startBarrageWithNewArray:(NSMutableArray <chatMsgModel *>*)newBarrageArray; | |
| 24 | + | |
| 25 | +/** | |
| 26 | + 停止弹幕 | |
| 27 | + */ | |
| 28 | +- (void)stopBarrage; | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | +@end | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Barrage/CNBarrageManager.m
0 → 100644
| 1 | +// | |
| 2 | +// CNBarrageManager.m | |
| 3 | +// personalXmppChatDemo | |
| 4 | +// | |
| 5 | +// Created by 张旭 on 2016/12/10. | |
| 6 | +// Copyright © 2016年 cnlive. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "CNBarrageManager.h" | |
| 10 | +#import "CNBarrageView.h" | |
| 11 | + | |
| 12 | +#define MAX_OVERLAP_COUNT 100 | |
| 13 | + | |
| 14 | +@interface CNBarrageManager () | |
| 15 | + | |
| 16 | +@property (nonatomic, strong) NSMutableArray *_Nullable allComments;//所有评论 | |
| 17 | +@property (nonatomic, strong) NSMutableArray *_Nullable tmpComments;//临时评论 | |
| 18 | +@property (nonatomic ,strong) NSMutableArray *_Nullable barrageQueue;//评论管理队列数组 | |
| 19 | +@property (nonatomic ,strong) NSMutableArray *_Nullable trajectoryArr;//弹幕轨迹数组 | |
| 20 | + | |
| 21 | +@property BOOL isStarted;//标记是否开始弹幕 | |
| 22 | +@property BOOL isStopAnimation;//标记是否停止弹幕 | |
| 23 | + | |
| 24 | +@end | |
| 25 | + | |
| 26 | +@implementation CNBarrageManager | |
| 27 | + | |
| 28 | +/** | |
| 29 | + 开始弹幕根据新消息数组 | |
| 30 | + | |
| 31 | + @param newBarrageArray 新消息数组 | |
| 32 | + */ | |
| 33 | +- (void)startBarrageWithNewArray:(NSMutableArray <chatMsgModel *>*)newBarrageArray | |
| 34 | +{ | |
| 35 | + if (self.isStopAnimation && _isStopBarrage) { | |
| 36 | + return; | |
| 37 | + } | |
| 38 | + [self.allComments addObjectsFromArray:newBarrageArray]; | |
| 39 | + | |
| 40 | + [self startBarrage]; | |
| 41 | +} | |
| 42 | + | |
| 43 | +/** | |
| 44 | + 开始弹幕 | |
| 45 | + */ | |
| 46 | +- (void)startBarrage | |
| 47 | +{ | |
| 48 | + if (self.tmpComments.count == 0) { | |
| 49 | + [self.tmpComments addObjectsFromArray:self.allComments]; | |
| 50 | + [self.allComments removeAllObjects]; | |
| 51 | + } | |
| 52 | + | |
| 53 | + self.isStarted = YES; | |
| 54 | + self.isStopAnimation = NO; | |
| 55 | + [self initBarrageCommentView]; | |
| 56 | +} | |
| 57 | + | |
| 58 | +/** | |
| 59 | + 停止弹幕 | |
| 60 | + */ | |
| 61 | +- (void)stopBarrage | |
| 62 | +{ | |
| 63 | + self.isStopAnimation = YES; | |
| 64 | + | |
| 65 | + [self.barrageQueue enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { | |
| 66 | + CNBarrageView *view = obj; | |
| 67 | + [view stopAnimation]; | |
| 68 | + view = nil; | |
| 69 | + self.tmpComments = nil; | |
| 70 | + self.allComments = nil; | |
| 71 | + self.trajectoryArr = nil; | |
| 72 | + }]; | |
| 73 | + self.barrageQueue = nil; | |
| 74 | +} | |
| 75 | + | |
| 76 | +/** | |
| 77 | + 初始化弹幕的评论View | |
| 78 | + */ | |
| 79 | +- (void)initBarrageCommentView | |
| 80 | +{ | |
| 81 | + if(self.isStopAnimation)return; | |
| 82 | + //初始化轨道位置随机 | |
| 83 | + long count = self.tmpComments.count; | |
| 84 | + for (int i = 0; i < count; i ++) { | |
| 85 | + chatMsgModel *model = [self.tmpComments firstObject]; | |
| 86 | + NSString *comment = model.content; | |
| 87 | + if (comment) { | |
| 88 | + [self.tmpComments removeObjectAtIndex:0]; | |
| 89 | + //根据当前未发送弹幕数量生成轨迹 | |
| 90 | + NSString *trajectory; | |
| 91 | + if (self.tmpComments.count > MAX_OVERLAP_COUNT) | |
| 92 | + {//数量较多轨迹可重叠 | |
| 93 | + trajectory = [self trajectoryOverlap:YES]; | |
| 94 | + }else | |
| 95 | + {//数量较少轨迹可能不重叠,但频率高会使轨迹数组已满,造成重叠 | |
| 96 | + trajectory = [self trajectoryOverlap:NO]; | |
| 97 | + } | |
| 98 | + [self createBarrageComment:comment trajectory:trajectory isMine:model.isMine]; | |
| 99 | + } | |
| 100 | + else { | |
| 101 | + //当弹幕没有时跳出循环 | |
| 102 | + break; | |
| 103 | + } | |
| 104 | + } | |
| 105 | +} | |
| 106 | + | |
| 107 | +/** | |
| 108 | + 评论弹幕轨迹 | |
| 109 | + | |
| 110 | + @param isOverlap 是否重叠 | |
| 111 | + @return 根据轨迹是否可重叠,生成对应的新轨迹 | |
| 112 | + */ | |
| 113 | +- (NSString *)trajectoryOverlap:(BOOL)isOverlap | |
| 114 | +{ | |
| 115 | + NSString *trajectory = @""; | |
| 116 | + long arcIndex = arc4random() % MAX_BARRAGE_VERTICAL_COUNT; | |
| 117 | + CGFloat tra = arcIndex * BARRAGE_VERTICAL_HEIGHT + (arcIndex - 1) * BARRAGE_VERTICAL_MARGIN; | |
| 118 | + if (isOverlap) { | |
| 119 | + //生成可重叠的轨迹 | |
| 120 | + trajectory = [NSString stringWithFormat:@"%f",tra]; | |
| 121 | + [self.trajectoryArr addObject:trajectory]; | |
| 122 | + return [NSString stringWithFormat:@"%f",tra]; | |
| 123 | + } | |
| 124 | + //生成不重叠的轨迹 | |
| 125 | + do { | |
| 126 | + arcIndex = arc4random() % MAX_BARRAGE_VERTICAL_COUNT; | |
| 127 | + tra = arcIndex * BARRAGE_VERTICAL_HEIGHT + (arcIndex - 1) * BARRAGE_VERTICAL_MARGIN; | |
| 128 | + trajectory = [NSString stringWithFormat:@"%f",tra]; | |
| 129 | + if (self.trajectoryArr.count >= MAX_BARRAGE_VERTICAL_COUNT) break; | |
| 130 | + | |
| 131 | + } while ([self.trajectoryArr containsObject:trajectory]); | |
| 132 | + if (self.trajectoryArr.count >= MAX_BARRAGE_VERTICAL_COUNT) | |
| 133 | + {//当前轨迹数组已满,弹幕需要重叠显示 | |
| 134 | + | |
| 135 | + }else | |
| 136 | + {//当前轨迹数组还没满,弹幕无需重叠 | |
| 137 | + [self.trajectoryArr addObject:trajectory]; | |
| 138 | + } | |
| 139 | + return trajectory; | |
| 140 | +} | |
| 141 | + | |
| 142 | +/** | |
| 143 | + 下一条评论 | |
| 144 | + | |
| 145 | + @return 返回当前tmpComments的下一条评论数据 | |
| 146 | + */ | |
| 147 | +- (NSString *)nextComment { | |
| 148 | + chatMsgModel *model = [self.tmpComments firstObject]; | |
| 149 | + if (model.content) { | |
| 150 | + [self.tmpComments removeObjectAtIndex:0]; | |
| 151 | + } | |
| 152 | + return model.content; | |
| 153 | +} | |
| 154 | + | |
| 155 | +/** | |
| 156 | + 创建评论弹幕,根据评论内容和弹幕轨迹 | |
| 157 | + | |
| 158 | + @param comment 评论内容 | |
| 159 | + @param trajectory 弹幕轨迹 | |
| 160 | + */ | |
| 161 | +- (void)createBarrageComment:(NSString *)comment trajectory:(NSString *)trajectory isMine:(BOOL)isMine | |
| 162 | +{ | |
| 163 | + if (self.isStopAnimation) { | |
| 164 | + return; | |
| 165 | + } | |
| 166 | + //创建一个弹幕view | |
| 167 | + CNBarrageView *view = [[CNBarrageView alloc] initWithContent:comment isMine:isMine]; | |
| 168 | + | |
| 169 | + //设置运行轨迹 | |
| 170 | + view.trajectory = [trajectory floatValue]; | |
| 171 | + weakself | |
| 172 | + __weak CNBarrageView *weakBarrageView = view; | |
| 173 | + view.moveBlock = ^(CommentMoveState status){ | |
| 174 | + strongself | |
| 175 | + if (self.isStopAnimation) { | |
| 176 | + return; | |
| 177 | + } | |
| 178 | + switch (status) { | |
| 179 | + case CommentMoveStateStart: | |
| 180 | + { | |
| 181 | + //弹幕开始,将view加入弹幕管理数组 | |
| 182 | + [self.barrageQueue addObject:weakBarrageView]; | |
| 183 | + } | |
| 184 | + break; | |
| 185 | + case CommentMoveStateEnter: | |
| 186 | + { | |
| 187 | + [self.trajectoryArr removeObject:trajectory]; | |
| 188 | + //弹幕完全进入屏幕,判断接下来是否还有内容,如果有则在该弹幕轨迹队列中创建弹幕 | |
| 189 | + NSString *comment = [self nextComment]; | |
| 190 | + if (comment) { | |
| 191 | + [self createBarrageComment:comment trajectory:trajectory isMine:isMine]; | |
| 192 | + } | |
| 193 | + else { | |
| 194 | + //没有评论了 | |
| 195 | + } | |
| 196 | + } | |
| 197 | + break; | |
| 198 | + case CommentMoveStateEnd: | |
| 199 | + { | |
| 200 | + //弹幕飞出屏幕后从弹幕管理队列中删除 | |
| 201 | + if ([self.barrageQueue containsObject:weakBarrageView]) { | |
| 202 | + [self.barrageQueue removeObject:weakBarrageView]; | |
| 203 | + } | |
| 204 | + } | |
| 205 | + break; | |
| 206 | + default: | |
| 207 | + break; | |
| 208 | + } | |
| 209 | + }; | |
| 210 | + //弹幕生成后,传到Controller进行页面展示 | |
| 211 | + if (self.generateBarrageBlock) { | |
| 212 | + self.generateBarrageBlock(view); | |
| 213 | + } | |
| 214 | +} | |
| 215 | + | |
| 216 | +#pragma mark - getter | |
| 217 | + | |
| 218 | +- (NSMutableArray *)allComments { | |
| 219 | + if (!_allComments) { | |
| 220 | + _allComments = [NSMutableArray array]; | |
| 221 | + } | |
| 222 | + return _allComments; | |
| 223 | +} | |
| 224 | + | |
| 225 | +- (NSMutableArray *)tmpComments { | |
| 226 | + if (!_tmpComments) { | |
| 227 | + _tmpComments = [NSMutableArray array]; | |
| 228 | + } | |
| 229 | + return _tmpComments; | |
| 230 | +} | |
| 231 | + | |
| 232 | +- (NSMutableArray *)barrageQueue { | |
| 233 | + if (!_barrageQueue) { | |
| 234 | + _barrageQueue = [NSMutableArray array]; | |
| 235 | + } | |
| 236 | + return _barrageQueue; | |
| 237 | +} | |
| 238 | + | |
| 239 | +- (NSMutableArray *)trajectoryArr { | |
| 240 | + if (!_trajectoryArr) { | |
| 241 | + _trajectoryArr = [NSMutableArray array]; | |
| 242 | + } | |
| 243 | + return _trajectoryArr; | |
| 244 | +} | |
| 245 | + | |
| 246 | +@end | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Barrage/CNBarrageView.h
0 → 100644
| 1 | +// | |
| 2 | +// CNBarrageView.h | |
| 3 | +// personalXmppChatDemo | |
| 4 | +// | |
| 5 | +// Created by 张旭 on 2016/12/10. | |
| 6 | +// Copyright © 2016年 cnlive. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <UIKit/UIKit.h> | |
| 10 | + | |
| 11 | +#define BARRAGE_VERTICAL_HEIGHT 25 //每个弹幕View在垂直方向上的高度 | |
| 12 | +#define MAX_BARRAGE_VERTICAL_COUNT (long)[UIScreen mainScreen].bounds.size.height / BARRAGE_VERTICAL_HEIGHT //垂直方向上的弹幕最大数量 | |
| 13 | +#define BARRAGE_VERTICAL_MARGIN ([UIScreen mainScreen].bounds.size.height - BARRAGE_VERTICAL_HEIGHT * MAX_BARRAGE_VERTICAL_COUNT) / (MAX_BARRAGE_VERTICAL_COUNT - 1) //垂直方向上弹幕之间的间隙 | |
| 14 | + | |
| 15 | +typedef NS_ENUM(NSInteger, CommentMoveState){//弹幕移动的状态 | |
| 16 | + CommentMoveStateStart = 0,//将要进入屏幕 | |
| 17 | + CommentMoveStateEnter ,//完全进入 | |
| 18 | + CommentMoveStateEnd //完全移除屏幕 | |
| 19 | +}; | |
| 20 | + | |
| 21 | + | |
| 22 | +@interface CNBarrageView : UIView | |
| 23 | + | |
| 24 | +@property (nonatomic ,copy) void (^moveBlock) (CommentMoveState state);//弹幕移动的状态 | |
| 25 | +@property (nonatomic) CGFloat trajectory;//弹幕的移动轨迹 | |
| 26 | + | |
| 27 | +/** | |
| 28 | + 初始化弹幕View根据评论内容,消息是否是自己发送 | |
| 29 | + | |
| 30 | + @param content 评论内容 | |
| 31 | + @param isMine 是否是自己的评论弹幕 | |
| 32 | + @return 弹幕View | |
| 33 | + */ | |
| 34 | +- (instancetype)initWithContent:(NSString *)content isMine:(BOOL)isMine; | |
| 35 | + | |
| 36 | +/** | |
| 37 | + 开始移动动画 | |
| 38 | + */ | |
| 39 | +- (void)startAnimation; | |
| 40 | + | |
| 41 | +/** | |
| 42 | + 停止移动动画 | |
| 43 | + */ | |
| 44 | +- (void)stopAnimation; | |
| 45 | + | |
| 46 | +@end | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Barrage/CNBarrageView.m
0 → 100644
| 1 | + | |
| 2 | +// | |
| 3 | +// CNBarrageView.m | |
| 4 | +// personalXmppChatDemo | |
| 5 | +// | |
| 6 | +// Created by 张旭 on 2016/12/10. | |
| 7 | +// Copyright © 2016年 cnlive. All rights reserved. | |
| 8 | +// | |
| 9 | + | |
| 10 | +#import "CNBarrageView.h" | |
| 11 | + | |
| 12 | +#define TotalDuration 5 //弹幕飘过总时间 | |
| 13 | +#define BARRAGE_Horizontal_Margin 5 //弹幕间水平间隙 | |
| 14 | + | |
| 15 | +#define LVCRandomColor LVCColor(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256)) | |
| 16 | +#define LVCColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | +@interface CNBarrageView () | |
| 21 | + | |
| 22 | +@property (nonatomic ,strong) UILabel * _Nullable commentLabel;//评论Label | |
| 23 | +@property BOOL isDealloc;//标记资源是否已释放 | |
| 24 | + | |
| 25 | +@end | |
| 26 | + | |
| 27 | +@implementation CNBarrageView | |
| 28 | + | |
| 29 | +/** | |
| 30 | + 销毁对象及动画 | |
| 31 | + */ | |
| 32 | +- (void)dealloc | |
| 33 | +{ | |
| 34 | + [self stopAnimation]; | |
| 35 | + self.moveBlock = nil; | |
| 36 | +} | |
| 37 | + | |
| 38 | +/** | |
| 39 | + 初始化弹幕View根据评论内容,消息是否是自己发送 | |
| 40 | + | |
| 41 | + @param content 评论内容 | |
| 42 | + @param isMine 是否是自己的评论弹幕 | |
| 43 | + @return 弹幕View | |
| 44 | + */ | |
| 45 | +- (instancetype)initWithContent:(NSString *)content isMine:(BOOL)isMine | |
| 46 | +{ | |
| 47 | + if (self = [super init]) | |
| 48 | + { | |
| 49 | + NSDictionary *attributes = @{NSFontAttributeName:[UIFont systemFontOfSize:17]}; | |
| 50 | + float width = [content sizeWithAttributes:attributes].width; | |
| 51 | +// float height = [content sizeWithAttributes:attributes].height; | |
| 52 | +// NSLog(@"%f",height);//16.707031 | |
| 53 | + self.bounds = CGRectMake(0, 0, width + BARRAGE_Horizontal_Margin * 2, BARRAGE_VERTICAL_HEIGHT); | |
| 54 | + self.commentLabel.text = content; | |
| 55 | + self.commentLabel.frame = CGRectMake(BARRAGE_Horizontal_Margin, 0, width, BARRAGE_VERTICAL_HEIGHT); | |
| 56 | + if(isMine) | |
| 57 | + { | |
| 58 | + self.commentLabel.textColor = [UIColor redColor]; | |
| 59 | + }else | |
| 60 | + { | |
| 61 | + self.commentLabel.textColor = LVCRandomColor; | |
| 62 | + } | |
| 63 | + | |
| 64 | + } | |
| 65 | + return self; | |
| 66 | +} | |
| 67 | + | |
| 68 | +/** | |
| 69 | + 开始移动动画 | |
| 70 | + */ | |
| 71 | +- (void)startAnimation | |
| 72 | +{ | |
| 73 | + CGFloat wholeWidth = self.width + SCREEN_WIDTH + 50;//总轨迹长度 | |
| 74 | + CGFloat speed = wholeWidth / TotalDuration;//速度 | |
| 75 | + CGFloat duration = (self.width + 50) / speed;//完全进入屏幕的时间 | |
| 76 | + | |
| 77 | + if (self.moveBlock) { | |
| 78 | + //弹幕开始进入屏幕 | |
| 79 | + self.moveBlock(CommentMoveStateStart); | |
| 80 | + } | |
| 81 | + | |
| 82 | + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | |
| 83 | + //避免重复,若资源已释放 不再操作 | |
| 84 | + if (self.isDealloc) { | |
| 85 | + return; | |
| 86 | + } | |
| 87 | + //duration时间后弹幕完全进入屏幕 | |
| 88 | + if (self.moveBlock) { | |
| 89 | + self.moveBlock(CommentMoveStateEnter); | |
| 90 | + } | |
| 91 | + }); | |
| 92 | + | |
| 93 | + weakself | |
| 94 | + //弹幕完全离开屏幕 | |
| 95 | + [UIView animateWithDuration:TotalDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ | |
| 96 | + strongself | |
| 97 | + self.left = - self.width; | |
| 98 | + } completion:^(BOOL finished) { | |
| 99 | + if (self.moveBlock) { | |
| 100 | + self.moveBlock(CommentMoveStateEnd); | |
| 101 | + } | |
| 102 | + [self removeFromSuperview]; | |
| 103 | + }]; | |
| 104 | + | |
| 105 | +} | |
| 106 | + | |
| 107 | +/** | |
| 108 | + 停止移动动画 | |
| 109 | + */ | |
| 110 | +- (void)stopAnimation | |
| 111 | +{ | |
| 112 | + self.isDealloc = YES; | |
| 113 | + [self.layer removeAllAnimations]; | |
| 114 | + [self removeFromSuperview]; | |
| 115 | +} | |
| 116 | + | |
| 117 | +#pragma mark getter | |
| 118 | + | |
| 119 | +- (UILabel *)commentLabel | |
| 120 | +{ | |
| 121 | + if (!_commentLabel) { | |
| 122 | + _commentLabel = [[UILabel alloc] init]; | |
| 123 | + _commentLabel.backgroundColor = [UIColor clearColor]; | |
| 124 | + _commentLabel.font = [UIFont systemFontOfSize:17]; | |
| 125 | + _commentLabel.textColor = [UIColor whiteColor]; | |
| 126 | + [self addSubview:self.commentLabel]; | |
| 127 | + } | |
| 128 | + return _commentLabel; | |
| 129 | +} | |
| 130 | + | |
| 131 | +/* | |
| 132 | +// Only override drawRect: if you perform custom drawing. | |
| 133 | +// An empty implementation adversely affects performance during animation. | |
| 134 | +- (void)drawRect:(CGRect)rect { | |
| 135 | + // Drawing code | |
| 136 | +} | |
| 137 | +*/ | |
| 138 | + | |
| 139 | +@end | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuLabel.h deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuLabel.h | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import <UIKit/UIKit.h> | |
| 10 | -#import "LVCDanmuUtil.h" | |
| 11 | - | |
| 12 | -@interface LVCDanmuLabel : UILabel | |
| 13 | - | |
| 14 | - | |
| 15 | -@property (nonatomic, strong, readonly) NSDictionary *info; | |
| 16 | -@property (nonatomic, readonly) DanmuState danmuState; | |
| 17 | -@property (nonatomic, readonly) CGFloat animationDuartion; | |
| 18 | -@property (nonatomic, strong, readonly) NSDictionary *dicOptional; | |
| 19 | - | |
| 20 | -@property (nonatomic, readonly) CGFloat speed; | |
| 21 | -@property (nonatomic, readonly) CGFloat currentRightX; | |
| 22 | - | |
| 23 | -@property (nonatomic, readonly) CGFloat startTime; | |
| 24 | - | |
| 25 | - | |
| 26 | -@property (nonatomic, getter=isFontSizeBig, readonly) BOOL fontSizeBig; | |
| 27 | -@property (nonatomic, getter=isFontSizeMiddle, readonly) BOOL fontSizeMiddle; | |
| 28 | -@property (nonatomic, getter=isFontSizeSmall, readonly) BOOL fontSizeSmall; | |
| 29 | -@property (nonatomic, getter=isMoveModeRolling, readonly) BOOL moveModeRolling; | |
| 30 | -@property (nonatomic, getter=isPositionTop, readonly) BOOL positionTop; | |
| 31 | -@property (nonatomic, getter=isPositionMiddle, readonly) BOOL positionMiddle; | |
| 32 | -@property (nonatomic, getter=isPositionBottom, readonly) BOOL positionBottom; | |
| 33 | - | |
| 34 | -+ (instancetype)createWithInfo:(NSDictionary *)info inView:(UIView *)view; | |
| 35 | - | |
| 36 | -- (void)setDanmuChannel:(NSUInteger)channel offset:(CGFloat)xy; | |
| 37 | - | |
| 38 | -- (void)animationDanmuItem:(NSTimeInterval)waitTime; | |
| 39 | - | |
| 40 | -- (void)pause; | |
| 41 | - | |
| 42 | -- (void)resume:(NSTimeInterval)nowTime; | |
| 43 | - | |
| 44 | -- (void)removeDanmu; | |
| 45 | - | |
| 46 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuLabel.m deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuLabel.m | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import "LVCDanmuLabel.h" | |
| 10 | - | |
| 11 | -static NSString * const DANMU_FONT_SIZE_BIG = @"l"; | |
| 12 | -static NSString * const DANMU_FONT_SIZE_MIDDLE = @"m"; | |
| 13 | -static NSString * const DANMU_FONT_SIZE_SMALL = @"s"; | |
| 14 | - | |
| 15 | -static NSString * const DANMU_MOVE_MODE_ROLLING = @"l"; | |
| 16 | - | |
| 17 | -static NSString * const DANMU_POSITION_TOP = @"t"; | |
| 18 | -static NSString * const DANMU_POSITION_MIDDLE = @"m"; | |
| 19 | -static NSString * const DANMU_POSITION_BOTTOM = @"b"; | |
| 20 | - | |
| 21 | -#define ARC4RANDOM_MAX 0x100000000 | |
| 22 | - | |
| 23 | -#define ROLL_ANIMATION_DURATION_TIME 5 | |
| 24 | - | |
| 25 | -#define ANIMATION_DELAY_TIME 3 | |
| 26 | - | |
| 27 | -@interface LVCDanmuLabel () | |
| 28 | - | |
| 29 | -@property (nonatomic, strong, readwrite) NSDictionary *info; | |
| 30 | -@property (nonatomic, readwrite) DanmuState danmuState; | |
| 31 | -@property (nonatomic, readwrite) CGFloat animationDuartion; | |
| 32 | -@property (nonatomic, strong, readwrite) NSDictionary *dicOptional; | |
| 33 | - | |
| 34 | -@property (nonatomic, readwrite) CGFloat speed; | |
| 35 | -@property (nonatomic, readwrite) CGFloat currentRightX; | |
| 36 | - | |
| 37 | -@property (nonatomic) NSUInteger nChannel; | |
| 38 | -@property (nonatomic, weak) UIView *superView; | |
| 39 | - | |
| 40 | -@property (nonatomic) CGFloat originalX; | |
| 41 | - | |
| 42 | -@end | |
| 43 | - | |
| 44 | -@implementation LVCDanmuLabel | |
| 45 | - | |
| 46 | -- (void)dealloc { | |
| 47 | - _info = nil; | |
| 48 | - _dicOptional = nil; | |
| 49 | -} | |
| 50 | - | |
| 51 | -#pragma mark - Private | |
| 52 | - | |
| 53 | -- (void)p_initData { | |
| 54 | - self.textColor = [UIColor blackColor]; | |
| 55 | - // 弹幕颜色 | |
| 56 | - // id optional = [self.info objectForKey:kDanmuOptionalKey]; | |
| 57 | - // if ([optional isKindOfClass:[NSString class]]) { | |
| 58 | - // optional = [LVCDanmuUtil defaultOptions]; | |
| 59 | - // } | |
| 60 | - id optional = [LVCDanmuUtil randomOptions]; | |
| 61 | - self.dicOptional = [NSDictionary dictionaryWithDictionary:optional]; | |
| 62 | - | |
| 63 | - int color = [[optional objectForKey:@"c"] intValue]; | |
| 64 | - [self setTextColor:[LVCDanmuUtil colorFromARGB: color]]; | |
| 65 | - | |
| 66 | - CGFloat fontsize = 15; | |
| 67 | - if (self.isFontSizeBig) { | |
| 68 | - fontsize = 19; | |
| 69 | - }else if (self.isFontSizeMiddle) { | |
| 70 | - fontsize = 17; | |
| 71 | - } | |
| 72 | - | |
| 73 | - UIFont *font = [UIFont systemFontOfSize:fontsize]; | |
| 74 | - self.font = font; | |
| 75 | - | |
| 76 | - NSString *content = [_info objectForKey:kDanmuContentKey]; | |
| 77 | - self.text = content; | |
| 78 | -} | |
| 79 | - | |
| 80 | -- (void)p_initFrame:(CGFloat)offsetX { | |
| 81 | - NSString *content = [self.info objectForKey:kDanmuContentKey]; | |
| 82 | - CGSize size = [LVCDanmuUtil getSizeWithString:content withFont:self.font size:(CGSize){MAXFLOAT, CHANNEL_HEIGHT}]; | |
| 83 | - CGRect frame = (CGRect){(CGPoint){_superView.frame.size.width + offsetX, 0}, size}; | |
| 84 | - self.frame = frame; | |
| 85 | - _originalX = frame.origin.x + frame.size.width; | |
| 86 | -} | |
| 87 | - | |
| 88 | -- (void)p_rollAnimation:(CGFloat)time delay:(NSTimeInterval)waitTime { | |
| 89 | - self.danmuState = DanmuStateAnimationing; | |
| 90 | - [UIView animateWithDuration:time delay:waitTime options:UIViewAnimationOptionCurveLinear animations:^{ | |
| 91 | - CGRect frame = self.frame; | |
| 92 | - frame.origin.x = -self.frame.size.width; | |
| 93 | - self.frame = frame; | |
| 94 | - } completion:^(BOOL finished) { | |
| 95 | - if (finished) | |
| 96 | - [self removeDanmu]; | |
| 97 | - }]; | |
| 98 | -} | |
| 99 | - | |
| 100 | -#pragma mark - Action | |
| 101 | - | |
| 102 | -+ (instancetype)createWithInfo:(NSDictionary *)info inView:(UIView *)view { | |
| 103 | - LVCDanmuLabel *danmuLabel = [[LVCDanmuLabel alloc] init]; | |
| 104 | - | |
| 105 | - danmuLabel.info = info; | |
| 106 | - danmuLabel.superView = view; | |
| 107 | - danmuLabel.nChannel = 0; | |
| 108 | - | |
| 109 | - [danmuLabel p_initData]; | |
| 110 | - [danmuLabel p_initFrame:0]; | |
| 111 | - | |
| 112 | - return danmuLabel; | |
| 113 | -} | |
| 114 | - | |
| 115 | -- (void)setDanmuChannel:(NSUInteger)channel offset:(CGFloat)xy { | |
| 116 | - self.danmuState = DanmuStateStop; | |
| 117 | - self.nChannel = channel; | |
| 118 | - CGRect frame = self.frame; | |
| 119 | - frame.origin.x += xy; | |
| 120 | - frame.origin.y = CHANNEL_HEIGHT*_nChannel; | |
| 121 | - self.frame = frame; | |
| 122 | - _originalX = frame.origin.x + frame.size.width; | |
| 123 | - [_superView addSubview:self]; | |
| 124 | -} | |
| 125 | - | |
| 126 | -- (void)animationDanmuItem:(NSTimeInterval)waitTime { | |
| 127 | - | |
| 128 | - [self p_rollAnimation:self.animationDuartion delay:waitTime]; | |
| 129 | -} | |
| 130 | - | |
| 131 | -- (void)pause { | |
| 132 | - self.danmuState = DanmuStateStop; | |
| 133 | - UIView *view = self; | |
| 134 | - CALayer *layer = view.layer; | |
| 135 | - CGRect rect = view.frame; | |
| 136 | - if (layer.presentationLayer) { | |
| 137 | - rect = ((CALayer *)layer.presentationLayer).frame; | |
| 138 | - // rect.origin.x -= 1; | |
| 139 | - } | |
| 140 | - view.frame = rect; | |
| 141 | - [view.layer removeAllAnimations]; | |
| 142 | -} | |
| 143 | - | |
| 144 | -- (void)resume:(NSTimeInterval)nowTime { | |
| 145 | - CGFloat waitTime = self.startTime; | |
| 146 | - if (waitTime > nowTime) | |
| 147 | - waitTime = waitTime - nowTime; | |
| 148 | - else | |
| 149 | - waitTime = 0; | |
| 150 | - | |
| 151 | - CGFloat time = (self.frame.origin.x + self.frame.size.width)/self.speed; | |
| 152 | - [self p_rollAnimation:time delay:waitTime]; | |
| 153 | -} | |
| 154 | - | |
| 155 | -- (void)removeDanmu { | |
| 156 | - self.danmuState = DanmuStateFinish; | |
| 157 | - [self.layer removeAllAnimations]; | |
| 158 | - [self removeFromSuperview]; | |
| 159 | -} | |
| 160 | - | |
| 161 | - | |
| 162 | -#pragma mark - Get | |
| 163 | - | |
| 164 | -- (CGFloat)speed { | |
| 165 | - _speed = _originalX/self.animationDuartion; | |
| 166 | - return _speed; | |
| 167 | -} | |
| 168 | - | |
| 169 | -- (CGFloat)animationDuartion { | |
| 170 | - _animationDuartion = ROLL_ANIMATION_DURATION_TIME; | |
| 171 | - return _animationDuartion; | |
| 172 | -} | |
| 173 | - | |
| 174 | -- (CGFloat)currentRightX { | |
| 175 | - switch (self.danmuState) { | |
| 176 | - case DanmuStateStop: { | |
| 177 | - _currentRightX = CGRectGetMaxX(self.frame) - _superView.frame.size.width; | |
| 178 | - break; | |
| 179 | - } | |
| 180 | - case DanmuStateAnimationing: { | |
| 181 | - CALayer *layer = self.layer; | |
| 182 | - _currentRightX = _originalX; | |
| 183 | - if (layer.presentationLayer) | |
| 184 | - _currentRightX = ((CALayer *)layer.presentationLayer).frame.origin.x + self.frame.size.width; | |
| 185 | - _currentRightX -= _superView.frame.size.width; | |
| 186 | - break; | |
| 187 | - } | |
| 188 | - case DanmuStateFinish: { | |
| 189 | - _currentRightX = -_superView.frame.size.width; | |
| 190 | - break; | |
| 191 | - } | |
| 192 | - default: { | |
| 193 | - break; | |
| 194 | - } | |
| 195 | - } | |
| 196 | - return _currentRightX; | |
| 197 | -} | |
| 198 | - | |
| 199 | -#pragma mark - | |
| 200 | - | |
| 201 | -- (CGFloat)startTime { | |
| 202 | - return [[self.info valueForKey:kDanmuTimeKey] floatValue]; | |
| 203 | -} | |
| 204 | - | |
| 205 | -- (NSString *)fontSize { | |
| 206 | - return [self.dicOptional valueForKey: @"s"]; | |
| 207 | -} | |
| 208 | - | |
| 209 | -- (NSString *)moveMode { | |
| 210 | - return [self.dicOptional valueForKey: @"m"]; | |
| 211 | -} | |
| 212 | - | |
| 213 | -- (NSString *)position { | |
| 214 | - return [self.dicOptional valueForKey: @"p"]; | |
| 215 | -} | |
| 216 | - | |
| 217 | -- (BOOL)isFontSizeBig { | |
| 218 | - return [[self fontSize] isEqualToString: DANMU_FONT_SIZE_BIG]; | |
| 219 | -} | |
| 220 | - | |
| 221 | -- (BOOL)isFontSizeMiddle { | |
| 222 | - return [[self fontSize] isEqualToString: DANMU_FONT_SIZE_MIDDLE]; | |
| 223 | -} | |
| 224 | - | |
| 225 | -- (BOOL)isFontSizeSmall { | |
| 226 | - return [[self fontSize] isEqualToString: DANMU_FONT_SIZE_SMALL]; | |
| 227 | -} | |
| 228 | - | |
| 229 | -- (BOOL)isMoveModeRolling { | |
| 230 | - return [[self moveMode] isEqualToString: DANMU_MOVE_MODE_ROLLING]; | |
| 231 | -} | |
| 232 | - | |
| 233 | -- (BOOL)isPositionTop { | |
| 234 | - return [[self position] isEqualToString: DANMU_POSITION_TOP]; | |
| 235 | -} | |
| 236 | - | |
| 237 | -- (BOOL)isPositionMiddle { | |
| 238 | - return [[self position] isEqualToString: DANMU_POSITION_MIDDLE]; | |
| 239 | -} | |
| 240 | - | |
| 241 | -- (BOOL)isPositionBottom { | |
| 242 | - return [[self position] isEqualToString: DANMU_POSITION_BOTTOM]; | |
| 243 | -} | |
| 244 | - | |
| 245 | -/* | |
| 246 | -// Only override drawRect: if you perform custom drawing. | |
| 247 | -// An empty implementation adversely affects performance during animation. | |
| 248 | -- (void)drawRect:(CGRect)rect { | |
| 249 | - // Drawing code | |
| 250 | -} | |
| 251 | -*/ | |
| 252 | - | |
| 253 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuManager.h deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuManager.h | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import <Foundation/Foundation.h> | |
| 10 | -#import <UIKit/UIKit.h> | |
| 11 | -#import "LVCDanmuUtil.h" | |
| 12 | - | |
| 13 | -/** | |
| 14 | - * 弹幕状态 | |
| 15 | - */ | |
| 16 | -typedef NS_ENUM(NSUInteger, DanmuManagerState) { | |
| 17 | - /** | |
| 18 | - * 弹幕准备 | |
| 19 | - */ | |
| 20 | - DanmuManagerStateWait = 1, | |
| 21 | - /** | |
| 22 | - * 弹幕关闭 | |
| 23 | - */ | |
| 24 | - DanmuManagerStateStop, | |
| 25 | - /** | |
| 26 | - * 弹幕运动 | |
| 27 | - */ | |
| 28 | - DanmuManagerStateAnimationing, | |
| 29 | - /** | |
| 30 | - * 弹幕暂停 | |
| 31 | - */ | |
| 32 | - DanmuManagerStatePause | |
| 33 | -}; | |
| 34 | - | |
| 35 | -@interface LVCDanmuManager : NSObject | |
| 36 | - | |
| 37 | -/** | |
| 38 | - * 弹幕添加的UIView | |
| 39 | - */ | |
| 40 | -@property (nonatomic, strong, readonly) UIView *danmuView; | |
| 41 | -/** | |
| 42 | - * 弹幕状态 | |
| 43 | - */ | |
| 44 | -@property (nonatomic, readonly) DanmuManagerState danmuManagerState; | |
| 45 | -/** | |
| 46 | - * 创建弹幕管理对象 | |
| 47 | - * | |
| 48 | - * @param frame 弹幕显示的frame | |
| 49 | - * @param infos 弹幕信息,数组集合 | |
| 50 | - * @param view 弹幕添加的UIView | |
| 51 | - * @param time 弹幕刷新的间隔时间,一般1秒 | |
| 52 | - * | |
| 53 | - * @return | |
| 54 | - */ | |
| 55 | -- (instancetype)initWithFrame:(CGRect)frame data:(NSArray *)infos inView:(UIView *)view durationTime:(NSUInteger)time; | |
| 56 | -/** | |
| 57 | - * 弹幕初始化创建 | |
| 58 | - */ | |
| 59 | -- (void)initStart; | |
| 60 | -/** | |
| 61 | - * 弹幕滚动 | |
| 62 | - * | |
| 63 | - * @param startTime 目前的时间点 | |
| 64 | - */ | |
| 65 | -- (void)rollDanmu:(NSTimeInterval)startTime; | |
| 66 | -/** | |
| 67 | - * 弹幕关闭 | |
| 68 | - */ | |
| 69 | -- (void)stop; | |
| 70 | -/** | |
| 71 | - * 弹幕暂停 | |
| 72 | - */ | |
| 73 | -- (void)pause; | |
| 74 | -/** | |
| 75 | - * 弹幕继续 | |
| 76 | - * | |
| 77 | - * @param nowTime 现在的时间点 | |
| 78 | - */ | |
| 79 | -- (void)resume:(NSTimeInterval)nowTime; | |
| 80 | -/** | |
| 81 | - * 弹幕重新恢复 | |
| 82 | - */ | |
| 83 | -- (void)restart; | |
| 84 | -/** | |
| 85 | - * 发射弹幕 | |
| 86 | - * | |
| 87 | - * @param info 弹幕信息,字典集合 | |
| 88 | - */ | |
| 89 | -- (void)insertDanmu:(NSDictionary *)info; | |
| 90 | -/** | |
| 91 | - * 重置弹幕 | |
| 92 | - * | |
| 93 | - * @param frame 弹幕显示的frame | |
| 94 | - * @param infos 弹幕信息,数组集合 | |
| 95 | - * @param view 弹幕添加的UIView | |
| 96 | - * @param time 弹幕刷新的间隔时间,一般1秒 | |
| 97 | - */ | |
| 98 | -- (void)resetDanmuWithFrame:(CGRect)frame data:(NSArray *)infos inView:(UIView *)view durationTime:(NSUInteger)time; | |
| 99 | -/** | |
| 100 | - * 重置弹幕 | |
| 101 | - * | |
| 102 | - * @param frame 弹幕显示的frame | |
| 103 | - */ | |
| 104 | -- (void)resetDanmuWithFrame:(CGRect)frame; | |
| 105 | - | |
| 106 | - | |
| 107 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuManager.m deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuManager.m | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import "LVCDanmuManager.h" | |
| 10 | - | |
| 11 | -#import "LVCDanmuLabel.h" | |
| 12 | -#import "LVCDanmuView.h" | |
| 13 | - | |
| 14 | -#define CHANNEL_WIDTH_MAX 120 | |
| 15 | -#define CHANNEL_SPACE 10 | |
| 16 | - | |
| 17 | -struct DanmuPositionStruct { | |
| 18 | - NSInteger start; | |
| 19 | - NSInteger length; | |
| 20 | -}; | |
| 21 | -typedef struct DanmuPositionStruct DanmuPositionStruct; | |
| 22 | - | |
| 23 | -@interface LVCDanmuManager () | |
| 24 | - | |
| 25 | -@property (nonatomic, strong, readwrite) UIView *danmuView; | |
| 26 | -@property (nonatomic, readwrite) DanmuManagerState danmuManagerState; | |
| 27 | - | |
| 28 | -@property (nonatomic) CGRect frame; | |
| 29 | -@property (nonatomic, strong) NSArray *infos; | |
| 30 | -@property (nonatomic, weak) UIView *superView; | |
| 31 | -@property (nonatomic) NSUInteger durationTime;//添加弹幕的间隔时间 | |
| 32 | -@property (nonatomic) NSUInteger currentIndex; | |
| 33 | - | |
| 34 | -@property (nonatomic, strong) NSMutableArray *arRollChannelInfo; | |
| 35 | -@property (nonatomic) NSUInteger countChannel; | |
| 36 | - | |
| 37 | -@property (nonatomic) DanmuPositionStruct upPosition; | |
| 38 | -@property (nonatomic) DanmuPositionStruct middlePosition; | |
| 39 | -@property (nonatomic) DanmuPositionStruct downPosition; | |
| 40 | - | |
| 41 | -@end | |
| 42 | - | |
| 43 | -@implementation LVCDanmuManager | |
| 44 | - | |
| 45 | -- (void)dealloc { | |
| 46 | - _infos = nil; | |
| 47 | - _danmuView = nil; | |
| 48 | - _arRollChannelInfo = nil; | |
| 49 | -} | |
| 50 | - | |
| 51 | -- (instancetype)initWithFrame:(CGRect)frame data:(NSArray *)infos inView:(UIView *)view durationTime:(NSUInteger)time { | |
| 52 | - self = [super init]; | |
| 53 | - if (self) { | |
| 54 | - self.frame = frame; | |
| 55 | - self.infos = infos; | |
| 56 | - self.superView = view; | |
| 57 | - self.durationTime = time; | |
| 58 | - | |
| 59 | - [self p_initInfo]; | |
| 60 | - } | |
| 61 | - return self; | |
| 62 | -} | |
| 63 | - | |
| 64 | -#pragma mark - Private | |
| 65 | - | |
| 66 | -- (void)p_initInfo { | |
| 67 | - _countChannel = self.frame.size.height/CHANNEL_HEIGHT; | |
| 68 | - | |
| 69 | - self.arRollChannelInfo = [NSMutableArray arrayWithCapacity:_countChannel]; | |
| 70 | - | |
| 71 | - NSUInteger sectionLines = nearbyintf((CGFloat)_countChannel / 3); | |
| 72 | - NSUInteger firstLines = MAX(_countChannel - sectionLines*2, sectionLines); | |
| 73 | - //滚动航道布局 | |
| 74 | - //上中下,假设10,上:0-3,中:4-6,下:7-9 | |
| 75 | - _upPosition = (DanmuPositionStruct){0, firstLines}; | |
| 76 | - _middlePosition = (DanmuPositionStruct){_upPosition.length, sectionLines}; | |
| 77 | - _downPosition = (DanmuPositionStruct){_middlePosition.start + _middlePosition.length, _countChannel - _middlePosition.start - _middlePosition.length}; | |
| 78 | - | |
| 79 | - _danmuManagerState = DanmuManagerStateWait; | |
| 80 | -} | |
| 81 | - | |
| 82 | -- (void)p_initData { | |
| 83 | - [self.arRollChannelInfo removeAllObjects]; | |
| 84 | - | |
| 85 | - for (int i = 0; i < _countChannel; i++) { | |
| 86 | - [self.arRollChannelInfo addObject:[NSNumber numberWithInt:i]]; | |
| 87 | - } | |
| 88 | - | |
| 89 | - self.currentIndex = 0; | |
| 90 | - [self.danmuView removeFromSuperview]; | |
| 91 | - self.danmuView = nil; | |
| 92 | - self.danmuView = [[LVCDanmuView alloc] initWithFrame:_frame]; | |
| 93 | - [self.superView addSubview:self.danmuView]; | |
| 94 | - | |
| 95 | - _danmuManagerState = DanmuManagerStateWait; | |
| 96 | -} | |
| 97 | - | |
| 98 | -- (void)p_danmu:(NSTimeInterval)startTime { | |
| 99 | - __weak typeof(self) weakSelf = self; | |
| 100 | - | |
| 101 | - __block NSMutableArray *danmuInfos = [NSMutableArray new]; | |
| 102 | - __block NSUInteger index = 0; | |
| 103 | - | |
| 104 | - for (int i = (int)self.currentIndex; i < self.infos.count; i++) { | |
| 105 | - NSDictionary *obj = [self.infos objectAtIndex:i]; | |
| 106 | - CGFloat time = [[obj objectForKey:kDanmuTimeKey] floatValue]; | |
| 107 | - if (time >= startTime && time < startTime + weakSelf.durationTime) { | |
| 108 | - [danmuInfos addObject:obj]; | |
| 109 | - } | |
| 110 | - if (time >= startTime + weakSelf.durationTime) { | |
| 111 | - index = i; | |
| 112 | - break; | |
| 113 | - } | |
| 114 | - } | |
| 115 | - | |
| 116 | - if (danmuInfos.count > 0) { | |
| 117 | - self.currentIndex = index; | |
| 118 | - | |
| 119 | - void(^func)(LVCDanmuLabel *danmuLabel, NSUInteger idx, CGFloat offsetXY) = ^(LVCDanmuLabel *danmuLabel, NSUInteger idx, CGFloat offsetXY){ | |
| 120 | - if (idx != NSNotFound) { | |
| 121 | - [danmuLabel setDanmuChannel:idx offset:offsetXY]; | |
| 122 | - CGFloat time = [danmuLabel startTime]; | |
| 123 | - time = time - startTime; | |
| 124 | - [danmuLabel animationDanmuItem:time]; | |
| 125 | - } | |
| 126 | - }; | |
| 127 | - | |
| 128 | - [danmuInfos enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) { | |
| 129 | - __block LVCDanmuLabel *danmuLabel = [LVCDanmuLabel createWithInfo:obj inView:weakSelf.danmuView]; | |
| 130 | - [weakSelf p_getRollBestChannel:danmuLabel completion:^(NSUInteger idx, CGFloat offsetX) { | |
| 131 | - func(danmuLabel, idx, offsetX); | |
| 132 | - }]; | |
| 133 | - }]; | |
| 134 | - } | |
| 135 | -} | |
| 136 | - | |
| 137 | -- (void)p_getRollBestChannel:(LVCDanmuLabel *)newDanmuL completion:(void(^)(NSUInteger idx, CGFloat offsetX))completion { | |
| 138 | - DanmuPositionStruct danmuPosition; | |
| 139 | - if (newDanmuL.isPositionMiddle) { | |
| 140 | - danmuPosition = _middlePosition; | |
| 141 | - } | |
| 142 | - else if (newDanmuL.isPositionBottom) { | |
| 143 | - danmuPosition = _downPosition; | |
| 144 | - } | |
| 145 | - else { | |
| 146 | - danmuPosition = _upPosition; | |
| 147 | - } | |
| 148 | - | |
| 149 | - NSUInteger index = danmuPosition.start; | |
| 150 | - BOOL bFind = NO; | |
| 151 | - for (int i = (int)danmuPosition.start; i < danmuPosition.start + danmuPosition.length; i++) { | |
| 152 | - id obj = [self.arRollChannelInfo objectAtIndex:i]; | |
| 153 | - index = i; | |
| 154 | - if ([obj isKindOfClass:[LVCDanmuLabel class]]) { | |
| 155 | - bFind = [self p_last:obj new:newDanmuL]; | |
| 156 | - }else { | |
| 157 | - bFind = YES; | |
| 158 | - } | |
| 159 | - | |
| 160 | - if (bFind) | |
| 161 | - break; | |
| 162 | - } | |
| 163 | - | |
| 164 | - if (bFind) { | |
| 165 | - id obj = [self.arRollChannelInfo objectAtIndex:index]; | |
| 166 | - [self.arRollChannelInfo replaceObjectAtIndex:index withObject:newDanmuL]; | |
| 167 | - if ([obj isKindOfClass:[LVCDanmuLabel class]]) { | |
| 168 | - CGFloat x = ((LVCDanmuLabel *)obj).currentRightX; | |
| 169 | - completion(index, x < 0 ? 0 : x); | |
| 170 | - }else | |
| 171 | - completion(index, 0); | |
| 172 | - }else { | |
| 173 | - if (index < danmuPosition.start + danmuPosition.length - 1) { | |
| 174 | - index += 1; | |
| 175 | - [self.arRollChannelInfo replaceObjectAtIndex:index withObject:newDanmuL]; | |
| 176 | - completion(index, 0); | |
| 177 | - } | |
| 178 | - else { | |
| 179 | - NSUInteger index = NSNotFound; | |
| 180 | - index = [self p_allChannelWithPosition:danmuPosition new:newDanmuL]; | |
| 181 | - if (index != NSNotFound) { | |
| 182 | - LVCDanmuLabel *obj = [self.arRollChannelInfo objectAtIndex:index]; | |
| 183 | - [self.arRollChannelInfo replaceObjectAtIndex:index withObject:newDanmuL]; | |
| 184 | - CGFloat x = obj.currentRightX; | |
| 185 | - completion(index, x < CHANNEL_SPACE ? CHANNEL_SPACE : x); | |
| 186 | - }else | |
| 187 | - completion(NSNotFound, 0); | |
| 188 | - } | |
| 189 | - } | |
| 190 | -} | |
| 191 | - | |
| 192 | -//选择完全不会碰撞的航道 | |
| 193 | -- (BOOL)p_last:(LVCDanmuLabel *)lastDanmuL new:(LVCDanmuLabel *)newDanmuL { | |
| 194 | - CGFloat durationTime = newDanmuL.startTime - lastDanmuL.startTime; | |
| 195 | - if (durationTime > newDanmuL.animationDuartion) { | |
| 196 | - return YES; | |
| 197 | - } | |
| 198 | - CGFloat timeS = lastDanmuL.frame.size.width/lastDanmuL.speed; | |
| 199 | - if (timeS >= durationTime) { | |
| 200 | - return NO; | |
| 201 | - } | |
| 202 | - CGFloat timeE = newDanmuL.currentRightX/newDanmuL.speed; | |
| 203 | - if (timeE <= durationTime) { | |
| 204 | - return NO; | |
| 205 | - } | |
| 206 | - | |
| 207 | - return YES; | |
| 208 | -} | |
| 209 | - | |
| 210 | -//选择在不超出缓冲区的且缓冲区最长的航道 | |
| 211 | -- (NSUInteger)p_allChannelWithPosition:(DanmuPositionStruct)danmuPosition new:(LVCDanmuLabel *)newDanmuL { | |
| 212 | - CGFloat width = CHANNEL_WIDTH_MAX; | |
| 213 | - NSUInteger index = NSNotFound; | |
| 214 | - for (int i = (int)danmuPosition.start; i < danmuPosition.start + danmuPosition.length; i++) {id obj = [self.arRollChannelInfo objectAtIndex:i]; | |
| 215 | - if ([obj isKindOfClass:[LVCDanmuLabel class]]) { | |
| 216 | - CGFloat rightX = ((LVCDanmuLabel *)obj).currentRightX; | |
| 217 | - if (rightX <= CHANNEL_WIDTH_MAX) { | |
| 218 | - CGFloat xx = rightX; | |
| 219 | - if (xx < width) { | |
| 220 | - width = xx; | |
| 221 | - index = i; | |
| 222 | - } | |
| 223 | - } | |
| 224 | - } | |
| 225 | - } | |
| 226 | - | |
| 227 | - return index; | |
| 228 | -} | |
| 229 | - | |
| 230 | -- (NSUInteger)p_arDanmuLabel:(NSMutableArray *)arDanmuLs position:(DanmuPositionStruct)danmuPosition new:(LVCDanmuLabel *)newDanmuL { | |
| 231 | - BOOL bFind = NO; | |
| 232 | - NSUInteger index = danmuPosition.start; | |
| 233 | - for (int i = (int)danmuPosition.start; i < danmuPosition.start + danmuPosition.length; i++) { | |
| 234 | - id obj = [arDanmuLs objectAtIndex:i]; | |
| 235 | - index = i; | |
| 236 | - if ([obj isKindOfClass:[LVCDanmuLabel class]]) { | |
| 237 | - LVCDanmuLabel *lastDanmuL = obj; | |
| 238 | - CGFloat durationTime = newDanmuL.startTime - lastDanmuL.startTime; | |
| 239 | - bFind = (durationTime > (newDanmuL.animationDuartion - 1)); | |
| 240 | - }else { | |
| 241 | - bFind = YES; | |
| 242 | - } | |
| 243 | - | |
| 244 | - if (bFind) | |
| 245 | - break; | |
| 246 | - } | |
| 247 | - if (!bFind) { | |
| 248 | - if (index < danmuPosition.start + danmuPosition.length - 1) | |
| 249 | - index += 1; | |
| 250 | - else | |
| 251 | - index = NSNotFound; | |
| 252 | - } | |
| 253 | - | |
| 254 | - return index; | |
| 255 | -} | |
| 256 | - | |
| 257 | -#pragma mark - Action | |
| 258 | - | |
| 259 | -- (void)initStart { | |
| 260 | - if (_danmuManagerState == DanmuManagerStateWait || | |
| 261 | - _danmuManagerState == DanmuManagerStateStop) { | |
| 262 | - [self p_initData]; | |
| 263 | - } | |
| 264 | -} | |
| 265 | - | |
| 266 | -- (void)rollDanmu:(NSTimeInterval)startTime { | |
| 267 | - if (_danmuManagerState == DanmuManagerStateStop) | |
| 268 | - return; | |
| 269 | - if (_danmuManagerState != DanmuManagerStateAnimationing) | |
| 270 | - _danmuManagerState = DanmuManagerStateAnimationing; | |
| 271 | - | |
| 272 | - if ((NSInteger)startTime % _durationTime == 0) { | |
| 273 | - [self p_danmu:startTime]; | |
| 274 | - } | |
| 275 | -} | |
| 276 | - | |
| 277 | -- (void)stop { | |
| 278 | - _danmuManagerState = DanmuManagerStateStop; | |
| 279 | - [self.arRollChannelInfo removeAllObjects]; | |
| 280 | - [self.danmuView.subviews makeObjectsPerformSelector:@selector(removeDanmu)]; | |
| 281 | - [self.danmuView removeFromSuperview]; | |
| 282 | -} | |
| 283 | - | |
| 284 | -- (void)pause { | |
| 285 | - if (_danmuManagerState != DanmuManagerStateAnimationing) | |
| 286 | - return; | |
| 287 | - _danmuManagerState = DanmuManagerStatePause; | |
| 288 | - [self.danmuView.subviews makeObjectsPerformSelector:@selector(pause)]; | |
| 289 | -} | |
| 290 | - | |
| 291 | -- (void)resume:(NSTimeInterval)nowTime { | |
| 292 | - if (_danmuManagerState != DanmuManagerStatePause) | |
| 293 | - return; | |
| 294 | - _danmuManagerState = DanmuManagerStateAnimationing; | |
| 295 | - for (id subview in self.danmuView.subviews) { | |
| 296 | - if ([subview isKindOfClass:[LVCDanmuLabel class]]) { | |
| 297 | - [(LVCDanmuLabel *)subview resume:nowTime]; | |
| 298 | - } | |
| 299 | - } | |
| 300 | -} | |
| 301 | - | |
| 302 | -- (void)restart { | |
| 303 | - [self p_initData]; | |
| 304 | - _danmuManagerState = DanmuManagerStateAnimationing; | |
| 305 | -} | |
| 306 | - | |
| 307 | -- (void)insertDanmu:(NSDictionary *)info { | |
| 308 | - __block LVCDanmuLabel *danmuLabel = [LVCDanmuLabel createWithInfo:info inView:self.danmuView]; | |
| 309 | - [self p_getRollBestChannel:danmuLabel completion:^(NSUInteger idx, CGFloat offsetX) { | |
| 310 | - if (idx != NSNotFound) { | |
| 311 | - [danmuLabel setDanmuChannel:idx offset:offsetX]; | |
| 312 | - } | |
| 313 | - }]; | |
| 314 | -} | |
| 315 | - | |
| 316 | -- (void)resetDanmuWithFrame:(CGRect)frame data:(NSArray *)infos inView:(UIView *)view durationTime:(NSUInteger)time { | |
| 317 | - self.frame = frame; | |
| 318 | - if (infos != nil) | |
| 319 | - self.infos = infos; | |
| 320 | - self.superView = view; | |
| 321 | - self.durationTime = time; | |
| 322 | - | |
| 323 | - [self p_initInfo]; | |
| 324 | -} | |
| 325 | - | |
| 326 | -- (void)resetDanmuWithFrame:(CGRect)frame { | |
| 327 | - self.frame = frame; | |
| 328 | - [self p_initInfo]; | |
| 329 | -} | |
| 330 | - | |
| 331 | - | |
| 332 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuUtil.h deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuUtil.h | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import <Foundation/Foundation.h> | |
| 10 | -#import <UIKit/UIKit.h> | |
| 11 | - | |
| 12 | -typedef NS_ENUM(NSUInteger, DanmuState) { | |
| 13 | - DanmuStateStop = 1, | |
| 14 | - DanmuStateAnimationing, | |
| 15 | - DanmuStateFinish | |
| 16 | -}; | |
| 17 | - | |
| 18 | -#define CHANNEL_HEIGHT 25 | |
| 19 | - | |
| 20 | -extern NSString * const kDanmuContentKey; //弹幕内容 | |
| 21 | -extern NSString * const kDanmuTimeKey; //视频时间 | |
| 22 | -extern NSString * const kDanmuOptionalKey; //弹幕样式 | |
| 23 | - | |
| 24 | -@interface LVCDanmuUtil : NSObject | |
| 25 | - | |
| 26 | -+ (CGSize)getSizeWithString:(NSString *)str withFont:(UIFont *)font size:(CGSize)size; | |
| 27 | - | |
| 28 | -+ (UIColor *)colorFromARGB:(int)argb; | |
| 29 | - | |
| 30 | -+ (NSDictionary *)defaultOptions; | |
| 31 | - | |
| 32 | -+ (NSDictionary *)randomOptions; | |
| 33 | - | |
| 34 | -+ (BOOL)isOrientationLandscape; | |
| 35 | - | |
| 36 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuUtil.m deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuUtil.m | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import "LVCDanmuUtil.h" | |
| 10 | - | |
| 11 | -NSString * const kDanmuContentKey = @"c"; | |
| 12 | -NSString * const kDanmuTimeKey = @"v"; | |
| 13 | -NSString * const kDanmuOptionalKey = @"t"; | |
| 14 | - | |
| 15 | -@implementation LVCDanmuUtil | |
| 16 | - | |
| 17 | -+ (CGSize)getSizeWithString:(NSString *)str withFont:(UIFont *)font size:(CGSize)size { | |
| 18 | - CGRect stringRect = [str boundingRectWithSize:size | |
| 19 | - options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) | |
| 20 | - attributes:@{ NSFontAttributeName : font } | |
| 21 | - context:nil]; | |
| 22 | - | |
| 23 | - return stringRect.size; | |
| 24 | -} | |
| 25 | - | |
| 26 | -+ (UIColor *)colorFromARGB:(int)argb { | |
| 27 | - int blue = argb & 0xff; | |
| 28 | - int green = argb >> 8 & 0xff; | |
| 29 | - int red = argb >> 16 & 0xff; | |
| 30 | - //int alpha = argb >> 24 & 0xff; | |
| 31 | - //NSLog(@"%i, %i, %i", red, green, blue); | |
| 32 | - return [UIColor colorWithRed:red/255.f green:green/255.f blue:blue/255.f alpha: 1]; | |
| 33 | -} | |
| 34 | - | |
| 35 | -+ (long)argbFromHex:(NSString *)hex | |
| 36 | -{ | |
| 37 | - const char *cStr = [hex cStringUsingEncoding:NSASCIIStringEncoding]; | |
| 38 | - long x = strtol(cStr + 1, NULL, 16); | |
| 39 | - return x; | |
| 40 | - // return [self colorFromARGB: (int)x]; | |
| 41 | -} | |
| 42 | - | |
| 43 | -+ (NSDictionary *)defaultOptions { | |
| 44 | - return @{@"c": [NSNumber numberWithLong:[LVCDanmuUtil argbFromHex: @"#ffffff"]], | |
| 45 | - @"m": @"l", | |
| 46 | - @"p": @"t", | |
| 47 | - @"s": @"m", | |
| 48 | - @"l": @"n" | |
| 49 | - }; | |
| 50 | -} | |
| 51 | - | |
| 52 | -+ (NSDictionary *)randomOptions { | |
| 53 | - NSUInteger c = arc4random_uniform(4); | |
| 54 | - NSArray *arColor = @[@"#ffffff", @"#ff0000", @"#00ff00", @"#0000ff"]; | |
| 55 | - NSUInteger s = arc4random_uniform(3); | |
| 56 | - NSArray *arFontSize = @[@"l", @"m", @"s"]; | |
| 57 | - NSUInteger m = arc4random_uniform(4); | |
| 58 | - NSArray *arMode = @[@"l", @"f", @"l", @"l"]; | |
| 59 | - return @{@"c": [NSNumber numberWithLong:[LVCDanmuUtil argbFromHex:arColor[c]]], | |
| 60 | - @"m": arMode[m], | |
| 61 | - @"p": @"t", | |
| 62 | - @"s": arFontSize[s], | |
| 63 | - @"l": @"n" | |
| 64 | - }; | |
| 65 | -} | |
| 66 | - | |
| 67 | -+ (BOOL)isOrientationLandscape { | |
| 68 | - //if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) { | |
| 69 | - if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { | |
| 70 | - return YES; | |
| 71 | - } else { | |
| 72 | - return NO; | |
| 73 | - } | |
| 74 | -} | |
| 75 | - | |
| 76 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuView.h deleted
100644 → 0
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/Danmu/LVCDanmuView.m deleted
100644 → 0
| 1 | -// | |
| 2 | -// LVCDanmuView.m | |
| 3 | -// LiveVideoCloud | |
| 4 | -// | |
| 5 | -// Created by iOS on 17/3/28. | |
| 6 | -// Copyright © 2017年 cnlive. All rights reserved. | |
| 7 | -// | |
| 8 | - | |
| 9 | -#import "LVCDanmuView.h" | |
| 10 | - | |
| 11 | -@implementation LVCDanmuView | |
| 12 | - | |
| 13 | -- (instancetype)initWithFrame:(CGRect)frame { | |
| 14 | - self = [super initWithFrame:frame]; | |
| 15 | - if (self) { | |
| 16 | - self.backgroundColor = [UIColor clearColor]; | |
| 17 | - self.clipsToBounds = YES; | |
| 18 | - } | |
| 19 | - return self; | |
| 20 | -} | |
| 21 | - | |
| 22 | -/* | |
| 23 | -// Only override drawRect: if you perform custom drawing. | |
| 24 | -// An empty implementation adversely affects performance during animation. | |
| 25 | -- (void)drawRect:(CGRect)rect { | |
| 26 | - // Drawing code | |
| 27 | -} | |
| 28 | -*/ | |
| 29 | - | |
| 30 | -@end |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/LVCPlayer.h
| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | // |
| 8 | 8 | |
| 9 | 9 | #import <UIKit/UIKit.h> |
| 10 | +#import "LVCChannelDetailsModel.h" | |
| 10 | 11 | |
| 11 | 12 | @class LVCPlayer; |
| 12 | 13 | |
| ... | ... | @@ -14,9 +15,10 @@ |
| 14 | 15 | |
| 15 | 16 | @optional |
| 16 | 17 | |
| 17 | -- (void)lvcPlayer:(LVCPlayer *)player clickedBackBtn:(UIButton *)backBtn; //返回 | |
| 18 | -- (void)lvcPlayer:(LVCPlayer *)player clickedFullScreenBtn:(UIButton *)fullScreenBtn; //全屏 | |
| 19 | -- (void)lvcPlayer:(LVCPlayer *)player clickedEditBtn:(UIButton *)editBtn; //全屏编辑按钮 | |
| 18 | +- (void)lvcPlayer:(LVCPlayer *)player clickedBackBtn:(UIButton *)backBtn; //返回 | |
| 19 | +- (void)lvcPlayer:(LVCPlayer *)player clickedFullScreenBtn:(UIButton *)fullScreenBtn; //全屏 | |
| 20 | +- (void)lvcPlayer:(LVCPlayer *)player clickedEditBtn:(UIButton *)editBtn; //全屏编辑按钮 | |
| 21 | +- (void)lvcPlayer:(LVCPlayer *)player barrageSwitch:(BOOL)on; //弹幕开关 | |
| 20 | 22 | |
| 21 | 23 | @end |
| 22 | 24 | |
| ... | ... | @@ -26,11 +28,15 @@ typedef void(^HideInputViewBlock)(BOOL hide); |
| 26 | 28 | |
| 27 | 29 | @property (nonatomic, strong) UIImageView *topBgView; //顶部蒙版 |
| 28 | 30 | @property (nonatomic, strong) UIImageView *bottomBgView; //底部蒙版 |
| 31 | +@property (nonatomic, strong) UIImageView *contentView; //所有空间统一管理在这个view中 | |
| 32 | +@property (nonatomic, strong) LVCChannelDetailsModel *model; //所有空间统一管理在这个view中 | |
| 29 | 33 | @property (nonatomic, readwrite, assign) BOOL isFullScreen; //是否是全屏 |
| 30 | 34 | @property (nonatomic, copy) HideInputViewBlock hideBlock; //全屏模式下是否隐藏输入框 |
| 31 | - | |
| 35 | +@property (nonatomic, assign, readonly) BOOL displayBarrage; //是否显示弹幕 | |
| 32 | 36 | @property (nonatomic, assign) id<LVCPlayerDelegate> delegate; |
| 33 | 37 | |
| 38 | +- (instancetype)initWithFrame:(CGRect)frame playerModel:(LVCChannelDetailsModel *)model; | |
| 39 | + | |
| 34 | 40 | - (void)autoHideControlView; //自动隐藏上下功能条 |
| 35 | 41 | |
| 36 | 42 | - (void)stopPlaying; //停止播放 | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/LVCPlayer.m
| ... | ... | @@ -10,14 +10,9 @@ |
| 10 | 10 | #import "LVCPlayerLoadingView.h" |
| 11 | 11 | #import "SevenSwitch.h" |
| 12 | 12 | |
| 13 | -#define kAppId @"60_irn9edco29" | |
| 14 | -#define kAppKey @"69fe70bda67e059286ad509d9f5377f815955645b52f94" | |
| 15 | -#define kbundleId @"com.cnlive.zhangxu.LiveVideoCloud" | |
| 16 | - | |
| 17 | 13 | @interface LVCPlayer ()<UIGestureRecognizerDelegate> |
| 18 | 14 | |
| 19 | 15 | @property (nonatomic, strong) UIButton *backBtn; //返回 |
| 20 | -@property (nonatomic, strong) UIImageView *contentView; //所有空间统一管理在这个view中 | |
| 21 | 16 | @property (nonatomic, strong) UIButton *playOrPauseBtn; //播放/暂停 |
| 22 | 17 | @property (nonatomic, strong) UILabel *titleLab; //标题 |
| 23 | 18 | @property (nonatomic, strong) UIButton *fullScreenBtn; //控制全屏按钮 |
| ... | ... | @@ -32,12 +27,12 @@ |
| 32 | 27 | |
| 33 | 28 | @implementation LVCPlayer |
| 34 | 29 | |
| 35 | -- (instancetype)initWithFrame:(CGRect)frame | |
| 30 | +- (instancetype)initWithFrame:(CGRect)frame playerModel:(LVCChannelDetailsModel *)model | |
| 36 | 31 | { |
| 37 | 32 | self = [super initWithFrame:frame]; |
| 38 | 33 | if (self) { |
| 39 | 34 | |
| 40 | - [self initPlayer]; | |
| 35 | + [self initPlayerWithModel:model]; | |
| 41 | 36 | |
| 42 | 37 | [self addSubview:self.contentView]; |
| 43 | 38 | [self.contentView addSubview:self.bottomBgView]; |
| ... | ... | @@ -58,27 +53,44 @@ |
| 58 | 53 | } |
| 59 | 54 | #pragma mark - |
| 60 | 55 | #pragma mark - initPlayer |
| 61 | -- (void)initPlayer | |
| 62 | -{ | |
| 63 | - [[CNLiveWebcastManager manager] initWithAppId:kAppId appKey:kAppKey]; | |
| 64 | - //点播播放 | |
| 65 | - _player = [[CNLiveMoviePlayerController alloc] initVodPlayWithVId:@"aaa123" | |
| 66 | - authSuccess:^{ | |
| 67 | - | |
| 68 | - [self addObservers]; | |
| 69 | - _player.videoDecoderMode = CNLiveMovieVideoDecoderMode_AUTO; | |
| 70 | - _player.shouldAutoplay = YES; | |
| 71 | - [_player prepareToPlay]; | |
| 72 | - [self.contentView addSubview:_player.view]; | |
| 73 | - [self.contentView sendSubviewToBack:_player.view]; | |
| 74 | - | |
| 75 | - [self makePlayerConstraint]; | |
| 76 | - | |
| 77 | - | |
| 78 | - } authFailed:^(NSDictionary *errorInfo) { | |
| 79 | - NSLog(@"初始化点播播放器失败%@", errorInfo); | |
| 56 | +- (void)initPlayerWithModel:(LVCChannelDetailsModel *)model | |
| 57 | +{ | |
| 58 | + /* | |
| 59 | + */ | |
| 60 | + _player = [[CNLiveMoviePlayerController alloc] initLivePlayWithChannelId:model.mediaId authSuccess:^{ | |
| 61 | + [self addObservers]; | |
| 62 | + _player.videoDecoderMode = CNLiveMovieVideoDecoderMode_AUTO; | |
| 63 | + _player.shouldAutoplay = YES; | |
| 64 | + [_player prepareToPlay]; | |
| 65 | + [self.contentView addSubview:_player.view]; | |
| 66 | + [self.contentView sendSubviewToBack:_player.view]; | |
| 67 | + | |
| 68 | + [self makePlayerConstraint]; | |
| 80 | 69 | |
| 81 | - }]; | |
| 70 | + } authFailed:^(NSDictionary *errorInfo) { | |
| 71 | + NSLog(@"初始化点播播放器失败%@", errorInfo); | |
| 72 | + } getAnchorStatusResult:NULL]; | |
| 73 | + | |
| 74 | + /* | |
| 75 | + //点播播放 | |
| 76 | + _player = [[CNLiveMoviePlayerController alloc] initVodPlayWithVId:@"aaa123" | |
| 77 | + authSuccess:^{ | |
| 78 | + | |
| 79 | + [self addObservers]; | |
| 80 | + _player.videoDecoderMode = CNLiveMovieVideoDecoderMode_AUTO; | |
| 81 | + _player.shouldAutoplay = YES; | |
| 82 | + [_player prepareToPlay]; | |
| 83 | + [self.contentView addSubview:_player.view]; | |
| 84 | + [self.contentView sendSubviewToBack:_player.view]; | |
| 85 | + | |
| 86 | + [self makePlayerConstraint]; | |
| 87 | + | |
| 88 | + | |
| 89 | + } authFailed:^(NSDictionary *errorInfo) { | |
| 90 | + NSLog(@"初始化点播播放器失败%@", errorInfo); | |
| 91 | + | |
| 92 | + }]; | |
| 93 | + */ | |
| 82 | 94 | } |
| 83 | 95 | |
| 84 | 96 | #pragma mark - |
| ... | ... | @@ -112,9 +124,12 @@ |
| 112 | 124 | |
| 113 | 125 | - (void)barrageSwitchAction |
| 114 | 126 | { |
| 115 | - NSString *string = self.barrageSwitch.on ? @"已开启弹幕" : @"已关闭弹幕"; | |
| 127 | + self.editBtn.hidden =! self.barrageSwitch.on; | |
| 128 | + | |
| 129 | + if (self.delegate && [self.delegate respondsToSelector:@selector(lvcPlayer:barrageSwitch:)]) { | |
| 130 | + [self.delegate lvcPlayer:self barrageSwitch:_barrageSwitch.on]; | |
| 131 | + } | |
| 116 | 132 | |
| 117 | - NSLog(@"%@",string); | |
| 118 | 133 | } |
| 119 | 134 | |
| 120 | 135 | - (void)editBtnAction:(UIButton *)btn |
| ... | ... | @@ -483,6 +498,11 @@ |
| 483 | 498 | #pragma mark - |
| 484 | 499 | #pragma mark - getter |
| 485 | 500 | |
| 501 | +- (BOOL)displayBarrage | |
| 502 | +{ | |
| 503 | + return _barrageSwitch.on; | |
| 504 | +} | |
| 505 | + | |
| 486 | 506 | - (UIImageView *)contentView |
| 487 | 507 | { |
| 488 | 508 | if (!_contentView) { | ... | ... |
LiveVideoCloud/LiveVideoCloud/Classes/Sections/homeSections/View/LVCTelevisionView.m
| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | #import "LVCChannelDetailsModel.h" |
| 14 | 14 | #import "LVCChannelsModel.h" |
| 15 | 15 | #import "LVCBannerModel.h" |
| 16 | +#import "LVCLivePlayerController.h" | |
| 16 | 17 | |
| 17 | 18 | static NSString *cellId = @"LVCLiveListCollectionViewCell"; |
| 18 | 19 | static NSString *firstHeaderId = @"LVCFirstHeaderReusableView"; |
| ... | ... | @@ -186,8 +187,15 @@ static NSString *otherHeaderId = @"LVCOtherHeaderReusableView"; |
| 186 | 187 | #pragma mark - |
| 187 | 188 | #pragma mark - UICollectionViewDelegate |
| 188 | 189 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { |
| 189 | - NSLog(@"跳转-----"); | |
| 190 | 190 | |
| 191 | + LVCChannelsModel *model = _channelsModelArray[indexPath.section - 1]; | |
| 192 | + LVCChannelDetailsModel *details = model.programs[indexPath.item]; | |
| 193 | + self.viewController.hidesBottomBarWhenPushed = YES; | |
| 194 | + | |
| 195 | + LVCLivePlayerController *playVC = [[LVCLivePlayerController alloc] init]; | |
| 196 | + playVC.model = details; | |
| 197 | + self.viewController.navigationController.navigationBar.hidden = YES; | |
| 198 | + [self.viewController.navigationController pushViewController:playVC animated:YES]; | |
| 191 | 199 | } |
| 192 | 200 | |
| 193 | 201 | #pragma mark - |
| ... | ... | @@ -213,8 +221,7 @@ static NSString *otherHeaderId = @"LVCOtherHeaderReusableView"; |
| 213 | 221 | |
| 214 | 222 | NSMutableArray *arrayM = [[NSMutableArray alloc]init]; |
| 215 | 223 | for (NSDictionary *dict in responseObject[@"channels"]) { |
| 216 | - LVCChannelsModel *model = [LVCChannelsModel new]; | |
| 217 | - [model setValuesForKeysWithDictionary:dict]; | |
| 224 | + LVCChannelsModel *model = [LVCChannelsModel mj_objectWithKeyValues:dict]; | |
| 218 | 225 | [arrayM addObject:model]; |
| 219 | 226 | } |
| 220 | 227 | self.channelsModelArray = arrayM; |
| ... | ... | @@ -223,8 +230,7 @@ static NSString *otherHeaderId = @"LVCOtherHeaderReusableView"; |
| 223 | 230 | |
| 224 | 231 | NSMutableArray *arrayM = [NSMutableArray array]; |
| 225 | 232 | for (NSDictionary *dict in responseObject[@"banner"]) { |
| 226 | - LVCBannerModel *rollModel = [LVCBannerModel new]; | |
| 227 | - [rollModel setValuesForKeysWithDictionary:dict]; | |
| 233 | + LVCBannerModel *rollModel = [LVCBannerModel mj_objectWithKeyValues:dict]; | |
| 228 | 234 | [arrayM addObject:rollModel]; |
| 229 | 235 | } |
| 230 | 236 | self.bannerModelArray = arrayM; | ... | ... |
LiveVideoCloud/LiveVideoCloud/Info.plist
| ... | ... | @@ -2,19 +2,8 @@ |
| 2 | 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 3 | 3 | <plist version="1.0"> |
| 4 | 4 | <dict> |
| 5 | - <key>UIViewControllerBasedStatusBarAppearance</key> | |
| 6 | - <false/> | |
| 7 | 5 | <key>CFBundleDevelopmentRegion</key> |
| 8 | 6 | <string>en</string> |
| 9 | - <key>NSAppTransportSecurity</key> | |
| 10 | - <dict> | |
| 11 | - <key>NSAllowsArbitraryLoads</key> | |
| 12 | - <true/> | |
| 13 | - </dict> | |
| 14 | - <key>NSCameraUsageDescription</key> | |
| 15 | - <string></string> | |
| 16 | - <key>NSMicrophoneUsageDescription</key> | |
| 17 | - <string></string> | |
| 18 | 7 | <key>CFBundleExecutable</key> |
| 19 | 8 | <string>$(EXECUTABLE_NAME)</string> |
| 20 | 9 | <key>CFBundleIdentifier</key> |
| ... | ... | @@ -59,5 +48,7 @@ |
| 59 | 48 | <string>UIInterfaceOrientationLandscapeLeft</string> |
| 60 | 49 | <string>UIInterfaceOrientationLandscapeRight</string> |
| 61 | 50 | </array> |
| 51 | + <key>UIViewControllerBasedStatusBarAppearance</key> | |
| 52 | + <false/> | |
| 62 | 53 | </dict> |
| 63 | 54 | </plist> | ... | ... |
LiveVideoCloud/LiveVideoCloud/UtilKits/Macro/Macros/AppMacro.h
| ... | ... | @@ -13,15 +13,8 @@ |
| 13 | 13 | #ifndef AppMacro_h |
| 14 | 14 | #define AppMacro_h |
| 15 | 15 | |
| 16 | -#ifdef DEBUG | |
| 17 | -#define AppId @"3_ix6yg1gl62" | |
| 18 | -#define AppKey @"d8dd4312037a6aaff83dc4809c027fc9b06847a3f130e5" | |
| 19 | -#define AppSceret @"78417aa2f74718de7958a0c9632f630904895029755b3e" | |
| 20 | -#else | |
| 21 | -#define AppId @"3_iw67pjcd56" | |
| 22 | -#define AppKey @"0d88fbc8da13dfd434540a89da71cd96dd78d42d4d62c9" | |
| 23 | -#define AppSceret @"c70a9bb56f2f654b60db64b2a5fa7e92ebd4954b237435" | |
| 24 | -#endif | |
| 25 | - | |
| 16 | +#define AppId @"60_j0uqrv0u11" | |
| 17 | +#define AppKey @"876c5efece0fc9c98c51ff2180ee1bcfa5c5b5af202c78" | |
| 18 | +#define AppSceret @"ee844ea67b6be7303b6f5d9365af10ac09933c0828aba7" | |
| 26 | 19 | |
| 27 | 20 | #endif /* AppMacro_h */ | ... | ... |