diff --git a/GIGA.xcodeproj/project.pbxproj b/GIGA.xcodeproj/project.pbxproj index d464558..f445430 100644 --- a/GIGA.xcodeproj/project.pbxproj +++ b/GIGA.xcodeproj/project.pbxproj @@ -79,6 +79,13 @@ 838388D3212FB7D700D14C53 /* JXTAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = 838388CE212FB7D700D14C53 /* JXTAlertController.m */; }; 838388D4212FB7D700D14C53 /* JXTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 838388D2212FB7D700D14C53 /* JXTAlertView.m */; }; 838388DA2130046D00D14C53 /* emojizone.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 838388D92130046D00D14C53 /* emojizone.mp4 */; }; + 83928FFA2134D8F60077D2E8 /* GiGaFlyingCommitInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83928FF92134D8F60077D2E8 /* GiGaFlyingCommitInputView.m */; }; + 83928FFE2134F37D0077D2E8 /* GiGaSocketRocketUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 83928FFD2134F37D0077D2E8 /* GiGaSocketRocketUtility.m */; }; + 839290052134F4240077D2E8 /* LXDanMuTrackView.m in Sources */ = {isa = PBXBuildFile; fileRef = 839290002134F4230077D2E8 /* LXDanMuTrackView.m */; }; + 839290062134F4240077D2E8 /* LXDanMuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 839290012134F4230077D2E8 /* LXDanMuManager.m */; }; + 839290092134F4C40077D2E8 /* GiGaFlingCommitVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 839290082134F4C40077D2E8 /* GiGaFlingCommitVC.m */; }; + 8392900C2134F9F80077D2E8 /* GiGaCommentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8392900A2134F9F80077D2E8 /* GiGaCommentView.m */; }; + 8392900F2134FA0A0077D2E8 /* GiGaCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8392900E2134FA0A0077D2E8 /* GiGaCommentModel.m */; }; 83A2270C212A97ED00B3E75C /* MaskViewBootomWaringView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A2270B212A97ED00B3E75C /* MaskViewBootomWaringView.m */; }; 83A22712212A9EA900B3E75C /* UIView+Sizes.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A22710212A9EA900B3E75C /* UIView+Sizes.m */; }; 83A22718212ABDFF00B3E75C /* GiGaBlockButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A22717212ABDFF00B3E75C /* GiGaBlockButton.m */; }; @@ -231,6 +238,21 @@ 838388D1212FB7D700D14C53 /* JXTAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JXTAlertView.h; sourceTree = ""; }; 838388D2212FB7D700D14C53 /* JXTAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JXTAlertView.m; sourceTree = ""; }; 838388D92130046D00D14C53 /* emojizone.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = emojizone.mp4; sourceTree = ""; }; + 83928FF82134D8F60077D2E8 /* GiGaFlyingCommitInputView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiGaFlyingCommitInputView.h; sourceTree = ""; }; + 83928FF92134D8F60077D2E8 /* GiGaFlyingCommitInputView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GiGaFlyingCommitInputView.m; sourceTree = ""; }; + 83928FFC2134F37D0077D2E8 /* GiGaSocketRocketUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiGaSocketRocketUtility.h; sourceTree = ""; }; + 83928FFD2134F37D0077D2E8 /* GiGaSocketRocketUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiGaSocketRocketUtility.m; sourceTree = ""; }; + 839290002134F4230077D2E8 /* LXDanMuTrackView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LXDanMuTrackView.m; sourceTree = ""; }; + 839290012134F4230077D2E8 /* LXDanMuManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LXDanMuManager.m; sourceTree = ""; }; + 839290022134F4230077D2E8 /* LXDanMuManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LXDanMuManager.h; sourceTree = ""; }; + 839290032134F4230077D2E8 /* LXDanMuManagerConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LXDanMuManagerConfig.h; sourceTree = ""; }; + 839290042134F4230077D2E8 /* LXDanMuTrackView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LXDanMuTrackView.h; sourceTree = ""; }; + 839290072134F4C40077D2E8 /* GiGaFlingCommitVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiGaFlingCommitVC.h; sourceTree = ""; }; + 839290082134F4C40077D2E8 /* GiGaFlingCommitVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GiGaFlingCommitVC.m; sourceTree = ""; }; + 8392900A2134F9F80077D2E8 /* GiGaCommentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiGaCommentView.m; sourceTree = ""; }; + 8392900B2134F9F80077D2E8 /* GiGaCommentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiGaCommentView.h; sourceTree = ""; }; + 8392900D2134FA0A0077D2E8 /* GiGaCommentModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GiGaCommentModel.h; sourceTree = ""; }; + 8392900E2134FA0A0077D2E8 /* GiGaCommentModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GiGaCommentModel.m; sourceTree = ""; }; 83A2270A212A97ED00B3E75C /* MaskViewBootomWaringView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MaskViewBootomWaringView.h; sourceTree = ""; }; 83A2270B212A97ED00B3E75C /* MaskViewBootomWaringView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MaskViewBootomWaringView.m; sourceTree = ""; }; 83A22710212A9EA900B3E75C /* UIView+Sizes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Sizes.m"; sourceTree = ""; }; @@ -353,6 +375,8 @@ 83346AD3212BFF6E0054D597 /* UserGuardViewController.m */, 83346AD5212C18F50054D597 /* GiGaAppGaurdVC.h */, 83346AD6212C18F50054D597 /* GiGaAppGaurdVC.m */, + 839290072134F4C40077D2E8 /* GiGaFlingCommitVC.h */, + 839290082134F4C40077D2E8 /* GiGaFlingCommitVC.m */, ); path = Controller; sourceTree = ""; @@ -360,6 +384,8 @@ 8354B3822121BAFA004F448F /* Model */ = { isa = PBXGroup; children = ( + 8392900D2134FA0A0077D2E8 /* GiGaCommentModel.h */, + 8392900E2134FA0A0077D2E8 /* GiGaCommentModel.m */, ); path = Model; sourceTree = ""; @@ -367,8 +393,12 @@ 8354B3832121BB00004F448F /* View */ = { isa = PBXGroup; children = ( + 8392900B2134F9F80077D2E8 /* GiGaCommentView.h */, + 8392900A2134F9F80077D2E8 /* GiGaCommentView.m */, 83A2270A212A97ED00B3E75C /* MaskViewBootomWaringView.h */, 83A2270B212A97ED00B3E75C /* MaskViewBootomWaringView.m */, + 83928FF82134D8F60077D2E8 /* GiGaFlyingCommitInputView.h */, + 83928FF92134D8F60077D2E8 /* GiGaFlyingCommitInputView.m */, ); path = View; sourceTree = ""; @@ -468,6 +498,8 @@ 8361B3FC21215C7400238FEB /* Common */ = { isa = PBXGroup; children = ( + 83928FFF2134F4230077D2E8 /* LXDanMuManager */, + 83928FFB2134F37D0077D2E8 /* SocketRocketUtility */, 838388CB212FB7D700D14C53 /* JXTAlertManager */, 838388C5212F9C0A00D14C53 /* GiGaLocalNotificationManager */, 83835BC4212E7B96001480F2 /* GiGaNavTitileView */, @@ -742,6 +774,27 @@ path = AlertView; sourceTree = ""; }; + 83928FFB2134F37D0077D2E8 /* SocketRocketUtility */ = { + isa = PBXGroup; + children = ( + 83928FFC2134F37D0077D2E8 /* GiGaSocketRocketUtility.h */, + 83928FFD2134F37D0077D2E8 /* GiGaSocketRocketUtility.m */, + ); + path = SocketRocketUtility; + sourceTree = ""; + }; + 83928FFF2134F4230077D2E8 /* LXDanMuManager */ = { + isa = PBXGroup; + children = ( + 839290002134F4230077D2E8 /* LXDanMuTrackView.m */, + 839290012134F4230077D2E8 /* LXDanMuManager.m */, + 839290022134F4230077D2E8 /* LXDanMuManager.h */, + 839290032134F4230077D2E8 /* LXDanMuManagerConfig.h */, + 839290042134F4230077D2E8 /* LXDanMuTrackView.h */, + ); + path = LXDanMuManager; + sourceTree = ""; + }; 83A22719212AC7FC00B3E75C /* View */ = { isa = PBXGroup; children = ( @@ -1049,10 +1102,12 @@ 8357ADD82124027D000816F2 /* GiGaUserDefault.m in Sources */, 83835BB6212E5174001480F2 /* GiGaServiceViewController.m in Sources */, 8361B40721215E6F00238FEB /* GiGaHelper.m in Sources */, + 8392900F2134FA0A0077D2E8 /* GiGaCommentModel.m in Sources */, 83835BA0212E43BD001480F2 /* GiGaMasssagesVC.m in Sources */, 8357ADCD2123C091000816F2 /* GiGaNetManager.m in Sources */, 838388D4212FB7D700D14C53 /* JXTAlertView.m in Sources */, 835060A9212D38EE007E6220 /* GiGaStartAdView.m in Sources */, + 83928FFA2134D8F60077D2E8 /* GiGaFlyingCommitInputView.m in Sources */, 838388D3212FB7D700D14C53 /* JXTAlertController.m in Sources */, 833DA7762122A62000A5C614 /* GiGaMaskTaskViewController.m in Sources */, 8357ADD02123C5F7000816F2 /* GiGaAPIRequest.m in Sources */, @@ -1073,13 +1128,18 @@ 83835BB9212E51B0001480F2 /* GiGaSystemViewController.m in Sources */, 8361B40421215E0C00238FEB /* LXCountTimer.m in Sources */, 8357ADC52123BEBD000816F2 /* GiGaUser.m in Sources */, + 8392900C2134F9F80077D2E8 /* GiGaCommentView.m in Sources */, + 839290062134F4240077D2E8 /* LXDanMuManager.m in Sources */, + 839290052134F4240077D2E8 /* LXDanMuTrackView.m in Sources */, 83E40B2F21218BA0008149C4 /* GiGaUserViewController.m in Sources */, 835060A5212D3536007E6220 /* AppDelegate+GiGaConfig.m in Sources */, 83E40B2B21218B6F008149C4 /* GiGaExercisesViewController.m in Sources */, 83835BA7212E4748001480F2 /* MAssaageCenterCell.m in Sources */, 8361B42E2121812000238FEB /* GiGaServerConfig.m in Sources */, 83A22712212A9EA900B3E75C /* UIView+Sizes.m in Sources */, + 839290092134F4C40077D2E8 /* GiGaFlingCommitVC.m in Sources */, 83A22718212ABDFF00B3E75C /* GiGaBlockButton.m in Sources */, + 83928FFE2134F37D0077D2E8 /* GiGaSocketRocketUtility.m in Sources */, 83A2270C212A97ED00B3E75C /* MaskViewBootomWaringView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/GIGA/Common/GiGaHelper.h b/GIGA/Common/GiGaHelper.h index 7df77f2..7f234f5 100644 --- a/GIGA/Common/GiGaHelper.h +++ b/GIGA/Common/GiGaHelper.h @@ -48,5 +48,10 @@ +(CGFloat)getSpaceLabelHeight:(NSString*)str withFont:(UIFont*)font maxSize:(CGSize)maxSize; +(void)setLabelSpace:(UILabel*)label withValue:(NSString*)str withFont:(UIFont*)font; +/** + 是否是手机号 + */ ++(BOOL)isPhoneNumber:(NSString*)mobileNumber; + @end diff --git a/GIGA/Common/GiGaHelper.m b/GIGA/Common/GiGaHelper.m index 4d56ac1..86d310b 100644 --- a/GIGA/Common/GiGaHelper.m +++ b/GIGA/Common/GiGaHelper.m @@ -144,4 +144,34 @@ label.attributedText = attributeStr; } + ++(BOOL)isPhoneNumber:(NSString*)mobileNumber{ + + if (mobileNumber.length != 11) + { + return NO; + } + /** * 手机号码: * 13[0-9], 14[5,7], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[6, 7, 8], 18[0-9], 170[0-9] * 移动号段: 134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705 * 联通号段: 130,131,132,155,156,185,186,145,176,1709 * 电信号段: 133,153,180,181,189,177,1700 */ + NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|7[0678])\\d{8}$"; + /** * 中国移动:China Mobile * 134,135,136,137,138,139,150,151,152,157,158,159,182,183,184,187,188,147,178,1705 */ + NSString *CM = @"(^1(3[4-9]|4[7]|5[0-27-9]|7[8]|8[2-478])\\d{8}$)|(^1705\\d{7}$)"; + /** * 中国联通:China Unicom * 130,131,132,155,156,185,186,145,176,1709 */ + NSString *CU = @"(^1(3[0-2]|4[5]|5[56]|7[6]|8[56])\\d{8}$)|(^1709\\d{7}$)"; /** * 中国电信:China Telecom * 133,153,180,181,189,177,1700 */ + NSString *CT = @"(^1(33|53|77|8[019])\\d{8}$)|(^1700\\d{7}$)"; + /** 25 * 大陆地区固话及小灵通 26 * 区号:010,020,021,022,023,024,025,027,028,029 27 * 号码:七位或八位 28 */ // + // NSString * PHS = @"^(0[0-9]{2})\\d{8}$|^(0[0-9]{3}(\\d{7,8}))$"; + NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; + NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM]; + NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU]; + NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT]; + if (([regextestmobile evaluateWithObject:mobileNumber] == YES) || ([regextestcm evaluateWithObject:mobileNumber] == YES) || ([regextestct evaluateWithObject:mobileNumber] == YES) || ([regextestcu evaluateWithObject:mobileNumber] == YES)) { + return YES; + + } else { + return NO; + + } + +} + @end diff --git a/GIGA/Common/GiGaLocalNotificationManager/GiGaLocalNotificationManager.m b/GIGA/Common/GiGaLocalNotificationManager/GiGaLocalNotificationManager.m index 54d5b44..2859fc7 100644 --- a/GIGA/Common/GiGaLocalNotificationManager/GiGaLocalNotificationManager.m +++ b/GIGA/Common/GiGaLocalNotificationManager/GiGaLocalNotificationManager.m @@ -44,11 +44,10 @@ content.attachments = @[attachAudio]; //延迟通知 第一个参数是重复的时间间隔,最小60s,第二个参数是是否重复。 - UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:60 repeats:NO]; + UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:timeInterval repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) { GILog(@"成功添加推送"); - }]; } else { diff --git a/GIGA/Common/LXDanMuManager/LXDanMuManager.h b/GIGA/Common/LXDanMuManager/LXDanMuManager.h new file mode 100644 index 0000000..058c0a8 --- /dev/null +++ b/GIGA/Common/LXDanMuManager/LXDanMuManager.h @@ -0,0 +1,34 @@ +// +// LXDanMuManager.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import +#import +@interface LXDanMuManager : NSObject +@property (nonatomic,strong) NSArray *trackSpeedArray; +@property (nonatomic,assign) float centerY;//所有轨道中心点 +@property (nonatomic,assign) float trackWidth; +@property (nonatomic,strong) NSTimer *timer; +@property (nonatomic,strong) UIView *superView; +@property (nonatomic,strong) NSMutableArray *trackArray; +@property (nonatomic,strong) UIView *baseView; + ++(LXDanMuManager *)shareInstance; +-(void)createDanmuWithTrackSpeedArray:(NSArray *)trackSpeedArray centerY:(float)centerY trackWidth:(float)trackWidth showInView:(UIView *)inView; +/** + 插入一条弹幕,可以插入任意继承UIView的对象 + + @param customView 自定义的view(注意,最高不能超过轨道的高,否则会出问题) + @param trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入) + */ +-(void)appendDanMuWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex; +-(void)start; +-(void)pause; +-(void)stop; +-(void)destory; + +@end diff --git a/GIGA/Common/LXDanMuManager/LXDanMuManager.m b/GIGA/Common/LXDanMuManager/LXDanMuManager.m new file mode 100644 index 0000000..33dd03c --- /dev/null +++ b/GIGA/Common/LXDanMuManager/LXDanMuManager.m @@ -0,0 +1,145 @@ +// +// LXDanMuManager.m +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "LXDanMuManager.h" +#import "LXDanMuTrackView.h" + +@implementation LXDanMuManager + ++ (LXDanMuManager *)shareInstance{ + static LXDanMuManager *managerInstance = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + managerInstance = [[self alloc] init]; + }); + return managerInstance; +} + +- (void)createDanmuWithTrackSpeedArray:(NSArray *)trackSpeedArray centerY:(float)centerY trackWidth:(float)trackWidth showInView:(UIView *)inView{ + _superView = inView; + _trackSpeedArray = trackSpeedArray; + _centerY = centerY; + _trackWidth = trackWidth; + _trackArray = [[NSMutableArray alloc] init]; + [self initUI]; +} + +-(void)initUI{ + _baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,_trackWidth, 0)]; + _baseView.userInteractionEnabled = NO; + [_superView addSubview:_baseView]; + + for (int i = 0; i<_trackSpeedArray.count; i++) { + + LXDanMuTrackView *trackView = [[LXDanMuTrackView alloc] initWithFrame:CGRectMake(0, (TRACK_HEIGHT + TRACK_VERTICAL_PADDING) * i, _baseView.frame.size.width, TRACK_HEIGHT)]; + [_baseView addSubview:trackView]; + [_trackArray addObject:trackView]; + if (_trackSpeedArray.count - 1 == i) { + _baseView.frame = CGRectMake(_baseView.frame.origin.x, _baseView.frame.origin.y, _baseView.frame.size.width,CGRectGetMaxY(trackView.frame)); + _baseView.center = CGPointMake(_baseView.center.x, _centerY); + } + } +} + +-(void)start{ + + if (_timer) { + return; + } + _timer = [NSTimer timerWithTimeInterval:0.01 target:self selector:@selector(startAction) userInfo:nil repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; + +} + +- (void)pause{ + [_timer invalidate]; + _timer = nil; +} + +- (void)stop{ + + [_timer invalidate]; + _timer = nil; + for (LXDanMuTrackView *trackView in _trackArray) { + [trackView cleanTrack]; + } +} + +- (void)destory{ + + [_timer invalidate]; + _timer = nil; + for (LXDanMuTrackView * trackView in _trackArray) { + [trackView cleanTrack]; + [trackView removeFromSuperview]; + } + [_trackArray removeAllObjects]; + [_baseView removeFromSuperview]; + _trackSpeedArray = nil; + _superView = nil; + _baseView = nil; + _trackArray = nil; + +} + +-(void)startAction{ + + for (int i = 0; i < _trackArray.count; i++) { + //执行轨道定时器方法 + LXDanMuTrackView *trackView = _trackArray[i]; + [trackView moveViewWithSpeed:[_trackSpeedArray[i] floatValue]]; + + } +} + +-(UIView *)baseView{ + if (!_baseView) { + _baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,_trackWidth, 0)]; + + } + return _baseView; +} + +//自定义的view(注意,最高不能超过轨道的高,会出问题) +- (void)appendDanMuWithCustomView:(UIView *)customView toTrackIndex:(NSInteger)trackIndex +{ + //trackIndex 插入弹幕的轨道(为-1则代表自动寻找最不拥挤的轨道插入) + NSInteger realTrackIndex = trackIndex; + if (realTrackIndex == -1) { + realTrackIndex = [self findTheMinTotalWidthTrack]; + } + LXDanMuTrackView *trackView = _trackArray[realTrackIndex]; + [trackView appendWithCustomView:customView]; + +} + +/** + 找到最短右侧出屏幕和等待数组总长度最短的轨道序号 + + @return 轨道的序号 + */ + +- (int)findTheMinTotalWidthTrack +{ + LXDanMuTrackView *firstTrackView = _trackArray[0]; + int minWidthIndex = 0; + float minWidth = [firstTrackView rightOutScreenWidth]; + for (int i = 0; i<_trackArray.count; i++) + { + LXDanMuTrackView *trackView = _trackArray[i]; + float trackRightOutScreenWidth = [trackView rightOutScreenWidth]; + if (trackRightOutScreenWidth < minWidth) + { + minWidth = trackRightOutScreenWidth; + minWidthIndex = i; + } + } + return minWidthIndex; +} + +@end diff --git a/GIGA/Common/LXDanMuManager/LXDanMuManagerConfig.h b/GIGA/Common/LXDanMuManager/LXDanMuManagerConfig.h new file mode 100644 index 0000000..353516a --- /dev/null +++ b/GIGA/Common/LXDanMuManager/LXDanMuManagerConfig.h @@ -0,0 +1,19 @@ +// +// LXDanMuManagerConfig.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#ifndef LXDanMuManagerConfig_h +#define LXDanMuManagerConfig_h + +//轨道中弹幕的最小间距 +#define TRACK_HORIZONTAL_PADDING 10 +//轨道与轨道的纵向间距 +#define TRACK_VERTICAL_PADDING 10 +//轨道的高度(轨道上的View不能超过此高度) +#define TRACK_HEIGHT 60 + +#endif /* LXDanMuManagerConfig_h */ diff --git a/GIGA/Common/LXDanMuManager/LXDanMuTrackView.h b/GIGA/Common/LXDanMuManager/LXDanMuTrackView.h new file mode 100644 index 0000000..3dadf0c --- /dev/null +++ b/GIGA/Common/LXDanMuManager/LXDanMuTrackView.h @@ -0,0 +1,47 @@ +// +// LXDanMuTrackView.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import +#import "LXDanMuManagerConfig.h" + +@interface LXDanMuTrackView : UIView + +/** + 等待出现到屏幕中的弹幕view数组 + */ +@property (nonatomic,strong) NSMutableArray *waitShowArray; + +/** + 正在展示的弹幕view数组 + */ +@property (nonatomic,strong) NSMutableArray *showingArray; +/** + 向轨道中插入一条自定义的view + + @param view 自定义的view,高度不可超过轨道的高,否则出问题 + */ +- (void)appendWithCustomView:(UIView *)view; + +/** + 当前轨道右侧出屏幕的距离+等待出现到屏幕中的弹幕view的总长度和 + @return 等待弹幕+右侧出屏幕弹幕的和 + */ +- (float)rightOutScreenWidth; +/** + 清理轨道,移除所有弹幕 + */ +- (void)cleanTrack; +/** + 根据速度移动轨道中所有弹幕的位置 + + @param speed 每0.01秒弹幕向左移动的距离 + */ +- (void)moveViewWithSpeed:(float)speed; + + +@end diff --git a/GIGA/Common/LXDanMuManager/LXDanMuTrackView.m b/GIGA/Common/LXDanMuManager/LXDanMuTrackView.m new file mode 100644 index 0000000..2054b51 --- /dev/null +++ b/GIGA/Common/LXDanMuManager/LXDanMuTrackView.m @@ -0,0 +1,123 @@ +// +// LXDanMuTrackView.m +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "LXDanMuTrackView.h" + +@implementation LXDanMuTrackView + +- (instancetype)initWithFrame:(CGRect)frame{ + + self = [super initWithFrame:frame]; + if (self) { + [self dataConfig]; + } + return self; +} + +-(void)dataConfig{ + + _showingArray = [[NSMutableArray alloc] init]; + _waitShowArray = [[NSMutableArray alloc] init]; + +} + +- (void)appendWithCustomView:(UIView *)view{ + + view.frame = CGRectMake(self.frame.size.width,view.frame.origin.y, view.frame.size.width,view.frame.size.height); + view.center = CGPointMake(view.center.x, TRACK_HEIGHT/2); + if (_showingArray.count) { + UIView *lastView = [_showingArray lastObject]; + //最右侧的那条弹幕还没有完全出现在屏幕中 + if (CGRectGetMaxX(lastView.frame) + TRACK_HORIZONTAL_PADDING > self.frame.size.width || _waitShowArray.count) { + //把这条弹幕加到等待数组中 + [_waitShowArray addObject:view]; + }else{ + //加入轨道 + [self addSubview:view]; + //加入展示数组 + [_showingArray addObject:view]; + + } + }else{ + + [self addSubview:view]; + [_showingArray addObject:view]; + } +} + +- (void)moveViewWithSpeed:(float)speed{ + //正在展示的弹幕自减一次 + for (UIView *view in _showingArray) { + view.frame = CGRectMake(view.frame.origin.x - speed, view.frame.origin.y, view.frame.size.width, view.frame.size.height); + + } + //正在展示的弹幕 + if (_showingArray.count){ + UIView *firstView = [_showingArray firstObject]; + UIView *lastView = [_showingArray lastObject]; + + if (CGRectGetMaxX(firstView.frame) < 0) { + //已移除屏幕 remove + [firstView removeFromSuperview]; + [_showingArray removeObjectAtIndex:0]; + + } + if (_waitShowArray.count) { + //最右侧的view 已经完全出现 + if (CGRectGetMaxX(lastView.frame) + TRACK_HORIZONTAL_PADDING <= self.frame.size.width) { + //转移数组 + [_showingArray addObject:[_waitShowArray firstObject]]; + [_waitShowArray removeObjectAtIndex:0]; + [self addSubview:[_showingArray lastObject]]; + + } + } + } +} +- (float)rightOutScreenWidth +{ + float outScreenWidth = 0.0; + //如果等待数组中有值 + if (_waitShowArray.count) + { + //先遍历所有等待数组中的view,累加长度和间距 + for (UIView *view in _waitShowArray) + { + outScreenWidth += view.frame.size.width + TRACK_HORIZONTAL_PADDING; + } + } + + //如果展示数组中有值 + if (_showingArray.count) + { + //拿出最右侧的view + UIView *lastView = [_showingArray lastObject]; + //算出出屏宽 + float rightOutWidth = CGRectGetMaxX(lastView.frame) - self.frame.size.width; + if (rightOutWidth < 0) + { + rightOutWidth = 0; + } + outScreenWidth += rightOutWidth; + } + + return outScreenWidth; +} + +//清理轨道 +- (void)cleanTrack +{ + for (UIView *view in _showingArray) + { + [view removeFromSuperview]; + } + [_showingArray removeAllObjects]; + [_waitShowArray removeAllObjects]; + +} +@end diff --git a/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.h b/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.h new file mode 100644 index 0000000..5be856d --- /dev/null +++ b/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.h @@ -0,0 +1,25 @@ +// +// GiGaSocketRocketUtility.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/17. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import +#import "SocketRocket.h" +extern NSString * const kNeedPayOrderNote; +extern NSString * const kWebSocketDidOpenNote; +extern NSString * const kWebSocketDidCloseNote; +extern NSString * const kWebSocketdidReceiveMessageNote; + +@interface GiGaSocketRocketUtility : NSObject +// 获取连接状态 +@property (nonatomic,assign,readonly) SRReadyState socketReadyState; + ++ (GiGaSocketRocketUtility *)shareInstance; +-(void)srWebSocketOpenWithURLString:(NSString *)urlString;//开启连接 +-(void)srWebSocketClose;//关闭连接 +- (void)sendData:(id)data;//发送数据 + +@end diff --git a/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.m b/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.m new file mode 100644 index 0000000..c644e1d --- /dev/null +++ b/GIGA/Common/SocketRocketUtility/GiGaSocketRocketUtility.m @@ -0,0 +1,248 @@ +// +// GiGaSocketRocketUtility.m +// LXAnimationTest +// +// Created by lianxiang on 2018/8/17. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "GiGaSocketRocketUtility.h" + +#define dispatch_main_async_safe(block)\ +if ([NSThread isMainThread]) {\ +block();\ +} else {\ +dispatch_async(dispatch_get_main_queue(), block);\ +} + +NSString * const kNeedPayOrderNote = @"kNeedPayOrderNote";//发送的通知名 +NSString * const kWebSocketDidOpenNote = @"kWebSocketdidReceiveMessageNote"; +NSString * const kWebSocketDidCloseNote = @"kWebSocketDidCloseNote"; +NSString * const kWebSocketdidReceiveMessageNote = @"kWebSocketdidReceiveMessageNote"; + +@interface GiGaSocketRocketUtility() +{ + int _index; + NSTimer *heartBeat; + NSTimeInterval reConnectTime; +} + +@property (nonatomic,strong) SRWebSocket *socket; +@property (nonatomic,copy) NSString *urlString; + +@end + +@implementation GiGaSocketRocketUtility + ++(GiGaSocketRocketUtility *)shareInstance{ + + static GiGaSocketRocketUtility *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + + }); + return instance; +} +//开启链接 +-(void)srWebSocketOpenWithURLString:(NSString *)url{ + + if (!self.socket) { + return; + } + if (!url) { + return; + } + self.urlString = url; + self.socket = [[SRWebSocket alloc] initWithURLRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:url]]] ; + NSLog(@"请求的websocket地址:%@",self.socket.url.absoluteString); + self.socket.delegate = self; + [self.socket open]; + +} +//关闭连接 + +-(void)srWebSocketClose{ + + if (self.socket) { + [self.socket close]; + self.socket = nil; + [self removeHeartBeat]; + + } +} + +//移除心跳 +-(void)removeHeartBeat{ + + dispatch_main_async_safe(^{ + if (self->heartBeat) { + if ([self->heartBeat respondsToSelector:@selector(isValid)]) { + if ([self->heartBeat isValid]) { + [self->heartBeat invalidate]; + self->heartBeat = nil; + } + } + } + + } + ) +} + +//初始化心跳 +- (void)initHeartBeat +{ + dispatch_main_async_safe(^{ + [self removeHeartBeat]; + //心跳设置为3分钟,NAT超时一般为5分钟 + self->heartBeat = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(sentheart) userInfo:nil repeats:YES]; + //和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小 + [[NSRunLoop currentRunLoop] addTimer:self->heartBeat forMode:NSRunLoopCommonModes]; + + }) +} + + +-(void)sentheart{ + //发送心跳 和后台可以约定发送什么内容 一般可以调用ping 这里发送data + [self sendData:@"heart"]; + +} + +#define WeakSelf(ws) __weak __typeof(&*self)weakSelf = self + +- (void)sendData:(id)data { + + NSLog(@"socketSendData --------------- %@",data); + WeakSelf(ws); + dispatch_queue_t queue = dispatch_queue_create("giga", NULL); + + dispatch_async(queue, ^{ + if (weakSelf.socket != nil) { + // 只有 SR_OPEN 开启状态才能调 send 方法啊,不然要崩 + if (weakSelf.socket.readyState == SR_OPEN) { + [weakSelf.socket send:data]; // 发送数据 + + } else if (weakSelf.socket.readyState == SR_CONNECTING) { + NSLog(@"正在连接中,重连后其他方法会去自动同步数据"); + // 每隔2秒检测一次 socket.readyState 状态,检测 10 次左右 + // 只要有一次状态是 SR_OPEN 的就调用 [ws.socket send:data] 发送数据 + // 如果 10 次都还是没连上的,那这个发送请求就丢失了,这种情况是服务器的问题了,小概率的 + + //重连 + [self reConnect]; + + } else if (weakSelf.socket.readyState == SR_CLOSING || weakSelf.socket.readyState == SR_CLOSED) { + // websocket 断开了,调用 reConnect 方法重连 + NSLog(@"重连"); + [self reConnect]; + + } + } else { + + NSLog(@"没网络,发送失败,一旦断网 socket 会被我设置 nil 的"); + } + }); +} + +//pingPong +- (void)ping{ + + if (self.socket.readyState == SR_OPEN) { + [self.socket sendPing:nil]; + } +} + +#pragma mark - socket delegate + +- (void)webSocketDidOpen:(SRWebSocket *)webSocket{ + //每次正常连接的时候清零重连时间 + reConnectTime = 0; + //开启心跳 + [self initHeartBeat]; + if (webSocket == self.socket) { + NSLog(@"************************** socket 连接成功************************** "); + [[NSNotificationCenter defaultCenter] postNotificationName:kWebSocketDidOpenNote object:nil]; + } +} + +- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error +{ + if (webSocket == self.socket) { + NSLog(@"************************** socket 连接失败************************** "); + NSLog(@"err:%@",error); + + _socket = nil; + //连接失败就重连 + [self reConnect]; + } +} + +- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{ + + if (webSocket == self.socket) { + NSLog(@"************************** socket连接断开************************** "); + NSLog(@"被关闭连接,code:%ld,reason:%@,wasClean:%d",(long)code,reason,wasClean); + [self srWebSocketClose]; + [[NSNotificationCenter defaultCenter] postNotificationName:kWebSocketDidCloseNote object:nil]; + } + +} + +/*该函数是接收服务器发送的pong消息,其中最后一个是接受pong消息的, + 在这里就要提一下心跳包,一般情况下建立长连接都会建立一个心跳包, + 用于每隔一段时间通知一次服务端,客户端还是在线,这个心跳包其实就是一个ping消息, + 我的理解就是建立一个定时器,每隔十秒或者十五秒向服务端发送一个ping消息,这个消息可是是空的 + */ + +-(void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload{ + + NSString *reply = [[NSString alloc] initWithData:pongPayload encoding:NSUTF8StringEncoding]; + NSLog(@"pongPayload===%@",reply); + +} + +- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{ + + if (webSocket == self.socket) { + NSLog(@"************************** socket收到数据了************************** "); + NSLog(@"我这后台约定的 message 是 json 格式数据收到数据,就按格式解析吧,然后把数据发给调用层"); + NSLog(@"message:%@",message); + [[NSNotificationCenter defaultCenter] postNotificationName:kWebSocketdidReceiveMessageNote object:message]; + } +} + +#pragma mark methods +//重连机制 +-(void)reConnect{ + [self srWebSocketClose]; + //超过一分钟就不再重连 所以只会重连5次 2^5 = 64 + if (reConnectTime > 64) { + return; + } + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(reConnectTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + self.socket = nil; + [self srWebSocketOpenWithURLString:self.urlString]; + NSLog(@"重连"); + }); + //重连时间2的指数级增长 + if (reConnectTime ==0 ) { + reConnectTime = 2; + + }else{ + reConnectTime *=2; + } +} + +- (SRReadyState)socketReadyState{ + return self.socket.readyState; +} + +-(void)dealloc{ + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + + +@end diff --git a/GIGA/Config/GIGA.h b/GIGA/Config/GIGA.h index 4a66850..b35d391 100644 --- a/GIGA/Config/GIGA.h +++ b/GIGA/Config/GIGA.h @@ -37,6 +37,8 @@ UD_SYNC #define APP_PUSHTO_DETAILVIEW @"appPushToDetailAdView" //面膜时间结束 #define kLOCALNotifiID_MASKETIMEEND @"GIGALocalNotificationMaskTimeEnd" +#define kUserNoti_MASKEND @"maskTimeEnd" + //app 挂起 #define kLOCALNotifiID_APPTERMINAL @"GIGALocalNotificationAppTerminal" //微信登陆授权成功 diff --git a/GIGA/GIGA.pch b/GIGA/GIGA.pch index f4adb9e..8fc21ca 100644 --- a/GIGA/GIGA.pch +++ b/GIGA/GIGA.pch @@ -16,6 +16,7 @@ #import "UIView+Toast.h" #import "JXTAlertManagerHeader.h" #import "Masonry.h" +#import "GiGaHelper.h" #import #import #import "MobClickList.h" diff --git a/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.m b/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.m index 6ac447b..0b12c2e 100644 --- a/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.m +++ b/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.m @@ -123,6 +123,25 @@ #pragma mark - 登录 -(void)loginBtnAction:(UIButton *)btn{ + + if (self.acountTextField.text == nil) { + GIGA_ShowToast(@"请输入手机号"); + return; + } + if (![GiGaHelper isPhoneNumber:self.acountTextField.text]) { + GIGA_ShowToast(@"请输入正确手机号"); + return; + } + + if (self.passwordTextField.text == nil) { + GIGA_ShowToast(@"密码不能为空"); + return; + } + if (self.passwordTextField.text.length < 6) { + GIGA_ShowToast(@"密码长度不能小于六位字符"); + return; + } + //埋点 [MobClick endEvent:MobClick_UserLogin]; [GiGaUserDefault saveUserId:@"123"]; diff --git a/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.xib b/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.xib index 17b9337..21ae225 100644 --- a/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.xib +++ b/GIGA/Modules/LogIn/Controller/GiGaUserLoginVC.xib @@ -34,7 +34,7 @@ - + @@ -44,7 +44,7 @@ - + diff --git a/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.h b/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.h new file mode 100644 index 0000000..c9e060e --- /dev/null +++ b/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.h @@ -0,0 +1,13 @@ +// +// GiGaFlingCommitVC.h +// GIGA +// +// Created by lianxiang on 2018/8/28. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import + +@interface GiGaFlingCommitVC : UIViewController + +@end diff --git a/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.m b/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.m new file mode 100644 index 0000000..871f3b1 --- /dev/null +++ b/GIGA/Modules/Mask/Controller/GiGaFlingCommitVC.m @@ -0,0 +1,98 @@ +// +// GiGaFlingCommitVC.m +// GIGA +// +// Created by lianxiang on 2018/8/28. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "GiGaFlingCommitVC.h" +#import "GiGaFlyingCommitInputView.h" +#import "LXDanMuManager.h" +#import "GiGaCommentView.h" +#import "GiGaCommentModel.h" +#import "LXDanMuManagerConfig.h" +#import "IQKeyboardManager.h" + +//弹幕控制器 +@interface GiGaFlingCommitVC () +@property (nonatomic,strong) GiGaFlyingCommitInputView *commitInputView; + +@end + +@implementation GiGaFlingCommitVC + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + NC_ADD_TARGET_NAME_OBJECT(self, @selector(maskTimeEnd), kUserNoti_MASKEND, nil); + [self.view addSubview: self.commitInputView]; + self.commitInputView.SendCommentHandler = ^(NSString *content) { + GILog(@"发送->:%@",content); + }; + [[LXDanMuManager shareInstance] createDanmuWithTrackSpeedArray:@[@1.00,@1.00,@3.00,@4.00] centerY:self.view.frame.size.height / 4 trackWidth:self.view.frame.size.width showInView:self.view]; + [[LXDanMuManager shareInstance] start]; + + [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(danmuAction) userInfo:nil repeats:YES]; + + +} + +-(void)danmuAction{ + + [self showFlyingCommit]; +} + +- (GiGaFlyingCommitInputView *)commitInputView{ + + if (!_commitInputView) { +// _commitInputView = [[GiGaFlyingCommitInputView alloc] initWithFrame:CGRectMake(0,self.view.frame.size.height - 60 , KMainW, 60)]; + _commitInputView = [[GiGaFlyingCommitInputView alloc] initWithFrame:self.view.bounds]; + [_commitInputView setPalceholderText:@"请输入弹幕"]; + } + return _commitInputView; +} +-(void)viewWillAppear:(BOOL)animated{ + [super viewWillAppear:animated]; + [IQKeyboardManager sharedManager].enable = NO; +} + +- (void)viewWillDisappear:(BOOL)animated{ + [super viewWillDisappear:animated]; + [IQKeyboardManager sharedManager].enable = YES; +} + +-(void)showFlyingCommit{ + NSArray *classArray = @[@"GiGaCommentView",@"GiGaCommentView"]; + NSArray *nameArray = @[@"mc子龙",@"小明",@"赵四",@"狂小狗",@"葬爱"]; + NSArray *msgArray = @[@"老铁666",@"主播,多少礼物给卡黄啊?",@"文明观球,大家有秩序排队观看,不要着急",@"主播,我报警啦",@"就是个萨比,还扮滴酷酷滴aaaaa"]; + NSArray *avatarArray = @[@"home_login_qq_color",@"home_login_qq_color",@"home_login_qq_color",@"home_login_qq_color",@"home_login_qq_color"]; + int classRandomIndex = arc4random() % 2; + int nameRandomIndex = arc4random() % 5; + int msgRandomIndex = arc4random() % 5; + int avatarRandomIndex = arc4random() % 5; + + GiGaCommentModel *model = [[GiGaCommentModel alloc]init]; + model.userName = nameArray[nameRandomIndex]; + model.msg = msgArray[msgRandomIndex]; + model.userAvatar = avatarArray[avatarRandomIndex]; + GiGaCommentView *customView = [[NSClassFromString(classArray[classRandomIndex]) alloc] initWithMsgModel:model height:TRACK_HEIGHT]; + [[LXDanMuManager shareInstance] appendDanMuWithCustomView:customView toTrackIndex:-1]; +} + +-(void)maskTimeEnd{ + + [[LXDanMuManager shareInstance] destory]; + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +-(void)dealloc{ + NC_REMOVE_NAME(self, kUserNoti_MASKEND, nil); +} + +@end diff --git a/GIGA/Modules/Mask/Controller/GiGaMaskTaskViewController.m b/GIGA/Modules/Mask/Controller/GiGaMaskTaskViewController.m index b830378..428b477 100644 --- a/GIGA/Modules/Mask/Controller/GiGaMaskTaskViewController.m +++ b/GIGA/Modules/Mask/Controller/GiGaMaskTaskViewController.m @@ -23,28 +23,70 @@ #import "GiGaHelper.h" #import #import "GiGaMeViewController.h" - -@interface GiGaMaskTaskViewController () +#import "GiGaFlyingCommitInputView.h" +#import "GiGaFlingCommitVC.h" +@interface GiGaMaskTaskViewController () { AVAudioPlayer *_musicPalyer; } @property(nonatomic,strong)MaskViewBootomWaringView *waringView; @property(nonatomic,strong)UILabel *countLabel; @property (strong ,nonatomic) LXCountTimer *timer; +//@property (nonatomic,strong) GiGaFlyingCommitInputView *commitInputView; +@property(nonatomic,strong) UIImageView *maskImageView; +@property(nonatomic,strong) UIImageView *faceView; +@property(nonatomic,strong) UIDynamicAnimator *animator; +@property(nonatomic,strong) UIAttachmentBehavior *attachmentBehavior; +@property(nonatomic) CGPoint attachPoint; +@property(nonatomic) UISnapBehavior *snapBehavior; @end @implementation GiGaMaskTaskViewController +//倒计时label -(UILabel *)countLabel{ if (!_countLabel) { _countLabel = [[UILabel alloc] init]; _countLabel.textColor = [UIColor redColor]; - _countLabel.text = @"30:00"; + _countLabel.text = @"00:00"; _countLabel.textAlignment = NSTextAlignmentCenter; + } return _countLabel; +} +//面膜 +- (UIImageView *)maskImageView{ + if (!_maskImageView) { + _maskImageView = [[UIImageView alloc] init]; + _maskImageView.userInteractionEnabled = YES; + _maskImageView.backgroundColor = [UIColor purpleColor]; + UIPanGestureRecognizer *pangesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)]; + [_maskImageView addGestureRecognizer:pangesture]; + } + return _maskImageView; +} +//人脸 +- (UIImageView *)faceView{ + if (!_faceView) { + _faceView = [[UIImageView alloc] init]; + _faceView.backgroundColor = [UIColor lightGrayColor]; + _faceView.userInteractionEnabled = YES; + } + return _faceView; +} + +-(void)createInputView{ + GiGaFlingCommitVC* GiGaFlingVC = [[GiGaFlingCommitVC alloc] init]; + if (ISIOS8) { + GiGaFlingVC.modalPresentationStyle = UIModalPresentationOverCurrentContext; + }else{ + GiGaFlingVC.modalPresentationStyle = UIModalPresentationCurrentContext; + } + GiGaFlingVC.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; + [self presentViewController:GiGaFlingVC animated:NO completion:nil]; + } -(LXCountTimer *)timer{ @@ -55,6 +97,73 @@ return _timer; } +//滑动手势 +-(void)panGestureAction:(UIPanGestureRecognizer *)pan{ + + CGPoint panLocation = [pan locationInView:self.view]; + NSLog(@"panlocation.y:%f",panLocation.y); + if (pan.state == UIGestureRecognizerStateBegan) { + + [self animaMask]; +// self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.faceView attachedToAnchor:self.attachPoint]; +// [self.animator addBehavior: self.attachmentBehavior ]; + + }else if (pan.state == UIGestureRecognizerStateChanged){ +// [self.snapBehavior setSnapPoint:self.attachPoint]; +// [self.attachmentBehavior setAnchorPoint:panLocation]; + + }else if (pan.state == UIGestureRecognizerStateEnded){ +// [self.animator addBehavior:self.snapBehavior]; +// [self.animator removeBehavior:self.attachmentBehavior]; + }else{ + + } +} + +#pragma mark -开始面膜时间动画 +-(void)animaMask{ + + [self.view layoutIfNeeded]; + [UIView animateWithDuration:1.0 animations:^{ + [self.maskImageView mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.attachPoint.y - 50); + }]; + [self.faceView mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.attachPoint.y - 50); + }]; + [self.countLabel mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.attachPoint.y + 50 + 10); + }]; + [self.view layoutIfNeeded]; + } completion:^(BOOL finished) { + self.countLabel.hidden = NO; + self.maskImageView.userInteractionEnabled = NO; + //开始面膜时间 + [self startMaskTime]; + }]; +} + +#pragma mark 面膜时间结束复原动画 +-(void)endMaskAnimation{ + + self.countLabel.hidden = YES; + [self.view layoutIfNeeded]; + [UIView animateWithDuration:1.0 animations:^{ + [self.maskImageView mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(100 + 100 + 200); + }]; + + [self.faceView mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(100); + }]; + + [self.view layoutIfNeeded]; + + } completion:^(BOOL finished) { + self.maskImageView.userInteractionEnabled = YES; + }]; +} + -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; @@ -71,16 +180,37 @@ -(void)initUI{ + [self.view addSubview:self.maskImageView]; + [self.view addSubview:self.faceView]; + [self.view bringSubviewToFront:self.maskImageView]; [self.view addSubview:self.countLabel]; - [self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.mas_equalTo(self.view.mas_top).offset(200); - make.width.mas_equalTo(100); - make.height.mas_equalTo(30); - make.centerX.mas_equalTo(self.view.mas_centerX); + self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; + + //face + [self.faceView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.view.mas_top).offset(100); + make.left.mas_equalTo(self.view.mas_centerX).offset(-50); + make.size.mas_equalTo(CGSizeMake(100, 100)); + + }]; + + //mask + [self.maskImageView mas_makeConstraints:^(MASConstraintMaker *make) { + + make.top.mas_equalTo(self.view.mas_top).offset(100 + 100 + 200); + make.left.mas_equalTo(self.view.mas_centerX).offset(-50); + make.size.mas_equalTo(CGSizeMake(100, 100)); }]; + [self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.view.mas_top).offset(200); + make.width.and.height.mas_equalTo(100); + make.centerX.mas_equalTo(self.view.mas_centerX); + }]; + self.countLabel.hidden = YES; + UIButton *testBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [testBtn setTitle:@"测试肤质" forState:UIControlStateNormal]; [testBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; @@ -94,8 +224,15 @@ make.centerX.mas_equalTo(self.view.mas_centerX); make.width.mas_equalTo(150); make.height.mas_equalTo(40); - make.bottom.mas_equalTo(self.view.mas_bottom).offset(-200); + make.bottom.mas_equalTo(self.view.mas_bottom).offset(-130); }]; + + [self.view layoutIfNeeded]; + CGFloat Y = CGRectGetMinY(self.maskImageView.frame) - 100; + CGFloat X = CGRectGetMidX(self.view.frame); + CGPoint anchorPoint = CGPointMake(X, Y); + self.attachPoint = anchorPoint; +// self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.maskImageView snapToPoint:self.attachPoint]; } #pragma mark 开始计时 @@ -131,14 +268,12 @@ //设置后台模式和锁屏模式下依然能够播放 //[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; - - - } #pragma mark 开始面膜时间 -(void)startMaskTime{ + [self createInputView]; //出现弹幕 AppDelegate *delegate =(AppDelegate *) [[UIApplication sharedApplication] delegate]; if (delegate.isMasking) { return; @@ -148,7 +283,7 @@ [self setBackGroundPlayingInfo];//锁屏音频信息 //总时间隔 s - NSTimeInterval timeInterVal = 58; + NSTimeInterval timeInterVal = 61; NSString *timeformat = [GiGaHelper stringWithNSTimerinterval:timeInterVal]; NSArray *timesArr = [timeformat componentsSeparatedByString:@":"]; NSString *hour = timesArr[0]; @@ -158,6 +293,7 @@ [self showWaringView]; + return; //app 前台时收到本地通知showAlert 后台时通知提醒 [[GiGaLocalNotificationManager localNotifiationCenter] sendLocalNotification:@"本地推送" fireTimeInterval:timeInterVal alertAction:@"测试面膜时间" withIdentifier:kLOCALNotifiID_MASKETIMEEND]; @@ -183,7 +319,7 @@ } -- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent { +- (void)remoteControlReceivedWithEvent: (UIEvent *) receivedEvent { if (receivedEvent.type == UIEventTypeRemoteControl) { switch (receivedEvent.subtype) { @@ -207,20 +343,22 @@ #pragma mark 面膜时间结束 -(void)maskTimeEnd{ + NC_POST_NAME_OBJECT(kUserNoti_MASKEND, nil); //面膜时间结束时设置 全局变量 不再发送本地通知 提醒 AppDelegate *delegate =(AppDelegate *) [[UIApplication sharedApplication] delegate]; delegate.isMasking = NO; [_musicPalyer stop]; [self.timer destoryTimer]; - + //复原动画 + [self endMaskAnimation]; } #pragma mark 开始测试 -(void)testBtnAcion:(UIButton *)btn{ - [self startMaskTime]; - return ; +// [self startMaskTime]; +// return ; BOOL isUserLogin = [GiGaUserDefault isUserLogin]; @@ -305,7 +443,6 @@ #pragma mark - setUpNav -(void)setUpNav{ - //leftItem UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom]; leftBtn.frame = CGRectMake(0, 0, 40, 40); @@ -381,5 +518,4 @@ } - @end diff --git a/GIGA/Modules/Mask/Model/GiGaCommentModel.h b/GIGA/Modules/Mask/Model/GiGaCommentModel.h new file mode 100644 index 0000000..c683e4d --- /dev/null +++ b/GIGA/Modules/Mask/Model/GiGaCommentModel.h @@ -0,0 +1,18 @@ +// +// GiGaCommentModel.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import +#import "JSONModel.h" +@interface GiGaCommentModel :JSONModel + +@property (nonatomic,copy) NSString *userName; +@property (nonatomic,copy) NSString *userLevel; +@property (nonatomic,copy) NSString *msg; +@property (nonatomic,copy) NSString *userAvatar; + +@end diff --git a/GIGA/Modules/Mask/Model/GiGaCommentModel.m b/GIGA/Modules/Mask/Model/GiGaCommentModel.m new file mode 100644 index 0000000..698fea7 --- /dev/null +++ b/GIGA/Modules/Mask/Model/GiGaCommentModel.m @@ -0,0 +1,13 @@ +// +// GiGaCommentModel.m +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "GiGaCommentModel.h" + +@implementation GiGaCommentModel + +@end diff --git a/GIGA/Modules/Mask/View/GiGaCommentView.h b/GIGA/Modules/Mask/View/GiGaCommentView.h new file mode 100644 index 0000000..628a9f0 --- /dev/null +++ b/GIGA/Modules/Mask/View/GiGaCommentView.h @@ -0,0 +1,15 @@ +// +// GiGaCommentView.h +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import +#import "GiGaCommentModel.h" +@interface GiGaCommentView : UIView +@property(nonatomic,strong) GiGaCommentModel *msgModel; +-(instancetype)initWithMsgModel:(GiGaCommentModel *)model height:(CGFloat)height; + +@end diff --git a/GIGA/Modules/Mask/View/GiGaCommentView.m b/GIGA/Modules/Mask/View/GiGaCommentView.m new file mode 100644 index 0000000..55f95f2 --- /dev/null +++ b/GIGA/Modules/Mask/View/GiGaCommentView.m @@ -0,0 +1,94 @@ +// +// GiGaCommentView.m +// LXAnimationTest +// +// Created by lianxiang on 2018/8/14. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "GiGaCommentView.h" +#import "Masonry.h" +@interface GiGaCommentView() +@property(nonatomic,strong) UILabel *userName; +@property(nonatomic,strong) UIImageView *userAvtar; +@property(nonatomic,strong) UILabel *msg; +@end + +@implementation GiGaCommentView + +-(instancetype)initWithMsgModel:(GiGaCommentModel *)model height:(CGFloat)height{ + + if (self = [super init]) { + self.frame = CGRectMake(0, 0, 0, height); + _msgModel = model; + //self.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5]; + self.backgroundColor = [UIColor redColor]; + [self initUI]; + } + return self; +} + +-(void)layoutIfNeeded{ + +} +- (void)layoutSubviews{ + +} + +-(void)initUI{ + + UIImageView *avatar = [[UIImageView alloc] init]; + avatar.image = [UIImage imageNamed:@"home_login_qq_color"]; + //avatar.frame = CGRectMake(3, 3, self.frame.size.height - 6, self.frame.size.height - 6); + avatar.layer.masksToBounds = YES; + avatar.layer.cornerRadius = 15; + [self addSubview:avatar]; + avatar.image = [UIImage imageNamed:_msgModel.userAvatar]; + self.userAvtar = avatar; + [self.userAvtar mas_makeConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo(30); + make.height.mas_equalTo(30); + make.left.mas_equalTo(self.mas_left).mas_offset(3); + make.top.mas_equalTo(self.mas_top).mas_offset(3); + + }]; + + UILabel *namelabel = [[UILabel alloc] init]; + namelabel.font = [UIFont systemFontOfSize:14]; + namelabel.textColor = [UIColor blackColor]; + //namelabel.frame= CGRectMake(CGRectGetMaxX(avatar.frame) + 5, 4, namelabel.frame.size.width, namelabel.frame.size.height); + namelabel.text = _msgModel.userName; + [namelabel sizeToFit]; + self.userName = namelabel; + [self addSubview:self.userName]; + [self.userName mas_makeConstraints:^(MASConstraintMaker *make) { + + make.left.mas_equalTo(self.userAvtar.mas_right).mas_offset(3); + make.top.mas_equalTo(self.mas_top).mas_offset(10); + + }]; + + UILabel *msglabel = [[UILabel alloc] init]; + msglabel.font = [UIFont systemFontOfSize:13]; + msglabel.textColor = [UIColor blackColor]; + + //msglabel.frame= CGRectMake(namelabel.frame.origin.x, CGRectGetMaxY(avatar.frame) - msglabel.frame.size.height - namelabel.frame.origin.y, msglabel.frame.size.width, msglabel.frame.size.height); + msglabel.text = _msgModel.msg; + self.msg = msglabel; + [msglabel sizeToFit]; + [self addSubview:self.msg]; + [self.msg mas_makeConstraints:^(MASConstraintMaker *make) { + + make.top.mas_equalTo(self.userAvtar.mas_bottom).mas_offset(3); + make.left.mas_equalTo(self.mas_left).mas_offset(5); + + + }]; + + float width = msglabel.frame.size.width > namelabel.frame.size.width ? msglabel.frame.size.width:namelabel.frame.size.width ; + + self.frame = CGRectMake(0, 0, namelabel.frame.origin.x + 10 + width, self.frame.size.height); + +} + +@end diff --git a/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.h b/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.h new file mode 100644 index 0000000..00f8f29 --- /dev/null +++ b/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.h @@ -0,0 +1,17 @@ +// +// GiGaFlyingCommitInputView.h +// GIGA +// +// Created by lianxiang on 2018/8/28. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import + +@interface GiGaFlyingCommitInputView : UIView + +@property (nonatomic, copy) void (^SendCommentHandler)(NSString *content); +@property (nonatomic, copy) NSString *palceholderText; +-(void)setPalceholderText:(NSString *)palceholderText; + +@end diff --git a/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.m b/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.m new file mode 100644 index 0000000..747f36e --- /dev/null +++ b/GIGA/Modules/Mask/View/GiGaFlyingCommitInputView.m @@ -0,0 +1,169 @@ +// +// GiGaFlyingCommitInputView.m +// GIGA +// +// Created by lianxiang on 2018/8/28. +// Copyright © 2018年 com.giga.ios. All rights reserved. +// + +#import "GiGaFlyingCommitInputView.h" +@interface GiGaFlyingCommitInputView() +@property(nonatomic,strong) UIView *commitInputView; +@property(nonatomic,strong) UITextField * inputTextField; +@end + +@implementation GiGaFlyingCommitInputView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + +// self.backgroundColor = [UIColor blackColor]; + self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1]; +// UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(dismissSelfViewTap)]; +// [self addGestureRecognizer:tap]; + + [self creatInputView]; + [self bringSubviewToFront:_commitInputView]; + } + + return self; +} + +-(void)creatInputView{ + + UIView *commitView =[[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - 60, self.bounds.size.width, 60)]; +// commitView.frame = CGRectMake(0, self.frame.size.height-commitView.frame.size.height, self.frame.size.width, commitView.frame.size.height); + self.commitInputView = commitView; + self.commitInputView.backgroundColor = [UIColor redColor]; + [self addSubview:self.commitInputView]; + + UIButton *sendBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + CGFloat topMargin = 5; + CGFloat leftMargin = 10; + sendBtn.frame = CGRectMake(self.frame.size.width - leftMargin - 60,topMargin,60,40); + [sendBtn addTarget:self action:@selector(sendBtnAction:) forControlEvents:UIControlEventTouchUpInside]; + [sendBtn setTitle:@"发送" forState:UIControlStateNormal]; + [sendBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + sendBtn.backgroundColor = [UIColor purpleColor]; + sendBtn.layer.masksToBounds = YES; + sendBtn.layer.cornerRadius = 4; + [commitView addSubview:sendBtn]; + UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 5,self.frame.size.width - sendBtn.frame.size.width - 10*2 - 5, 30)]; + textField.backgroundColor = [UIColor lightGrayColor]; + textField.clearButtonMode = UITextFieldViewModeWhileEditing; + textField.delegate = self; + [commitView addSubview:textField]; + self.inputTextField = textField; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; + +} + +-(void)setPalceholderText:(NSString *)palceholderText +{ + _palceholderText = palceholderText; +} + +-(void)dismissSelfViewTap{ + [self removeFromSuperview]; +} + +-(void)sendBtnAction:(UIButton *)btn{ + + [self sendCommend]; +} + +-(void)sendCommend{ + + if (self.inputTextField.text.length > 200) { + [[UIApplication sharedApplication].keyWindow makeToast:@"The comments should not exceed 200 words" duration:1 position:CSToastPositionCenter]; + return; + } + if (self.inputTextField.text.length == 0) { + + [[UIApplication sharedApplication].keyWindow makeToast:@"Comment content cannot be empty" duration:1 position:CSToastPositionCenter]; + return; + } + + if (self.SendCommentHandler) { + self.SendCommentHandler(self.inputTextField.text); + } + + [self dismissKeyboard]; + +} + +- (void)dismissKeyboard +{ + if ([self.inputTextField becomeFirstResponder]) { + [self.inputTextField resignFirstResponder]; + } +} + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; +{ + if (textField ==self.inputTextField) { + textField.placeholder = _palceholderText; + } + + return YES; +} + +-(BOOL)textFieldShouldReturn:(UITextField *)textField{ + + if (textField ==self.inputTextField) { + [self sendCommend]; + } + + return YES; +} + +- (void)keyboardWillShow:(NSNotification*)notification { + + // get keyboard size and loctaion + CGRect keyboardBounds; + [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds]; + NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; + NSNumber *curve = [notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey]; + + // Need to translate the bounds to account for rotation. + keyboardBounds = [self convertRect:keyboardBounds toView:nil]; + + // get a rect for the textView frame + CGRect commentInputViewFrame = self.commitInputView.frame; + commentInputViewFrame.origin.y = self.bounds.size.height - (keyboardBounds.size.height + commentInputViewFrame.size.height); + + // animations settings + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationDuration:[duration doubleValue]]; + [UIView setAnimationCurve:[curve intValue]]; + + // set views with new info + self.commitInputView.frame = commentInputViewFrame; + + [UIView commitAnimations]; + + +} + +- (void) keyboardWillHide:(NSNotification *)note +{ + self.commitInputView.frame = CGRectMake(0, self.bounds.size.height - 60, self.bounds.size.width, 60); +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + self.commitInputView = nil; + self.inputTextField= nil; + +} + +@end