diff --git a/HC.xcodeproj/project.pbxproj b/HC.xcodeproj/project.pbxproj index 2be6d1f..3288676 100644 --- a/HC.xcodeproj/project.pbxproj +++ b/HC.xcodeproj/project.pbxproj @@ -11,7 +11,7 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 38BE1CFC2ECC0F28004B805B /* Exceptions for "HC" folder in "HC" target */ = { + 3895388C2ED53BDF004AECEA /* Exceptions for "HC" folder in "HC" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( Info.plist, @@ -24,7 +24,7 @@ 38BE1CE42ECC0F27004B805B /* HC */ = { isa = PBXFileSystemSynchronizedRootGroup; exceptions = ( - 38BE1CFC2ECC0F28004B805B /* Exceptions for "HC" folder in "HC" target */, + 3895388C2ED53BDF004AECEA /* Exceptions for "HC" folder in "HC" target */, ); path = HC; sourceTree = ""; diff --git a/HC.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/HC.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/HC.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/HC.xcodeproj/project.xcworkspace/xcuserdata/huilinli.xcuserdatad/WorkspaceSettings.xcsettings b/HC.xcodeproj/project.xcworkspace/xcuserdata/huilinli.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..723a561 --- /dev/null +++ b/HC.xcodeproj/project.xcworkspace/xcuserdata/huilinli.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,16 @@ + + + + + BuildLocationStyle + UseAppPreferences + CompilationCachingSetting + Default + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + ShowSharedSchemesAutomaticallyEnabled + + + diff --git a/HC.xcodeproj/xcuserdata/huilinli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/HC.xcodeproj/xcuserdata/huilinli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..7896bae --- /dev/null +++ b/HC.xcodeproj/xcuserdata/huilinli.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/HC/AppDelegate.h b/HC/AppDelegate.h index b765a55..b77986a 100644 --- a/HC/AppDelegate.h +++ b/HC/AppDelegate.h @@ -11,7 +11,7 @@ @interface AppDelegate : UIResponder @property (readonly, strong) NSPersistentContainer *persistentContainer; - +@property (strong, nonatomic) UIWindow *window; - (void)saveContext; diff --git a/HC/AppDelegate.m b/HC/AppDelegate.m index bb6d50e..cb28cd1 100644 --- a/HC/AppDelegate.m +++ b/HC/AppDelegate.m @@ -6,6 +6,8 @@ // #import "AppDelegate.h" +#import "ViewController.h" +#import "ChartViewController.h" @interface AppDelegate () @@ -15,11 +17,12 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. + #if DEBUG + [[NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"] load]; + #endif return YES; } - #pragma mark - UISceneSession lifecycle diff --git a/HC/Assets.xcassets/banner1.imageset/Contents.json b/HC/Assets.xcassets/banner1.imageset/Contents.json new file mode 100644 index 0000000..70f2d3b --- /dev/null +++ b/HC/Assets.xcassets/banner1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "banner1.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/banner1.imageset/banner1.jpg b/HC/Assets.xcassets/banner1.imageset/banner1.jpg new file mode 100644 index 0000000..75913b1 Binary files /dev/null and b/HC/Assets.xcassets/banner1.imageset/banner1.jpg differ diff --git a/HC/Assets.xcassets/banner2.imageset/Contents.json b/HC/Assets.xcassets/banner2.imageset/Contents.json new file mode 100644 index 0000000..938f499 --- /dev/null +++ b/HC/Assets.xcassets/banner2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "banner2.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/banner2.imageset/banner2.jpg b/HC/Assets.xcassets/banner2.imageset/banner2.jpg new file mode 100644 index 0000000..f654642 Binary files /dev/null and b/HC/Assets.xcassets/banner2.imageset/banner2.jpg differ diff --git a/HC/Assets.xcassets/email.imageset/Contents.json b/HC/Assets.xcassets/email.imageset/Contents.json new file mode 100644 index 0000000..6488cb4 --- /dev/null +++ b/HC/Assets.xcassets/email.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "email.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/email.imageset/email.jpg b/HC/Assets.xcassets/email.imageset/email.jpg new file mode 100644 index 0000000..aa23c37 Binary files /dev/null and b/HC/Assets.xcassets/email.imageset/email.jpg differ diff --git a/HC/Assets.xcassets/hqz.imageset/Contents.json b/HC/Assets.xcassets/hqz.imageset/Contents.json new file mode 100644 index 0000000..1b018f8 --- /dev/null +++ b/HC/Assets.xcassets/hqz.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hqz.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/hqz.imageset/hqz.jpg b/HC/Assets.xcassets/hqz.imageset/hqz.jpg new file mode 100644 index 0000000..11c413f Binary files /dev/null and b/HC/Assets.xcassets/hqz.imageset/hqz.jpg differ diff --git a/HC/Assets.xcassets/image.imageset/Contents.json b/HC/Assets.xcassets/image.imageset/Contents.json new file mode 100644 index 0000000..a19a549 --- /dev/null +++ b/HC/Assets.xcassets/image.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/logo.imageset/20251117-225344.jpg b/HC/Assets.xcassets/logo.imageset/20251117-225344.jpg new file mode 100644 index 0000000..8b15a5f Binary files /dev/null and b/HC/Assets.xcassets/logo.imageset/20251117-225344.jpg differ diff --git a/HC/Assets.xcassets/logo.imageset/Contents.json b/HC/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..2b4b876 --- /dev/null +++ b/HC/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "20251117-225344.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/logo.jpg b/HC/Assets.xcassets/logo.jpg new file mode 100644 index 0000000..8b15a5f Binary files /dev/null and b/HC/Assets.xcassets/logo.jpg differ diff --git a/HC/Assets.xcassets/singapore_flag.imageset/Contents.json b/HC/Assets.xcassets/singapore_flag.imageset/Contents.json new file mode 100644 index 0000000..d3d93b6 --- /dev/null +++ b/HC/Assets.xcassets/singapore_flag.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "singapore_flag.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/HC/Assets.xcassets/singapore_flag.imageset/singapore_flag.jpg b/HC/Assets.xcassets/singapore_flag.imageset/singapore_flag.jpg new file mode 100644 index 0000000..b255901 Binary files /dev/null and b/HC/Assets.xcassets/singapore_flag.imageset/singapore_flag.jpg differ diff --git a/HC/CNViewController.h b/HC/CNViewController.h new file mode 100644 index 0000000..a524a7e --- /dev/null +++ b/HC/CNViewController.h @@ -0,0 +1,16 @@ +// +// CNViewController.h +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface CNViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/HC/CNViewController.m b/HC/CNViewController.m new file mode 100644 index 0000000..1f71662 --- /dev/null +++ b/HC/CNViewController.m @@ -0,0 +1,12 @@ +// +// CNViewController.m +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import "CNViewController.h" + +@implementation CNViewController + +@end diff --git a/HC/ChartViewController.h b/HC/ChartViewController.h new file mode 100644 index 0000000..2c0f6c7 --- /dev/null +++ b/HC/ChartViewController.h @@ -0,0 +1,16 @@ +// +// ChartViewController.h +// HC +// +// Created by huilinLi on 2025/11/27. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ChartViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/HC/ChartViewController.m b/HC/ChartViewController.m new file mode 100644 index 0000000..91208fe --- /dev/null +++ b/HC/ChartViewController.m @@ -0,0 +1,592 @@ +// ChartViewController.m +// HC +// +// Created by huilinLi on 2025/11/27. +// + +#import "ChartViewController.h" +#import "StockKLineModel.h" + +@interface ChartViewController () + +// 上方卡片容器 +@property (nonatomic, strong) UIView *cardContainer; +// k线选择项容器 +@property (nonatomic, strong) UIView *kSelectContainer; +// K线图表容器 +@property (nonatomic, strong) UIView *kLineContainer; +// K线图表滚动视图 +@property (nonatomic, strong) UIScrollView *kLineScrollView; + +// K线数据 +@property (nonatomic, strong) NSArray *kLineData; +// 价格刻度标签 +@property (nonatomic, strong) NSArray *priceLabels; +// 日期刻度标签 +@property (nonatomic, strong) NSArray *dateLabels; + +// 默认展示的K线数量 +@property (nonatomic, assign) NSInteger visibleKLineCount; + +@end + +@implementation ChartViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + + self.visibleKLineCount = 40; + + [self generateMockData]; + [self setupSubviews]; + [self setupConstraints]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self drawKLineChart]; + + if (self.kLineScrollView.contentSize.width > self.kLineScrollView.bounds.size.width) { + CGPoint offset = CGPointMake(self.kLineScrollView.contentSize.width - self.kLineScrollView.bounds.size.width, 0); + [self.kLineScrollView setContentOffset:offset animated:NO]; + } + }); +} + +#pragma mark - UI Setup +-(void) setupSubviews{ + // 卡片容器 + _cardContainer = [[UIView alloc] init]; + _cardContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 + green:26.0/255.0 + blue:2.0/255.0 + alpha:1.0]; + _cardContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_cardContainer]; + + UILabel *cardLabel1 = [[UILabel alloc] init]; + cardLabel1.text = @"1617.060"; + cardLabel1.textColor = [UIColor redColor]; + cardLabel1.font = [UIFont systemFontOfSize:15]; + cardLabel1.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabel1]; + + UILabel *cardLabel2 = [[UILabel alloc] init]; + cardLabel2.text = @"-7.470"; + cardLabel2.textColor = [UIColor redColor]; + cardLabel2.font = [UIFont systemFontOfSize:8]; + cardLabel2.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabel2]; + + UILabel *cardLabel3 = [[UILabel alloc] init]; + cardLabel3.text = @"-0.461%"; + cardLabel3.textColor = [UIColor redColor]; + cardLabel3.font = [UIFont systemFontOfSize:8]; + cardLabel3.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabel3]; + + [NSLayoutConstraint activateConstraints:@[ + [cardLabel1.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:25], + [cardLabel1.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10], + + [cardLabel2.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:50], + [cardLabel2.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant: 8], + + [cardLabel3.topAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:50], + [cardLabel3.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant: 45] + ]]; + + UILabel *cardLabelHeight = [[UILabel alloc] init]; + cardLabelHeight.text = @"高"; + cardLabelHeight.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelHeight.font = [UIFont systemFontOfSize:15]; + cardLabelHeight.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelHeight]; + + UILabel *cardLabelStart = [[UILabel alloc] init]; + cardLabelStart.text = @"开"; + cardLabelStart.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelStart.font = [UIFont systemFontOfSize:15]; + cardLabelStart.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelStart]; + + UILabel *cardLabelVolume = [[UILabel alloc] init]; + cardLabelVolume.text = @"量"; + cardLabelVolume.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelVolume.font = [UIFont systemFontOfSize:15]; + cardLabelVolume.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelVolume]; + + UILabel *cardLabelLow = [[UILabel alloc] init]; + cardLabelLow.text = @"低"; + cardLabelLow.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelLow.font = [UIFont systemFontOfSize:15]; + cardLabelLow.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelLow]; + + UILabel *cardLabelChange = [[UILabel alloc] init]; + cardLabelChange.text = @"换"; + cardLabelChange.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelChange.font = [UIFont systemFontOfSize:15]; + cardLabelChange.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelChange]; + + UILabel *cardLabelQuota = [[UILabel alloc] init]; + cardLabelQuota.text = @"额"; + cardLabelQuota.textColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + cardLabelQuota.font = [UIFont systemFontOfSize:15]; + cardLabelQuota.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardLabelQuota]; + + UILabel *cardNumHeight = [[UILabel alloc] init]; + cardNumHeight.text = @"1617.260"; + cardNumHeight.textColor = [UIColor redColor]; + cardNumHeight.font = [UIFont systemFontOfSize:12]; + cardNumHeight.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumHeight]; + + UILabel *cardNumStart = [[UILabel alloc] init]; + cardNumStart.text = @"1616.750"; + cardNumStart.textColor = [UIColor redColor]; + cardNumStart.font = [UIFont systemFontOfSize:12]; + cardNumStart.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumStart]; + + UILabel *cardNumVolume = [[UILabel alloc] init]; + cardNumVolume.text = @"1.511亿"; + cardNumVolume.textColor = [UIColor whiteColor]; + cardNumVolume.font = [UIFont systemFontOfSize:12]; + cardNumVolume.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumVolume]; + + UILabel *cardNumLow = [[UILabel alloc] init]; + cardNumLow.text = @"1608.850"; + cardNumLow.textColor = [UIColor whiteColor]; + cardNumLow.font = [UIFont systemFontOfSize:12]; + cardNumLow.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumLow]; + + UILabel *cardNumChange = [[UILabel alloc] init]; + cardNumChange.text = @"--"; + cardNumChange.textColor = [UIColor whiteColor]; + cardNumChange.font = [UIFont systemFontOfSize:12]; + cardNumChange.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumChange]; + + UILabel *cardNumQuota = [[UILabel alloc] init]; + cardNumQuota.text = @"--"; + cardNumQuota.textColor = [UIColor whiteColor]; + cardNumQuota.font = [UIFont systemFontOfSize:12]; + cardNumQuota.translatesAutoresizingMaskIntoConstraints = NO; + [_cardContainer addSubview:cardNumQuota]; + + [NSLayoutConstraint activateConstraints:@[ + [cardLabelHeight.bottomAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-75], + + [cardLabelStart.bottomAnchor constraintEqualToAnchor:cardLabelHeight.bottomAnchor], + + [cardLabelVolume.bottomAnchor constraintEqualToAnchor:cardLabelHeight.bottomAnchor], + + [cardLabelLow.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], + [cardLabelLow.leadingAnchor constraintEqualToAnchor:cardLabelHeight.leadingAnchor], + + [cardLabelChange.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], + [cardLabelChange.leadingAnchor constraintEqualToAnchor:cardLabelStart.leadingAnchor], + + [cardLabelQuota.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-50], + [cardLabelQuota.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor], + + [cardNumHeight.bottomAnchor constraintEqualToAnchor:_cardContainer.topAnchor constant:45], + [cardNumHeight.leadingAnchor constraintEqualToAnchor:cardLabelHeight.leadingAnchor], + + [cardNumStart.bottomAnchor constraintEqualToAnchor:cardNumHeight.bottomAnchor], + [cardNumStart.leadingAnchor constraintEqualToAnchor:cardLabelStart.leadingAnchor], + + [cardNumVolume.bottomAnchor constraintEqualToAnchor:cardNumHeight.bottomAnchor], + [cardNumVolume.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor], + + [cardNumLow.bottomAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:-10], + [cardNumLow.leadingAnchor constraintEqualToAnchor:cardLabelLow.leadingAnchor], + + [cardNumChange.bottomAnchor constraintEqualToAnchor:cardNumLow.bottomAnchor], + [cardNumChange.leadingAnchor constraintEqualToAnchor:cardLabelChange.leadingAnchor], + + [cardNumQuota.bottomAnchor constraintEqualToAnchor:cardNumLow.bottomAnchor], + [cardNumQuota.leadingAnchor constraintEqualToAnchor:cardLabelVolume.leadingAnchor] + ]]; + + [NSLayoutConstraint constraintWithItem:cardLabelHeight + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_cardContainer + attribute:NSLayoutAttributeTrailing + multiplier:0.25 + constant:0].active = YES; + [NSLayoutConstraint constraintWithItem:cardLabelStart + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_cardContainer + attribute:NSLayoutAttributeTrailing + multiplier:0.5 + constant:0].active = YES; + [NSLayoutConstraint constraintWithItem:cardLabelVolume + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_cardContainer + attribute:NSLayoutAttributeTrailing + multiplier:0.75 + constant:0].active = YES; + + // K线选择项容器 + _kSelectContainer = [[UIView alloc] init]; + _kSelectContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 + green:26.0/255.0 + blue:2.0/255.0 + alpha:1.0]; + _kSelectContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_kSelectContainer]; + [self addKSelectOptions]; + + // K线图表容器 + self.kLineContainer = [[UIView alloc] init]; + self.kLineContainer.backgroundColor = [UIColor colorWithRed:26.0/255.0 green:26.0/255.0 blue:26.0/255.0 alpha:1.0]; + self.kLineContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.kLineContainer]; + + // K线图表滚动视图 + self.kLineScrollView = [[UIScrollView alloc] init]; + self.kLineScrollView.backgroundColor = [UIColor clearColor]; + self.kLineScrollView.showsHorizontalScrollIndicator = NO; + self.kLineScrollView.userInteractionEnabled = YES; + self.kLineScrollView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.kLineContainer addSubview:self.kLineScrollView]; + + CGFloat priceLabelAreaWidth = 50.0; + + // 滚动视图的约束 + [NSLayoutConstraint activateConstraints:@[ + [self.kLineScrollView.topAnchor constraintEqualToAnchor:self.kLineContainer.topAnchor], + [self.kLineScrollView.bottomAnchor constraintEqualToAnchor:self.kLineContainer.bottomAnchor], + [self.kLineScrollView.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor constant:priceLabelAreaWidth], + [self.kLineScrollView.trailingAnchor constraintEqualToAnchor:self.kLineContainer.trailingAnchor], + [self.kLineScrollView.heightAnchor constraintEqualToAnchor:self.kLineContainer.heightAnchor] + ]]; + + // 边框 + UIView *borderView = [[UIView alloc] init]; + borderView.backgroundColor = [UIColor clearColor]; + borderView.layer.borderWidth = 1; + borderView.layer.borderColor = [[UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1.0] CGColor]; + borderView.translatesAutoresizingMaskIntoConstraints = NO; + [self.kLineContainer addSubview:borderView]; + [NSLayoutConstraint activateConstraints:@[ + [borderView.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor], + [borderView.trailingAnchor constraintEqualToAnchor:self.kLineContainer.trailingAnchor], + [borderView.topAnchor constraintEqualToAnchor:self.kLineContainer.topAnchor], + [borderView.bottomAnchor constraintEqualToAnchor:self.kLineContainer.bottomAnchor] + ]]; + + // 动态计算模型数据的价格区间 + CGFloat maxPrice = 0; + CGFloat minPrice = CGFLOAT_MAX; + for (id item in self.kLineData) { + if ([item isKindOfClass:[StockKLineModel class]]) { + StockKLineModel *model = (StockKLineModel *)item; + maxPrice = MAX(maxPrice, model.high); + minPrice = MIN(minPrice, model.low); + } else if ([item isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)item; + maxPrice = MAX(maxPrice, [dict[@"high"] floatValue]); + minPrice = MIN(minPrice, [dict[@"low"] floatValue]); + } + } + maxPrice = maxPrice + (maxPrice - minPrice) * 0.1; + minPrice = minPrice - (maxPrice - minPrice) * 0.1; + + // 价格刻度 + NSMutableArray *priceLabelArr = [NSMutableArray array]; + for (NSInteger i = 0; i < 5; i++) { + CGFloat price = maxPrice - (maxPrice - minPrice) / 4 * i; + UILabel *label = [[UILabel alloc] init]; + label.text = [NSString stringWithFormat:@"%.1f", price]; + label.textColor = [UIColor lightGrayColor]; + label.font = [UIFont systemFontOfSize:10]; + label.translatesAutoresizingMaskIntoConstraints = NO; + [self.kLineContainer addSubview:label]; + + [NSLayoutConstraint activateConstraints:@[ + [label.leadingAnchor constraintEqualToAnchor:self.kLineContainer.leadingAnchor constant:5], + [label.centerYAnchor constraintEqualToAnchor:self.kLineContainer.centerYAnchor constant:-80 + 40 * i] + ]]; + [priceLabelArr addObject:label]; + } + self.priceLabels = priceLabelArr; + + self.dateLabels = @[]; +} + +- (void)addKSelectOptions { + NSArray *titles = @[@"日k", @"周k", @"月k", @"更多", @"设置"]; + + UIStackView *stackView = [[UIStackView alloc] init]; + stackView.axis = UILayoutConstraintAxisHorizontal; + stackView.distribution = UIStackViewDistributionFillEqually; + stackView.alignment = UIStackViewAlignmentCenter; + stackView.spacing = 5.0; + stackView.translatesAutoresizingMaskIntoConstraints = NO; + + for (NSString *title in titles) { + UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; + [button setTitle:title forState:UIControlStateNormal]; + button.titleLabel.font = [UIFont systemFontOfSize:14]; + [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + if ([title isEqualToString:@"日k"]) { + [button setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal]; + button.layer.borderColor = [[UIColor yellowColor] CGColor]; + button.layer.borderWidth = 1.0; + } else { + [button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + button.layer.borderWidth = 0; + } + + button.layer.cornerRadius = 3.0; + button.clipsToBounds = YES; + + [stackView addArrangedSubview:button]; + } + + [_kSelectContainer addSubview:stackView]; + + [NSLayoutConstraint activateConstraints:@[ + [stackView.leadingAnchor constraintEqualToAnchor:_kSelectContainer.leadingAnchor constant:10], + [stackView.trailingAnchor constraintEqualToAnchor:_kSelectContainer.trailingAnchor constant:-10], + [stackView.topAnchor constraintEqualToAnchor:_kSelectContainer.topAnchor constant:5], + [stackView.bottomAnchor constraintEqualToAnchor:_kSelectContainer.bottomAnchor constant:-5] + ]]; +} + +#pragma mark - Constraints +- (void)setupConstraints{ + [NSLayoutConstraint activateConstraints:@[ + [_cardContainer.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], + [_cardContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [_cardContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], + [_cardContainer.heightAnchor constraintEqualToConstant:100], + + [_kSelectContainer.topAnchor constraintEqualToAnchor:_cardContainer.bottomAnchor constant:5], + [_kSelectContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [_kSelectContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], + [_kSelectContainer.heightAnchor constraintEqualToConstant:40], + + [self.kLineContainer.topAnchor constraintEqualToAnchor:self.kSelectContainer.bottomAnchor constant:5], + [self.kLineContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.kLineContainer.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], + [self.kLineContainer.heightAnchor constraintEqualToConstant:200] + ]]; +} + +#pragma mark - KLine Drawing +- (void)drawKLineChart { + // 移除旧的 K 线 + for (UIView *subview in self.kLineScrollView.subviews) { + if (![subview isKindOfClass:[UILabel class]]) { + [subview removeFromSuperview]; + } + } + + CGFloat chartHeight = self.kLineContainer.bounds.size.height; + if (chartHeight == 0) { + chartHeight = 200; + } + + // K线宽度计算 + CGFloat kLineUnitWidth = 5.0; + CGFloat kLineRatio = 0.8; + CGFloat kLineWidth = kLineUnitWidth * kLineRatio; + CGFloat space = kLineUnitWidth * (1.0 - kLineRatio); + CGFloat totalChartWidth = kLineUnitWidth * self.kLineData.count; + + // 设置contentSize + self.kLineScrollView.contentSize = CGSizeMake(totalChartWidth, chartHeight); + + // 动态计算价格区间 + CGFloat maxPrice = 0; + CGFloat minPrice = CGFLOAT_MAX; + for (id item in self.kLineData) { + if ([item isKindOfClass:[StockKLineModel class]]) { + StockKLineModel *model = (StockKLineModel *)item; + maxPrice = MAX(maxPrice, model.high); + minPrice = MIN(minPrice, model.low); + } else if ([item isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)item; + maxPrice = MAX(maxPrice, [dict[@"high"] floatValue]); + minPrice = MIN(minPrice, [dict[@"low"] floatValue]); + } + } + maxPrice = maxPrice + (maxPrice - minPrice) * 0.1; + minPrice = minPrice - (maxPrice - minPrice) * 0.1; + CGFloat priceRange = maxPrice - minPrice; + + // 绘制K线 + for (NSInteger i = 0; i < self.kLineData.count; i++) { + CGFloat open = 0, high = 0, low = 0, close = 0; + + if ([self.kLineData[i] isKindOfClass:[StockKLineModel class]]) { + StockKLineModel *model = (StockKLineModel *)self.kLineData[i]; + open = model.open; + high = model.high; + low = model.low; + close = model.close; + } else if ([self.kLineData[i] isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)self.kLineData[i]; + open = [dict[@"open"] floatValue]; + high = [dict[@"high"] floatValue]; + low = [dict[@"low"] floatValue]; + close = [dict[@"close"] floatValue]; + } + + // 坐标转换 + CGFloat yOpen = chartHeight * (maxPrice - open) / priceRange; + CGFloat yHigh = chartHeight * (maxPrice - high) / priceRange; + CGFloat yLow = chartHeight * (maxPrice - low) / priceRange; + CGFloat yClose = chartHeight * (maxPrice - close) / priceRange; + + // 计算X坐标 + CGFloat xPosition = space/2 + kLineUnitWidth * i; + + // 绘制K线实体 + UIView *bodyView = [[UIView alloc] init]; + bodyView.backgroundColor = (close >= open) ? [UIColor greenColor] : [UIColor redColor]; + bodyView.frame = CGRectMake( + xPosition, + MIN(yOpen, yClose), + kLineWidth, + MAX(1.0, fabs(yClose - yOpen)) + ); + [self.kLineScrollView addSubview:bodyView]; + + // 绘制影线 + UIView *shadowView = [[UIView alloc] init]; + shadowView.backgroundColor = bodyView.backgroundColor; + shadowView.frame = CGRectMake( + bodyView.center.x - 0.5, + yHigh, + 1, + yLow - yHigh + ); + [self.kLineScrollView addSubview:shadowView]; + } + + // 日期刻度 + for (UILabel *label in self.dateLabels) { + [label removeFromSuperview]; + } + + NSMutableArray *dateLabelArr = [NSMutableArray array]; + NSInteger dateInterval = 10; + + for (NSInteger i = 0; i < self.kLineData.count; i += dateInterval) { + NSString *dateStr = @""; + if ([self.kLineData[i] isKindOfClass:[StockKLineModel class]]) { + StockKLineModel *model = (StockKLineModel *)self.kLineData[i]; + dateStr = model.date; + } else if ([self.kLineData[i] isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)self.kLineData[i]; + dateStr = dict[@"date"]; + } + UILabel *label = [[UILabel alloc] init]; + label.text = dateStr; + label.textColor = [UIColor lightGrayColor]; + label.font = [UIFont systemFontOfSize:10]; + label.translatesAutoresizingMaskIntoConstraints = YES; + + CGFloat xCenter = kLineUnitWidth * (i + 0.5); + [label sizeToFit]; + + label.frame = CGRectMake( + xCenter - label.bounds.size.width / 2, + chartHeight - 15, + label.bounds.size.width, + label.bounds.size.height + ); + + [self.kLineScrollView addSubview:label]; + [dateLabelArr addObject:label]; + } + self.dateLabels = dateLabelArr; + + NSLog(@"ScrollView Bounds Width: %f", self.kLineScrollView.bounds.size.width); + NSLog(@"Content Size Width: %f", self.kLineScrollView.contentSize.width); + + if (self.kLineScrollView.contentSize.width <= self.kLineScrollView.bounds.size.width) { + NSLog(@"⚠️ 警告:ContentSize 不够大,无法滑动。"); + } +} + +#pragma mark - Mock Data +- (void) setupData{ + self.kLineData = @[ + @{@"date":@"2025/11/18", @"open":@1620.0, @"high":@1643.0, @"low":@1605.0, @"close":@1630.0, @"volume":@2.5}, + @{@"date":@"2025/11/19", @"open":@1630.0, @"high":@1635.0, @"low":@1615.0, @"close":@1620.0, @"volume":@2.2}, + @{@"date":@"2025/11/20", @"open":@1620.0, @"high":@1628.0, @"low":@1608.0, @"close":@1615.0, @"volume":@1.8}, + @{@"date":@"2025/11/21", @"open":@1615.0, @"high":@1625.0, @"low":@1610.0, @"close":@1622.0, @"volume":@2.0}, + @{@"date":@"2025/11/22", @"open":@1622.0, @"high":@1630.0, @"low":@1618.0, @"close":@1625.0, @"volume":@2.3}, + @{@"date":@"2025/11/25", @"open":@1625.0, @"high":@1632.0, @"low":@1620.0, @"close":@1628.0, @"volume":@1.9}, + @{@"date":@"2025/11/26", @"open":@1628.0, @"high":@1635.0, @"low":@1622.0, @"close":@1630.0, @"volume":@2.1}, + @{@"date":@"2025/11/27", @"open":@1630.0, @"high":@1638.0, @"low":@1625.0, @"close":@1628.0, @"volume":@2.4}, + @{@"date":@"2025/11/28", @"open":@1628.0, @"high":@1632.0, @"low":@1609.0, @"close":@1610.0, @"volume":@2.6}, + @{@"date":@"2025/11/29", @"open":@1610.0, @"high":@1620.0, @"low":@1608.0, @"close":@1615.0, @"volume":@1.7} + ]; +} + +- (void)generateMockData { + NSMutableArray *arr = [NSMutableArray array]; + CGFloat lastClose = 100.0; + NSLog(@"生成模拟数据中。。。"); + + // 生成200条数据(减少数量,避免contentSize过大) + for (int i = 0; i < 200; i++) { + StockKLineModel *model = [[StockKLineModel alloc] init]; + + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:-(200 - i) * 24 * 3600]; + NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; + [fmt setDateFormat:@"MM-dd"]; + model.date = [fmt stringFromDate:date]; + + // 价格生成逻辑 + CGFloat volatility = lastClose * 0.02; + CGFloat randomChange = ((arc4random() % 100) / 100.0 - 0.5) * 2 * volatility; + + model.open = lastClose + ((arc4random() % 100) / 100.0 - 0.5) * volatility * 0.5; + model.close = model.open + randomChange; + + CGFloat maxOC = MAX(model.open, model.close); + CGFloat minOC = MIN(model.open, model.close); + + model.high = maxOC + (arc4random() % 100) / 100.0 * 1.0; + model.low = minOC - (arc4random() % 100) / 100.0 * 1.0; + + // 成交量生成逻辑 + CGFloat baseVolume = 1000000.0; + CGFloat randomVolFactor = (arc4random() % 200) / 100.0 + 0.5; + + if (fabs(model.close - model.open) / model.open > 0.03) { + randomVolFactor *= 1.5; + } + + model.volume = baseVolume * randomVolFactor; + + if (model.low < 0) model.low = 0.01; + + [arr addObject:model]; + + lastClose = model.close; + } + + NSLog(@"生成模拟数据完毕,共%ld条", arr.count); + + self.kLineData = arr; +} + +@end diff --git a/HC/CommonTabBar.h b/HC/CommonTabBar.h new file mode 100644 index 0000000..11a496f --- /dev/null +++ b/HC/CommonTabBar.h @@ -0,0 +1,19 @@ +// +// CommonTabBar.h +// HC +// +// Created by huilinLi on 2025/11/25. +// + +#import + +@protocol CommonTabBarDelegate +- (void)tabBarDidSelectIndex:(NSInteger)index; +@end + +@interface CommonTabBar : UIView +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) NSInteger selectedIndex; // 当前选中的索引 + +- (instancetype)initWithTabItems:(NSArray *)tabItems; +@end diff --git a/HC/CommonTabBar.m b/HC/CommonTabBar.m new file mode 100644 index 0000000..4c9a9b3 --- /dev/null +++ b/HC/CommonTabBar.m @@ -0,0 +1,94 @@ +// +// CommonTabBar.m +// HC +// +// Created by huilinLi on 2025/11/25. +// + +#import "CommonTabBar.h" + +@interface CommonTabBar () +@property (nonatomic, strong) NSArray *tabButtons; +@end + +@implementation CommonTabBar + +- (instancetype)initWithTabItems:(NSArray *)tabItems { + self = [super init]; + if (self) { + self.backgroundColor = [UIColor blackColor]; + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setupTabButtonsWithItems:tabItems]; + } + return self; +} + +- (void)setupTabButtonsWithItems:(NSArray *)tabItems { + NSMutableArray *buttons = [NSMutableArray array]; + + for (NSInteger i = 0; i < tabItems.count; i++) { + NSDictionary *item = tabItems[i]; + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + + UIButtonConfiguration *config = [UIButtonConfiguration plainButtonConfiguration]; + config.image = [UIImage systemImageNamed:item[@"icon"] ?: @""]; + config.title = item[@"title"]; + config.imagePlacement = NSDirectionalRectEdgeTop; + config.imagePadding = 5; + btn.configuration = config; + + BOOL selected = [item[@"selected"] boolValue]; + btn.tintColor = selected ? [UIColor blueColor] : [UIColor whiteColor]; + btn.titleLabel.font = [UIFont systemFontOfSize:10]; + btn.tag = i; + + [btn addTarget:self action:@selector(tabButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + + [self addSubview:btn]; + [buttons addObject:btn]; + } + + self.tabButtons = buttons; + [self setupTabButtonConstraints]; +} + +- (void)setupTabButtonConstraints { + for (NSInteger i = 0; i < self.tabButtons.count; i++) { + UIButton *btn = self.tabButtons[i]; + btn.translatesAutoresizingMaskIntoConstraints = NO; + + [NSLayoutConstraint activateConstraints:@[ + [btn.widthAnchor constraintEqualToAnchor:self.widthAnchor multiplier:1.0/self.tabButtons.count], + [btn.heightAnchor constraintEqualToAnchor:self.heightAnchor], + [btn.centerYAnchor constraintEqualToAnchor:self.centerYAnchor], + + (i == 0) ? [btn.leadingAnchor constraintEqualToAnchor:self.leadingAnchor] : + [btn.leadingAnchor constraintEqualToAnchor:self.tabButtons[i-1].trailingAnchor], + ]]; + } + + // TabBar自身高度 + [self.heightAnchor constraintEqualToConstant:60].active = YES; +} + +- (void)tabButtonTapped:(UIButton *)sender { + self.selectedIndex = sender.tag; + + for (UIButton *btn in self.tabButtons) { + btn.tintColor = (btn.tag == sender.tag) ? [UIColor blueColor] : [UIColor whiteColor]; + } + + if ([self.delegate respondsToSelector:@selector(tabBarDidSelectIndex:)]) { + [self.delegate tabBarDidSelectIndex:sender.tag]; + } +} + +// 外部设置选中索引时更新样式 +- (void)setSelectedIndex:(NSInteger)selectedIndex { + _selectedIndex = selectedIndex; + for (UIButton *btn in self.tabButtons) { + btn.tintColor = (btn.tag == selectedIndex) ? [UIColor blueColor] : [UIColor whiteColor]; + } +} + +@end diff --git a/HC/CountryModel.h b/HC/CountryModel.h new file mode 100644 index 0000000..0be93f9 --- /dev/null +++ b/HC/CountryModel.h @@ -0,0 +1,18 @@ +// +// CountryModel.h +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import +@interface CountryModel : NSObject +@property (nonatomic, copy) NSString *code; // 国家代码 +@property (nonatomic, copy) NSString *name; // 国家名称 +@property (nonatomic, copy) NSString *vcClassName; // 子控制器名称 + ++ (instancetype)modelWithCode:(NSString *)code + name:(NSString *)name + vcClassName:(NSString *)vcClassName; +@end + diff --git a/HC/CountryModel.m b/HC/CountryModel.m new file mode 100644 index 0000000..2f9e88f --- /dev/null +++ b/HC/CountryModel.m @@ -0,0 +1,20 @@ +// +// CountryModel.m +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import "CountryModel.h" + +@implementation CountryModel ++ (instancetype)modelWithCode:(NSString *)code + name:(NSString *)name + vcClassName:(NSString *)vcClassName { + CountryModel *model = [[self alloc] init]; + model.code = code; + model.name = name; + model.vcClassName = vcClassName; + return model; +} +@end diff --git a/HC/HomeViewController.h b/HC/HomeViewController.h new file mode 100644 index 0000000..6d503ce --- /dev/null +++ b/HC/HomeViewController.h @@ -0,0 +1,45 @@ +// +// HomeViewController.h +// HC +// +// Created by huilinLi on 2025/11/18. +// + +#import +#import "CommonTabBar.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface HomeViewController : UIViewController + +@property (nonatomic, strong) UILabel *successLabel; +@property (nonatomic, strong) UITextField *searchField; +@property (nonatomic, strong) UIImageView *logoImage; +@property (nonatomic, strong) UIImageView *flagIcon; +@property (nonatomic, strong) UIButton *messageBtn; +@property (nonatomic, strong) UIScrollView *functionScrollView; +@property (nonatomic, strong) NSMutableArray *functionBtns; +@property (nonatomic, strong) UIScrollView *bannerScrollView; +@property (nonatomic, strong) UIPageControl *bannerPageControl; +@property (nonatomic, strong) UIView *tabContainer; +@property (nonatomic, strong) UIButton *courseBtn; // 课程按钮 +@property (nonatomic, strong) UIButton *infoBtn; // 资讯按钮 +@property (nonatomic, strong) UIButton *activityBtn; // 活动按钮 +@property (nonatomic, strong) UIView *courseUnderline; // 课程下划线 +@property (nonatomic, strong) UIView *infoUnderline; // 资讯下划线 +@property (nonatomic, strong) UIView *activityUnderline;// 活动下划线 +@property (nonatomic, strong) UITableView *courseTableView; +// @property (nonatomic, strong) UIView *commonTabBar; +@property (nonatomic, strong) CommonTabBar *commonTabBar; +@property (nonatomic, strong) UIButton *homeTabBtn; +@property (nonatomic, strong) UIButton *marketTabBtn; +@property (nonatomic, strong) UIButton *favoritesTabBtn; +@property (nonatomic, strong) UIButton *mineTabBtn; +@property (nonatomic, strong) UIImageView *redPacketIcon; +@property (nonatomic, strong) NSArray *functionIcons; +@property (nonatomic, strong) NSArray *courseData; +@property (nonatomic, strong) NSTimer *bannerTimer; // 轮播图的定时器 +@property (nonatomic, assign) NSInteger currentBannerIndex; // 当前轮播页码 +@end + +NS_ASSUME_NONNULL_END diff --git a/HC/HomeViewController.m b/HC/HomeViewController.m new file mode 100644 index 0000000..6a2d6fd --- /dev/null +++ b/HC/HomeViewController.m @@ -0,0 +1,634 @@ +// +// HomeViewController.m +// HC +// +// Created by huilinLi on 2025/11/18. +// +#import +#import "HomeViewController.h" +#import "MyViewController.h" +#import "CommonTabBar.h" +#import "QuotationViewController.h" + + +@implementation HomeViewController + +- (void)viewDidLoad { + self.view.backgroundColor = [UIColor blackColor]; + + [self setupData]; + [self setupSubviews]; + [self setupConstraints]; + + [self selectButton:self.courseBtn];// 课程 +} + +-(void) setupSubviews{ + // 搜索框左边logo + _logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo"]]; + _logoImage.contentMode = UIViewContentModeScaleAspectFit;// 保持比例 + _logoImage.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_logoImage]; + + // 搜索框 + _searchField = [[UITextField alloc] init]; + _searchField.placeholder = @"股票名称/代码"; + NSAttributedString *placeholder = [[NSAttributedString alloc] initWithString:@"股票名称/代码" attributes:@{ + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + _searchField.attributedPlaceholder = placeholder; + _searchField.textColor = [UIColor whiteColor]; + _searchField.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + _searchField.layer.cornerRadius = 15; + _searchField.leftView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"magnifyingglass"]]; + _searchField.leftViewMode = UITextFieldViewModeAlways; + _searchField.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_searchField]; + + // 市场配置 + _flagIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"singapore_flag"]]; + _flagIcon.contentMode = UIViewContentModeScaleAspectFit; + _flagIcon.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_flagIcon]; + + // 消息 + _messageBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + UIButtonConfiguration *config = [UIButtonConfiguration plainButtonConfiguration]; + config.image = [UIImage systemImageNamed:@"message"]; + config.baseForegroundColor = [UIColor whiteColor]; + // 富文本 + NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:@"15" attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:10], + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + config.attributedTitle = attributedTitle; + config.imagePadding = -5; + config.contentInsets = NSDirectionalEdgeInsetsMake(0, 0, 0, 0);// 内容边距 + [_messageBtn setConfiguration:config]; + _messageBtn.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_messageBtn]; + + // 功能按钮数组初始化 + _functionBtns = [NSMutableArray array]; + for (NSDictionary *dict in _functionIcons) { + UIButtonConfiguration *config = [UIButtonConfiguration plainButtonConfiguration]; + + UIImage *logoImage = [UIImage imageNamed:@"logo"]; + UIGraphicsBeginImageContextWithOptions(CGSizeMake(40, 40), NO, 0);// 开启图形上下文,((尺寸,尺寸),是否不透明,缩放因子) + [logoImage drawInRect:CGRectMake(0, 0, 40, 40)];// 调整,等比缩放 + UIImage *resizedLogo = UIGraphicsGetImageFromCurrentImageContext();// 获得调整后的 + UIGraphicsEndImageContext();// 关闭图形上下文 + + config.image = resizedLogo; + // 按钮文字,富文本 + NSAttributedString *titleAttr = [[NSAttributedString alloc] initWithString:dict[@"title"] attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:13], + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + config.attributedTitle = titleAttr; + config.imagePlacement = NSDirectionalRectEdgeTop; + config.imagePadding = 5; + config.baseForegroundColor = [UIColor whiteColor]; + + UIButton *btn = [UIButton buttonWithConfiguration:config primaryAction:nil]; + btn.titleLabel.font = [UIFont systemFontOfSize:12]; + btn.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:btn]; + [_functionBtns addObject:btn]; + } + + // 轮播图视图 + _bannerScrollView = [[UIScrollView alloc] init]; + _bannerScrollView.showsHorizontalScrollIndicator = NO;// 隐藏水平滚动条 + _bannerScrollView.pagingEnabled = YES;// 分页 + _bannerScrollView.delegate = self; + _bannerScrollView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_bannerScrollView]; + + // 轮播图内容容器 + UIView *bannerContentView = [[UIView alloc] init]; + bannerContentView.translatesAutoresizingMaskIntoConstraints = NO; + [_bannerScrollView addSubview:bannerContentView]; + + // 轮播图片 + NSArray *bannerImageNames = @[@"banner2", @"banner1", @"banner2", @"banner1"]; + NSMutableArray *bannerImages = [NSMutableArray array]; + + for (int i = 0; i < bannerImageNames.count; i++) { + UIImageView *bannerImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:bannerImageNames[i]]]; + bannerImage.contentMode = UIViewContentModeScaleAspectFill;// 填充 + bannerImage.clipsToBounds = YES;// 裁剪超出的 + bannerImage.translatesAutoresizingMaskIntoConstraints = NO; + [bannerContentView addSubview:bannerImage]; + [bannerImages addObject:bannerImage]; + + [bannerImage.heightAnchor constraintEqualToAnchor:bannerContentView.heightAnchor].active = YES; + [bannerImage.widthAnchor constraintEqualToAnchor:self.view.widthAnchor].active = YES; + + if (i == 0) { + [bannerImage.leadingAnchor constraintEqualToAnchor:bannerContentView.leadingAnchor].active = YES; + } else { + UIImageView *prevImage = bannerImages[i-1]; + [bannerImage.leadingAnchor constraintEqualToAnchor:prevImage.trailingAnchor].active = YES; + } + } + + // 内容视图宽度(总图片数 * 屏幕宽度) + [bannerContentView.widthAnchor constraintEqualToConstant:self.view.bounds.size.width * bannerImages.count].active = YES; + + [NSLayoutConstraint activateConstraints:@[ + [bannerContentView.leadingAnchor constraintEqualToAnchor:_bannerScrollView.leadingAnchor], + [bannerContentView.trailingAnchor constraintEqualToAnchor:_bannerScrollView.trailingAnchor], + [bannerContentView.topAnchor constraintEqualToAnchor:_bannerScrollView.topAnchor], + [bannerContentView.bottomAnchor constraintEqualToAnchor:_bannerScrollView.bottomAnchor], + [bannerContentView.heightAnchor constraintEqualToAnchor:_bannerScrollView.heightAnchor], + ]]; + + // 初始第一张 + [_bannerScrollView setContentOffset:CGPointMake(self.view.bounds.size.width, 0) animated:NO]; + + // 页码 + _bannerPageControl = [[UIPageControl alloc] init]; + _bannerPageControl.currentPageIndicatorTintColor = [UIColor blueColor]; + _bannerPageControl.pageIndicatorTintColor = [UIColor lightGrayColor];// 其他页码 + _bannerPageControl.numberOfPages = 2; + _bannerPageControl.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_bannerPageControl]; + + // 初始化定时器(2秒一切) + _bannerTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(autoScrollBanner) userInfo:nil repeats:YES]; + [[NSRunLoop mainRunLoop] addTimer:_bannerTimer forMode:NSRunLoopCommonModes]; + _currentBannerIndex = 0; + + // 课程咨询活动的容器 + self.tabContainer = [[UIView alloc] init]; + self.tabContainer.backgroundColor = [UIColor blackColor]; + self.tabContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.tabContainer]; + + // 课程 + _courseBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [_courseBtn setTitle:@"课程" forState:UIControlStateNormal]; + _courseBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + [_courseBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + [_courseBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + _courseBtn.backgroundColor = [UIColor blackColor]; + //[_courseBtn setBackgroundColor:[UIColor blackColor]]; + [_courseBtn addTarget:self action:@selector(tabButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + _courseBtn.tag = 100; + _courseBtn.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_courseBtn]; + + // 资讯 + _infoBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [_infoBtn setTitle:@"资讯" forState:UIControlStateNormal]; + _infoBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + //_infoBtn.backgroundColor = [UIColor blackColor]; + [_infoBtn setBackgroundColor:[UIColor blackColor]]; + [_infoBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + [_infoBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + [_infoBtn addTarget:self action:@selector(tabButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + _infoBtn.tag = 101; + _infoBtn.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_infoBtn]; + + // 活动 + _activityBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [_activityBtn setTitle:@"活动" forState:UIControlStateNormal]; + _activityBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + //_activityBtn.backgroundColor = [UIColor blackColor]; + [_activityBtn setBackgroundColor:[UIColor blackColor]]; + [_activityBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + [_activityBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected]; + [_activityBtn addTarget:self action:@selector(tabButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + _activityBtn.tag = 102; + _activityBtn.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_activityBtn]; + + // 课程下划线 + _courseUnderline = [[UIView alloc] init]; + _courseUnderline.backgroundColor = [UIColor blueColor]; + _courseUnderline.hidden = YES; + _courseUnderline.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_courseUnderline]; + + // 资讯下划线 + _infoUnderline = [[UIView alloc] init]; + _infoUnderline.backgroundColor = [UIColor blueColor]; + _infoUnderline.hidden = YES; + _infoUnderline.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_infoUnderline]; + + // 活动下划线 + _activityUnderline = [[UIView alloc] init]; + _activityUnderline.backgroundColor = [UIColor blueColor]; + _activityUnderline.hidden = YES; + _activityUnderline.translatesAutoresizingMaskIntoConstraints = NO; + [self.tabContainer addSubview:_activityUnderline]; + + // 课程列表TableView + _courseTableView = [[UITableView alloc] init]; + _courseTableView.backgroundColor = [UIColor blackColor]; + _courseTableView.separatorStyle = UITableViewCellSeparatorStyleNone;// 隐藏分割线 + [_courseTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CourseCell"]; + _courseTableView.delegate = self; + _courseTableView.dataSource = self;// 数据源 + _courseTableView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_courseTableView]; + + // 红包 + _redPacketIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo"]]; + _redPacketIcon.contentMode = UIViewContentModeScaleAspectFit; + _redPacketIcon.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_redPacketIcon]; + + NSArray *tabItems = @[ + @{@"title":@"首页", @"icon":@"house.fill", @"selected":@YES}, + @{@"title":@"行情", @"icon":@"chart.line.uptrend.xyaxis", @"selected":@NO}, + @{@"title":@"自选", @"icon":@"plus", @"selected":@NO}, + @{@"title":@"我的", @"icon":@"person", @"selected":@NO} + ]; + self.commonTabBar = [[CommonTabBar alloc] initWithTabItems:tabItems]; + self.commonTabBar.delegate = self; + [self.view addSubview:self.commonTabBar]; + + // 登录提示 + _successLabel = [[UILabel alloc] init]; + _successLabel.text = @"登录成功"; + _successLabel.font = [UIFont systemFontOfSize:20]; + _successLabel.textColor = [UIColor whiteColor]; + _successLabel.numberOfLines = 0; + _successLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_successLabel]; + + + // 标签容器和按钮约束 + [NSLayoutConstraint activateConstraints:@[ + // 标签容器,轮播图下15,左15,右15,高30 + [self.tabContainer.topAnchor constraintEqualToAnchor: _bannerScrollView.bottomAnchor constant:15], + [self.tabContainer.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor constant:15], + [self.tabContainer.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor constant:-15], + [self.tabContainer.heightAnchor constraintEqualToConstant:30], + + // 按钮均分宽度 + // 课程左齐容器,垂直居中,宽度1/3 + [_courseBtn.leadingAnchor constraintEqualToAnchor: self.tabContainer.leadingAnchor], + [_courseBtn.centerYAnchor constraintEqualToAnchor: self.tabContainer.centerYAnchor], + [_courseBtn.widthAnchor constraintEqualToAnchor: self.tabContainer.widthAnchor multiplier:1.0/3.0], + + // 咨询左对齐课程右侧 + [_infoBtn.leadingAnchor constraintEqualToAnchor: _courseBtn.trailingAnchor], + [_infoBtn.centerYAnchor constraintEqualToAnchor: self.tabContainer.centerYAnchor], + [_infoBtn.widthAnchor constraintEqualToAnchor: self.tabContainer.widthAnchor multiplier:1.0/3.0], + + // 活动左对齐咨询右侧 + [_activityBtn.leadingAnchor constraintEqualToAnchor: _infoBtn.trailingAnchor], + [_activityBtn.trailingAnchor constraintEqualToAnchor: self.tabContainer.trailingAnchor], + [_activityBtn.centerYAnchor constraintEqualToAnchor: self.tabContainer.centerYAnchor], + + // 下划线约束 + // 底部对齐容器,在button下方正中,宽30高2 + [_courseUnderline.bottomAnchor constraintEqualToAnchor: self.tabContainer.bottomAnchor], + [_courseUnderline.centerXAnchor constraintEqualToAnchor: _courseBtn.centerXAnchor], + [_courseUnderline.widthAnchor constraintEqualToConstant:30], + [_courseUnderline.heightAnchor constraintEqualToConstant:2], + + [_infoUnderline.bottomAnchor constraintEqualToAnchor: self.tabContainer.bottomAnchor], + [_infoUnderline.centerXAnchor constraintEqualToAnchor: _infoBtn.centerXAnchor], + [_infoUnderline.widthAnchor constraintEqualToConstant:30], + [_infoUnderline.heightAnchor constraintEqualToConstant:2], + + [_activityUnderline.bottomAnchor constraintEqualToAnchor: self.tabContainer.bottomAnchor], + [_activityUnderline.centerXAnchor constraintEqualToAnchor: _activityBtn.centerXAnchor], + [_activityUnderline.widthAnchor constraintEqualToConstant:30], + [_activityUnderline.heightAnchor constraintEqualToConstant:2], + ]]; +} + +-(void) setupConstraints{ + // 登录成功提示 + [NSLayoutConstraint activateConstraints:@[ + [_successLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],// 水平居中 + [_successLabel.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],// 垂直居中 + [_successLabel.widthAnchor constraintEqualToConstant:80], + [_successLabel.heightAnchor constraintEqualToConstant:30], + ]]; + + // Logo图标 搜索框高度下垂直居中,左边距15,宽40高40 + [NSLayoutConstraint activateConstraints:@[ + [_logoImage.centerYAnchor constraintEqualToAnchor: _searchField.centerYAnchor], + [_logoImage.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor constant:15], + [_logoImage.widthAnchor constraintEqualToConstant:40], + [_logoImage.heightAnchor constraintEqualToConstant:40], + ]]; + + // 搜索栏 父视图下50,logo左10,国旗左10,高30 + [NSLayoutConstraint activateConstraints:@[ + [_searchField.topAnchor constraintEqualToAnchor: self.view.topAnchor constant:50], + [_searchField.leadingAnchor constraintEqualToAnchor: _logoImage.trailingAnchor constant:10], + [_searchField.trailingAnchor constraintEqualToAnchor: _flagIcon.leadingAnchor constant:-10], + [_searchField.heightAnchor constraintEqualToConstant:30], + ]]; + + // 国旗图标 + [NSLayoutConstraint activateConstraints:@[ + [_flagIcon.centerYAnchor constraintEqualToAnchor: _searchField.centerYAnchor], + [_flagIcon.trailingAnchor constraintEqualToAnchor: _messageBtn.leadingAnchor constant:-10], + [_flagIcon.widthAnchor constraintEqualToConstant:40], + [_flagIcon.heightAnchor constraintEqualToConstant:40], + ]]; + + // 消息按钮 + [NSLayoutConstraint activateConstraints:@[ + [_messageBtn.centerYAnchor constraintEqualToAnchor: _searchField.centerYAnchor], + [_messageBtn.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor constant:-15], + [_messageBtn.widthAnchor constraintEqualToConstant:40], + [_messageBtn.heightAnchor constraintEqualToConstant:40], + ]]; + + // 功能按钮(两行四列,均匀占满整行) + for (int i = 0; i < _functionBtns.count; i++) { + UIButton *btn = _functionBtns[i]; + NSLayoutConstraint *topConstraint; + NSLayoutConstraint *widthConstraint = [btn.widthAnchor constraintEqualToAnchor: self.view.widthAnchor multiplier:0.25 constant:-15]; + NSLayoutConstraint *heightConstraint = [btn.heightAnchor constraintEqualToConstant:70]; + + if (i < 4) { + topConstraint = [btn.topAnchor constraintEqualToAnchor: _searchField.bottomAnchor constant:20]; + NSLayoutConstraint *leadingConstraint; + if (i == 0) { + leadingConstraint = [btn.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor constant:15]; + } else { + leadingConstraint = [btn.leadingAnchor constraintEqualToAnchor: _functionBtns[i-1].trailingAnchor constant:0]; + } + [NSLayoutConstraint activateConstraints:@[topConstraint, leadingConstraint, widthConstraint, heightConstraint]]; + } else { + topConstraint = [btn.topAnchor constraintEqualToAnchor: _functionBtns[i-4].bottomAnchor constant:10]; + NSLayoutConstraint *leadingConstraint; + if (i == 4) { + leadingConstraint = [btn.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor constant:15]; + } else { + leadingConstraint = [btn.leadingAnchor constraintEqualToAnchor: _functionBtns[i-1].trailingAnchor constant:0]; + } + [NSLayoutConstraint activateConstraints:@[topConstraint, leadingConstraint, widthConstraint, heightConstraint]]; + } + } + + // 轮播图ScrollView 顶部距离最后一个功能按钮20,左右对齐父视图,高150 + [NSLayoutConstraint activateConstraints:@[ + [_bannerScrollView.topAnchor constraintEqualToAnchor: _functionBtns.lastObject.bottomAnchor constant:20], + [_bannerScrollView.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor], + [_bannerScrollView.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor], + [_bannerScrollView.heightAnchor constraintEqualToConstant:150], + ]]; + + // 轮播图PageControl,底部距离轮播图5 + [NSLayoutConstraint activateConstraints:@[ + [_bannerPageControl.bottomAnchor constraintEqualToAnchor: _bannerScrollView.bottomAnchor constant:-5], + [_bannerPageControl.centerXAnchor constraintEqualToAnchor: self.view.centerXAnchor], + ]]; + + // 课程列表 顶部距离标签容器20,左右对齐父视图,底部tabBar + [NSLayoutConstraint activateConstraints:@[ + [_courseTableView.topAnchor constraintEqualToAnchor: self.tabContainer.bottomAnchor constant:20], + [_courseTableView.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor], + [_courseTableView.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor], + [_courseTableView.bottomAnchor constraintEqualToAnchor: _commonTabBar.topAnchor] + ]]; + + // 红包图标 + [NSLayoutConstraint activateConstraints:@[ + [_redPacketIcon.bottomAnchor constraintEqualToAnchor: _courseTableView.bottomAnchor constant:-200], + [_redPacketIcon.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor constant:-20], + [_redPacketIcon.widthAnchor constraintEqualToConstant:60], + [_redPacketIcon.heightAnchor constraintEqualToConstant:60], + ]]; + + // 底部页面按钮 底部对齐安全区域,左右对齐父视图 + [_commonTabBar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor].active = YES; + [_commonTabBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES; + [_commonTabBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES; +} + +- (void)setupData { + _functionIcons = @[// 先都用logo + @{@"title":@"全球指数"}, + @{@"title":@"浏览历史"}, + @{@"title":@"机构"}, + @{@"title":@"弘历学堂"}, + @{@"title":@"自选"}, + @{@"title":@"商店"}, + @{@"title":@"猎庄选股"}, + @{@"title":@"智能机器人"} + ]; + + _courseData = @[ + @{@"cover":@"course1", @"title":@"John Lu & Robert Xu “发财线”课程回顾!", @"lecturer":@"Homily Lecturer"}, + @{@"cover":@"event2", @"title":@"孩子炒股老亏钱,多半是废了", @"lecturer":@"kaslana"}, + @{@"cover":@"course3", @"title":@"论持久战", @"lecturer":@"教员先生"} + ]; +} + +#pragma mark - 标签方法 +- (void)tabButtonTapped:(UIButton *)sender { + [self selectButton:sender]; + + // 根据标签切换 + switch (sender.tag) { + case 100: + _courseData = @[ + @{@"cover":@"course1", @"title":@"John Lu & Robert Xu “发财线”课程回顾!", @"lecturer":@"Homily Lecturer"}, + @{@"cover":@"event2", @"title":@"孩子炒股老亏钱,多半是废了", @"lecturer":@"kaslana"}, + @{@"cover":@"course3", @"title":@"论持久战", @"lecturer":@"教员先生"} + ]; + break; + + case 101: + _courseData = @[ + @{@"cover":@"news1", @"title":@"objective-c从入门到入土", @"lecturer":@"财经资讯"}, + @{@"cover":@"news2", @"title":@"线程池核心参数详解", @"lecturer":@"财经资讯"}, + @{@"cover":@"news3", @"title":@"redis集群-主从、哨兵、分片", @"lecturer":@"财经资讯"} + ]; + break; + + case 102: + _courseData = @[ + @{@"cover":@"event1", @"title":@"SpringCloud入门到放弃", @"lecturer":@"活动预告"}, + @{@"cover":@"event2", @"title":@"孩子炒股老亏钱,多半是废了", @"lecturer":@"活动预告"}, + @{@"cover":@"event3", @"title":@"mySQL:从删库到跑路", @"lecturer":@"活动预告"} + ]; + break; + } + + [_courseTableView reloadData]; +} + +- (void) pushMine { + MyViewController *myViewController = [[MyViewController alloc] init]; + [self.navigationController pushViewController:myViewController animated:YES]; +} + +- (void)selectButton:(UIButton *)selectedButton { + _courseBtn.selected = NO; + _infoBtn.selected = NO; + _activityBtn.selected = NO; + + _courseBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + _infoBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + _activityBtn.titleLabel.font = [UIFont systemFontOfSize:14]; + + _courseUnderline.hidden = YES; + _infoUnderline.hidden = YES; + _activityUnderline.hidden = YES; + + // 设置选中按钮状态 + selectedButton.selected = YES; + selectedButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + + // 显示对应下划线 + if (selectedButton == _courseBtn) { + _courseUnderline.hidden = NO; + } else if (selectedButton == _infoBtn) { + _infoUnderline.hidden = NO; + } else if (selectedButton == _activityBtn) { + _activityUnderline.hidden = NO; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + if (scrollView == _bannerScrollView) { + CGFloat screenWidth = self.view.bounds.size.width; + NSInteger currentOffsetX = scrollView.contentOffset.x; + NSInteger page = currentOffsetX / screenWidth; + + // 首尾拼接图无缝跳转 + if (page == 0) { + page = 2; + [scrollView setContentOffset:CGPointMake(screenWidth * page, 0) animated:NO]; + } else if (page == 3) { + page = 1; + [scrollView setContentOffset:CGPointMake(screenWidth * page, 0) animated:NO]; + } + + _currentBannerIndex = (page - 1) % 2; + _bannerPageControl.currentPage = _currentBannerIndex; + + // 重启定时器 + [_bannerTimer invalidate]; + _bannerTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 + target:self + selector:@selector(autoScrollBanner) + userInfo:nil + repeats:YES]; + } +} + +- (void)autoScrollBanner { + CGFloat screenWidth = self.view.bounds.size.width; + + // 直接基于真实索引计算下一页,避免contentOffset的延迟问题 + _currentBannerIndex = (_currentBannerIndex + 1) % 2; // 0→1→0循环 + NSInteger targetPage = _currentBannerIndex + 1; // 对应拼接后的页面(1/2) + + // 处理尾部拼接图的无缝跳转 + if (targetPage > 2) { + targetPage = 1; + [_bannerScrollView setContentOffset:CGPointMake(screenWidth * targetPage, 0) animated:NO]; + } + + [_bannerScrollView setContentOffset:CGPointMake(screenWidth * targetPage, 0) animated:YES]; + _bannerPageControl.currentPage = _currentBannerIndex; +} + +- (void) pushQuotation { + QuotationViewController *quotationViewController = [[QuotationViewController alloc] init]; + [self.navigationController pushViewController:quotationViewController animated:YES]; +} + +- (void)tabBarDidSelectIndex:(NSInteger)index { + if (index == 3) { + [self pushMine]; + } + else if (index == 0) { + + } + else if (index == 1) { + [self pushQuotation]; + } + else if (index == 2) { + // 自选 + } +} + +#pragma mark - 视图即将消失 +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [_bannerTimer invalidate];// 销毁定时器 + _bannerTimer = nil; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [UIView animateWithDuration:0.3 animations:^{ + self->_successLabel.alpha = 0; + } completion:^(BOOL finished) { + [self->_successLabel removeFromSuperview]; + }]; + }); +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _courseData.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CourseCell" forIndexPath:indexPath]; + cell.backgroundColor = [UIColor blackColor]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + + NSDictionary *course = _courseData[indexPath.row]; + UIImageView *coverView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:course[@"cover"]]]; + coverView.contentMode = UIViewContentModeScaleAspectFill; + coverView.clipsToBounds = YES; + coverView.frame = CGRectMake(15, 10, 140, 100); + [cell.contentView addSubview:coverView]; + + UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(170, 10, 220, 60)]; + titleLabel.text = course[@"title"]; + titleLabel.textColor = [UIColor whiteColor]; + titleLabel.font = [UIFont systemFontOfSize:14]; + titleLabel.numberOfLines = 3; + [cell.contentView addSubview:titleLabel]; + + UILabel *lecturerLabel = [[UILabel alloc] initWithFrame:CGRectMake(170, 75, 120, 30)]; + lecturerLabel.text = course[@"lecturer"]; + lecturerLabel.textColor = [UIColor lightGrayColor]; + lecturerLabel.font = [UIFont systemFontOfSize:14]; + [cell.contentView addSubview:lecturerLabel]; + + UIView *bottomLine = [[UIView alloc] init]; + bottomLine.backgroundColor = [UIColor lightGrayColor]; + bottomLine.translatesAutoresizingMaskIntoConstraints = NO; + [cell.contentView addSubview:bottomLine]; + + [NSLayoutConstraint activateConstraints:@[ + [bottomLine.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:20], // 左边距15 + [bottomLine.trailingAnchor constraintEqualToAnchor:cell.contentView.trailingAnchor constant:-20], // 右边距15 + [bottomLine.bottomAnchor constraintEqualToAnchor:cell.contentView.bottomAnchor], + [bottomLine.heightAnchor constraintEqualToConstant:0.2] + ]]; + + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 120; +} + +@end diff --git a/HC/MLXYViewController.h b/HC/MLXYViewController.h new file mode 100644 index 0000000..a752571 --- /dev/null +++ b/HC/MLXYViewController.h @@ -0,0 +1,16 @@ +// +// MLXYViewController.h +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MLXYViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/HC/MLXYViewController.m b/HC/MLXYViewController.m new file mode 100644 index 0000000..505923e --- /dev/null +++ b/HC/MLXYViewController.m @@ -0,0 +1,442 @@ +// +// MLXYViewController.m +// HC +// +// Created by huilinLi on 2025/11/26. +// +#import "MLXYViewController.h" +#import "ChartViewController.h" + +@interface MLXYViewController () +@property (nonatomic, strong) UIButton *mlxyButton; +// 大盘指数 +@property (nonatomic, strong) UILabel *marketTitleLabel; +@property (nonatomic, strong) UIView *marketView; +@property (nonatomic, strong) UILabel *marketLine1; +@property (nonatomic, strong) UILabel *marketLine2; +@property (nonatomic, strong) UILabel *marketLine3; +// 板块 +@property (nonatomic, strong) UILabel *sectorTitleLabel; +@property (nonatomic, strong) UIButton *sectorBtn; +// 三个板块卡片(分别配置) +@property (nonatomic, strong) UIView *sectorCard1; +@property (nonatomic, strong) UIView *sectorCard2; +@property (nonatomic, strong) UIView *sectorCard3; +// 股票 +@property (nonatomic, strong) UIView *stockContainer; +@property (nonatomic, strong) UITableView *stockTableView; +// 股票表头 +@property (nonatomic, strong) UIView *stockHeaderView; +// 按钮配置 +@property (nonatomic, strong) UIButtonConfiguration *buttonConfig; +// 板块数据配置 +@property (nonatomic, strong) NSArray *sectorDataConfig; +@end + +@implementation MLXYViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + + [self setupButtonConfig]; + [self setupSectorDataConfig]; + + [self setupSubviews]; + [self setupConstraints]; + + [self marketViewClick]; +} + +-(void) marketViewClick{ + _marketView.userInteractionEnabled = YES; + UITapGestureRecognizer *click = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(marketViewPush)]; + [_marketView addGestureRecognizer:click]; +} + +-(void) marketViewPush{ + ChartViewController *chartViewController = [[ChartViewController alloc] init]; + [self.navigationController pushViewController:chartViewController animated:YES]; +} + +- (void)setupButtonConfig { + UIButtonConfiguration *config = [UIButtonConfiguration plainButtonConfiguration]; + config.title = @"更多"; + config.attributedTitle = [[NSAttributedString alloc] initWithString:@"更多" attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:14], + NSForegroundColorAttributeName: [UIColor lightGrayColor] + }]; + + UIImage *image = [[UIImage systemImageNamed:@"chevron.right"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + config.image = image; + config.imagePlacement = NSDirectionalRectEdgeTrailing; // 图片在文字右侧 + config.imagePadding = 1; + + config.baseForegroundColor = [UIColor lightGrayColor]; + + _buttonConfig = config; +} + +- (void)setupSectorDataConfig { + _sectorDataConfig = @[ + @{@"name":@"Health", @"value1":@"1099.683", @"value2":@"27.236",@"value3":@"2.270%"}, + @{@"name":@"Others", @"value1":@"2083.783", @"value2":@"0.000",@"value3":@"0.000%"}, + @{@"name":@"HLKLI", @"value1":@"987.895", @"value2":@"-1.854",@"value3":@"-0.230%"} + ]; +} + +- (void)setupSubviews { + // 马来西亚按钮 + _mlxyButton = [UIButton buttonWithType:UIButtonTypeSystem]; + [_mlxyButton setTitle:@"马来西亚" forState:UIControlStateNormal]; + [_mlxyButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [_mlxyButton setBackgroundColor:[UIColor blueColor]]; + _mlxyButton.layer.cornerRadius = 15; + _mlxyButton.titleLabel.font = [UIFont systemFontOfSize:14]; + _mlxyButton.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_mlxyButton]; + + // 大盘指数 + _marketTitleLabel = [[UILabel alloc] init]; + _marketTitleLabel.text = @"大盘指数"; + _marketTitleLabel.textColor = [UIColor whiteColor]; + _marketTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _marketTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_marketTitleLabel]; + + // 绿色卡片 + _marketView = [[UIView alloc] init]; + _marketView.backgroundColor = [UIColor greenColor]; + _marketView.layer.cornerRadius = 8; + _marketView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_marketView]; + + _marketLine1 = [[UILabel alloc] init]; + _marketLine1.text = @"富时马来西亚KLCI"; + _marketLine1.textColor = [UIColor whiteColor]; + _marketLine1.font = [UIFont fontWithName:@"Helvetica-Bold" size:12]; + _marketLine1.textAlignment = NSTextAlignmentCenter; + _marketLine1.translatesAutoresizingMaskIntoConstraints = NO; + [_marketView addSubview:_marketLine1]; + + _marketLine2 = [[UILabel alloc] init]; + _marketLine2.text = @"1624.500"; + _marketLine2.textColor = [UIColor whiteColor]; + _marketLine2.font = [UIFont boldSystemFontOfSize:17]; + _marketLine2.textAlignment = NSTextAlignmentCenter; + _marketLine2.translatesAutoresizingMaskIntoConstraints = NO; + [_marketView addSubview:_marketLine2]; + + _marketLine3 = [[UILabel alloc] init]; + _marketLine3.text = @"12.760 0.792%"; + _marketLine3.textColor = [UIColor whiteColor]; + _marketLine3.font = [UIFont boldSystemFontOfSize:12]; + _marketLine3.textAlignment = NSTextAlignmentCenter; + _marketLine3.translatesAutoresizingMaskIntoConstraints = NO; + [_marketView addSubview:_marketLine3]; + + // 板块 + _sectorTitleLabel = [[UILabel alloc] init]; + _sectorTitleLabel.text = @"板块"; + _sectorTitleLabel.textColor = [UIColor whiteColor]; + _sectorTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + _sectorTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_sectorTitleLabel]; + + _sectorBtn = [UIButton buttonWithConfiguration:self.buttonConfig primaryAction:nil]; + _sectorBtn.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_sectorBtn]; + + _sectorCard1 = [self createSectorCardWithData:self.sectorDataConfig[0]]; + [self.view addSubview:_sectorCard1]; + + _sectorCard2 = [self createSectorCardWithData:self.sectorDataConfig[1]]; + [self.view addSubview:_sectorCard2]; + + _sectorCard3 = [self createSectorCardWithData:self.sectorDataConfig[2]]; + [self.view addSubview:_sectorCard3]; + + // 股票容器 + _stockContainer = [[UIView alloc] init]; + _stockContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_stockContainer]; + + UILabel *stockTitleLabel = [[UILabel alloc] init]; + stockTitleLabel.text = @"股票"; + stockTitleLabel.textColor = [UIColor whiteColor]; + stockTitleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + stockTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_stockContainer addSubview:stockTitleLabel]; + + UIButton *stockBtn = [UIButton buttonWithConfiguration:self.buttonConfig primaryAction:nil]; + stockBtn.translatesAutoresizingMaskIntoConstraints = NO; + [_stockContainer addSubview:stockBtn]; + + // 股票列表表头 + _stockHeaderView = [[UIView alloc] init]; + _stockHeaderView.backgroundColor = [UIColor blackColor]; + _stockHeaderView.translatesAutoresizingMaskIntoConstraints = NO; + [_stockContainer addSubview:_stockHeaderView]; + + NSArray *headerTitles = @[@"名称", @"最新", @"涨幅"]; + for (NSInteger i = 0; i < headerTitles.count; i++) { + UILabel *headerLabel = [[UILabel alloc] init]; + headerLabel.text = headerTitles[i]; + headerLabel.textColor = [UIColor lightGrayColor]; + headerLabel.font = [UIFont systemFontOfSize:12]; + headerLabel.textAlignment = (i == 0) ? NSTextAlignmentLeft : NSTextAlignmentRight; + headerLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_stockHeaderView addSubview:headerLabel]; + + if (i == 0) { + [headerLabel.leadingAnchor constraintEqualToAnchor:_stockHeaderView.leadingAnchor constant:15].active = YES; + } else if (i == 1) { + [headerLabel.widthAnchor constraintEqualToConstant:60].active = YES; + [headerLabel.trailingAnchor constraintEqualToAnchor:_stockHeaderView.trailingAnchor constant:-110].active = YES; + } else { + [headerLabel.widthAnchor constraintEqualToConstant:80].active = YES; + [headerLabel.trailingAnchor constraintEqualToAnchor:_stockHeaderView.trailingAnchor constant:-30].active = YES; + } + [headerLabel.centerYAnchor constraintEqualToAnchor:_stockHeaderView.centerYAnchor].active = YES; + } + + _stockTableView = [[UITableView alloc] init]; + _stockTableView.backgroundColor = [UIColor blackColor]; + _stockTableView.separatorStyle = UITableViewCellSeparatorStyleNone;// 隐藏单元格之间的分隔线 + //SingleLine 默认,1px的分割线 + _stockTableView.delegate = self; + _stockTableView.dataSource = self; + [_stockTableView registerClass:[UITableViewCell class]// 单元格复用类 + forCellReuseIdentifier:@"StockCell"];// 复用标识 + _stockTableView.translatesAutoresizingMaskIntoConstraints = NO; + [_stockContainer addSubview:_stockTableView]; +} + +- (UIView *)createSectorCardWithData:(NSDictionary *)data { + UIView *card = [[UIView alloc] init]; + card.backgroundColor = [UIColor darkGrayColor]; + card.layer.cornerRadius = 8; + card.translatesAutoresizingMaskIntoConstraints = NO; + + // 名称 + UILabel *nameLabel = [[UILabel alloc] init]; + nameLabel.text = data[@"name"]; + nameLabel.textColor = [UIColor whiteColor]; + nameLabel.font = [UIFont systemFontOfSize:14]; + nameLabel.translatesAutoresizingMaskIntoConstraints = NO; + [card addSubview:nameLabel]; + + // 数值 + UILabel *value1Label = [[UILabel alloc] init]; + value1Label.text = data[@"value1"]; + value1Label.textColor = [UIColor greenColor]; + value1Label.font = [UIFont systemFontOfSize:16 weight:UIFontWeightBold]; + value1Label.translatesAutoresizingMaskIntoConstraints = NO; + [card addSubview:value1Label]; + + // 涨幅 + UILabel *value2Label = [[UILabel alloc] init]; + value2Label.text = data[@"value2"]; + value2Label.textColor = [UIColor greenColor]; + value2Label.font = [UIFont systemFontOfSize:12]; + value2Label.translatesAutoresizingMaskIntoConstraints = NO; + [card addSubview:value2Label]; + + UILabel *value3Label = [[UILabel alloc] init]; + value3Label.text = data[@"value3"]; + value3Label.textColor = [UIColor greenColor]; + value3Label.font = [UIFont systemFontOfSize:12]; + value3Label.translatesAutoresizingMaskIntoConstraints = NO; + [card addSubview:value3Label]; + + [NSLayoutConstraint activateConstraints:@[ + [nameLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:7], + [nameLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:10], + + [value1Label.topAnchor constraintEqualToAnchor:nameLabel.bottomAnchor constant:10], + [value1Label.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:10], + + [value2Label.topAnchor constraintEqualToAnchor:value1Label.bottomAnchor constant:7], + [value2Label.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:10], + + [value3Label.topAnchor constraintEqualToAnchor:value2Label.bottomAnchor constant:6], + [value3Label.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:10] + ]]; + + return card; +} + +- (void)setupConstraints { + // 马来西亚按钮 + NSLayoutConstraint *btnTop = [_mlxyButton.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor]; + NSLayoutConstraint *btnLeft = [_mlxyButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:15]; + NSLayoutConstraint *btnWidth = [_mlxyButton.widthAnchor constraintEqualToConstant:90]; + NSLayoutConstraint *btnHeight = [_mlxyButton.heightAnchor constraintEqualToConstant:30]; + [NSLayoutConstraint activateConstraints:@[btnTop, btnLeft, btnWidth, btnHeight]]; + + // 大盘 + NSLayoutConstraint *marketTitleTop = [_marketTitleLabel.topAnchor constraintEqualToAnchor:_mlxyButton.bottomAnchor constant:10]; + NSLayoutConstraint *marketTitleLeft = [_marketTitleLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:15]; + [NSLayoutConstraint activateConstraints:@[marketTitleTop, marketTitleLeft]]; + + NSLayoutConstraint *marketCardTop = [_marketView.topAnchor constraintEqualToAnchor:_marketTitleLabel.bottomAnchor constant:10]; + NSLayoutConstraint *marketCardLeft = [_marketView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:15]; + NSLayoutConstraint *marketCardWidth = [_marketView.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:0.3]; + NSLayoutConstraint *marketCardHeight = [_marketView.heightAnchor constraintEqualToConstant:100]; + [NSLayoutConstraint activateConstraints:@[marketCardTop, marketCardLeft, marketCardWidth, marketCardHeight]]; + + NSLayoutConstraint *line1Top = [_marketLine1.topAnchor constraintEqualToAnchor:_marketView.topAnchor constant:10]; + NSLayoutConstraint *line1CenterX = [_marketLine1.centerXAnchor constraintEqualToAnchor:_marketView.centerXAnchor]; + + NSLayoutConstraint *line2Top = [_marketLine2.topAnchor constraintEqualToAnchor:_marketLine1.bottomAnchor constant:15]; + NSLayoutConstraint *line2CenterX = [_marketLine2.centerXAnchor constraintEqualToAnchor:_marketView.centerXAnchor]; + + NSLayoutConstraint *line3Top = [_marketLine3.topAnchor constraintEqualToAnchor:_marketLine2.bottomAnchor constant:12]; + NSLayoutConstraint *line3CenterX = [_marketLine3.centerXAnchor constraintEqualToAnchor:_marketView.centerXAnchor]; + + [NSLayoutConstraint activateConstraints:@[line1Top, line1CenterX, line2Top, line2CenterX, line3Top, line3CenterX]]; + + // 板块 + NSLayoutConstraint *sectorTitleTop = [_sectorTitleLabel.topAnchor constraintEqualToAnchor:_marketView.bottomAnchor constant:20]; + NSLayoutConstraint *sectorTitleLeft = [_sectorTitleLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:15]; + [NSLayoutConstraint activateConstraints:@[sectorTitleTop, sectorTitleLeft]]; + + NSLayoutConstraint *sectorBtnTop = [_sectorBtn.centerYAnchor constraintEqualToAnchor:_sectorTitleLabel.centerYAnchor]; + NSLayoutConstraint *sectorBtnRight = [_sectorBtn.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-15]; + [NSLayoutConstraint activateConstraints:@[sectorBtnTop, sectorBtnRight]]; + + NSLayoutConstraint *card1Top = [_sectorCard1.topAnchor constraintEqualToAnchor:_sectorTitleLabel.bottomAnchor constant:10]; + NSLayoutConstraint *card1Left = [_sectorCard1.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:8]; + NSLayoutConstraint *card1Width = [_sectorCard1.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:0.3]; + NSLayoutConstraint *card1Height = [_sectorCard1.heightAnchor constraintEqualToConstant:100]; + [NSLayoutConstraint activateConstraints:@[card1Top, card1Left, card1Width, card1Height]]; + + NSLayoutConstraint *card2Top = [_sectorCard2.topAnchor constraintEqualToAnchor:_sectorCard1.topAnchor]; + NSLayoutConstraint *card2Left = [_sectorCard2.leadingAnchor constraintEqualToAnchor:_sectorCard1.trailingAnchor constant:8]; + NSLayoutConstraint *card2Width = [_sectorCard2.widthAnchor constraintEqualToAnchor:_sectorCard1.widthAnchor]; + NSLayoutConstraint *card2Height = [_sectorCard2.heightAnchor constraintEqualToAnchor:_sectorCard1.heightAnchor]; + [NSLayoutConstraint activateConstraints:@[card2Top, card2Left, card2Width, card2Height]]; + + NSLayoutConstraint *card3Top = [_sectorCard3.topAnchor constraintEqualToAnchor:_sectorCard1.topAnchor]; + NSLayoutConstraint *card3Left = [_sectorCard3.leadingAnchor constraintEqualToAnchor:_sectorCard2.trailingAnchor constant:8]; + NSLayoutConstraint *card3Right = [_sectorCard3.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16]; + // *card3Width = [_sectorCard3.widthAnchor constraintEqualToAnchor:_sectorCard1.widthAnchor];都行 + NSLayoutConstraint *card3Height = [_sectorCard3.heightAnchor constraintEqualToAnchor:_sectorCard1.heightAnchor]; + [NSLayoutConstraint activateConstraints:@[card3Top, card3Left, card3Right, card3Height]]; + + // 股票容器 + NSLayoutConstraint *stockTop = [_stockContainer.topAnchor constraintEqualToAnchor:_sectorCard1.bottomAnchor constant:20]; + NSLayoutConstraint *stockLeft = [_stockContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor]; + NSLayoutConstraint *stockRight = [_stockContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor]; + NSLayoutConstraint *stockBottom = [_stockContainer.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]; + [NSLayoutConstraint activateConstraints:@[stockTop, stockLeft, stockRight, stockBottom]]; + + UILabel *stockTitleLabel = _stockContainer.subviews[0]; + UIButton *stockBtn = _stockContainer.subviews[1]; + + NSLayoutConstraint *stockTitleTop = [stockTitleLabel.topAnchor constraintEqualToAnchor:_stockContainer.topAnchor constant:15]; + NSLayoutConstraint *stockTitleLeft = [stockTitleLabel.leadingAnchor constraintEqualToAnchor:_stockContainer.leadingAnchor constant:15]; + + NSLayoutConstraint *stockBtnTop = [stockBtn.centerYAnchor constraintEqualToAnchor:stockTitleLabel.centerYAnchor]; + NSLayoutConstraint *stockBtnRight = [stockBtn.trailingAnchor constraintEqualToAnchor:_stockContainer.trailingAnchor constant:-15]; + + [NSLayoutConstraint activateConstraints:@[stockTitleTop, stockTitleLeft, stockBtnTop, stockBtnRight]]; + + // 股票表头 + NSLayoutConstraint *headerTop = [_stockHeaderView.topAnchor constraintEqualToAnchor:stockTitleLabel.bottomAnchor constant:10]; + NSLayoutConstraint *headerLeft = [_stockHeaderView.leadingAnchor constraintEqualToAnchor:_stockContainer.leadingAnchor]; + NSLayoutConstraint *headerRight = [_stockHeaderView.trailingAnchor constraintEqualToAnchor:_stockContainer.trailingAnchor]; + NSLayoutConstraint *headerHeight = [_stockHeaderView.heightAnchor constraintEqualToConstant:30]; + [NSLayoutConstraint activateConstraints:@[headerTop, headerLeft, headerRight, headerHeight]]; + + // 股票列表 + NSLayoutConstraint *tableTop = [_stockTableView.topAnchor constraintEqualToAnchor:_stockHeaderView.bottomAnchor]; + NSLayoutConstraint *tableLeft = [_stockTableView.leadingAnchor constraintEqualToAnchor:_stockContainer.leadingAnchor]; + NSLayoutConstraint *tableRight = [_stockTableView.trailingAnchor constraintEqualToAnchor:_stockContainer.trailingAnchor]; + NSLayoutConstraint *tableBottom = [_stockTableView.bottomAnchor constraintEqualToAnchor:_stockContainer.bottomAnchor]; + [NSLayoutConstraint activateConstraints:@[tableTop, tableLeft, tableRight, tableBottom]]; +} + +#pragma mark - UITableView +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 4; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StockCell" forIndexPath:indexPath]; + cell.backgroundColor = [UIColor blackColor]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + // 清空复用内容 + [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + NSArray *stocks = @[ + @{@"name":@"PEGASUS HEIGHTS BERHAD", @"code":@"4464", @"price":@"0.010", @"value2":@"100.000%"}, + @{@"name":@"SMTRACK BERHAD", @"code":@"0169", @"price":@"0.010", @"value2":@"100.000%"}, + @{@"name":@"TXCD BERHAD - ICPS 2020/2030", @"code":@"7145PA", @"price":@"0.020", @"value2":@"33.333%"}, + @{@"name":@"DNONCE TECHNOLOGY BHD", @"code":@"7114", @"price":@"0.040", @"value2":@"33.333%"} + ]; + NSDictionary *stock = stocks[indexPath.row]; + + // 名称 + UILabel *nameLabel = [[UILabel alloc] init]; + nameLabel.text = stock[@"name"]; + nameLabel.textColor = [UIColor whiteColor]; + nameLabel.font = [UIFont systemFontOfSize:14]; + nameLabel.numberOfLines = 1; + nameLabel.lineBreakMode = NSLineBreakByTruncatingTail; + nameLabel.translatesAutoresizingMaskIntoConstraints = NO; + [cell.contentView addSubview:nameLabel]; + + // 代码 + UILabel *codeLabel = [[UILabel alloc] init]; + codeLabel.text = stock[@"code"]; + codeLabel.textColor = [UIColor lightGrayColor]; + codeLabel.font = [UIFont systemFontOfSize:12]; + codeLabel.translatesAutoresizingMaskIntoConstraints = NO; + [cell.contentView addSubview:codeLabel]; + + // 价格 + UILabel *priceLabel = [[UILabel alloc] init]; + priceLabel.text = stock[@"price"]; + priceLabel.textColor = [UIColor greenColor]; + priceLabel.font = [UIFont systemFontOfSize:14]; + priceLabel.textAlignment = NSTextAlignmentRight; + priceLabel.translatesAutoresizingMaskIntoConstraints = NO; + [cell.contentView addSubview:priceLabel]; + + // 涨幅 + UILabel *value2Label = [[UILabel alloc] init]; + value2Label.text = stock[@"value2"]; + value2Label.textColor = [UIColor greenColor]; + value2Label.font = [UIFont systemFontOfSize:14]; + value2Label.textAlignment = NSTextAlignmentRight; + value2Label.translatesAutoresizingMaskIntoConstraints = NO; + [cell.contentView addSubview:value2Label]; + + // 约束 + [NSLayoutConstraint activateConstraints:@[ + [nameLabel.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:15], + [nameLabel.topAnchor constraintEqualToAnchor:cell.contentView.topAnchor constant:10], + [nameLabel.trailingAnchor constraintLessThanOrEqualToAnchor:priceLabel.leadingAnchor constant:-10], + + [codeLabel.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:15], + [codeLabel.topAnchor constraintEqualToAnchor:nameLabel.bottomAnchor constant:5], + + [priceLabel.widthAnchor constraintEqualToConstant:60], + [priceLabel.trailingAnchor constraintEqualToAnchor:value2Label.leadingAnchor constant:-10], + [priceLabel.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor], + + [value2Label.widthAnchor constraintEqualToConstant:80], + [value2Label.trailingAnchor constraintEqualToAnchor:cell.contentView.trailingAnchor constant:-15], + [value2Label.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor] + ]]; + + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return 60; +} + +@end diff --git a/HC/MyViewController.h b/HC/MyViewController.h new file mode 100644 index 0000000..569d5f2 --- /dev/null +++ b/HC/MyViewController.h @@ -0,0 +1,18 @@ +// +// MyViewController.h +// HC +// +// Created by huilinLi on 2025/11/25. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class CommonTabBar; + +@interface MyViewController : UIViewController +@property (nonatomic, strong) CommonTabBar *tabBar; +@property (nonatomic, strong) UIView *lastSettingItem; +@end +NS_ASSUME_NONNULL_END diff --git a/HC/MyViewController.m b/HC/MyViewController.m new file mode 100644 index 0000000..8c0be44 --- /dev/null +++ b/HC/MyViewController.m @@ -0,0 +1,390 @@ +// +// MyViewController.m +// HC +// +// Created by huilinLi on 2025/11/25. +// + +#import "MyViewController.h" +#import +#import "CommonTabBar.h" +#import "HomeViewController.h" +#import "ViewController.h" +#import "QuotationViewController.h" + +@implementation MyViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + + [self setupUI]; +} + +- (void)setupUI { + UIScrollView *scrollView = [[UIScrollView alloc] init]; + scrollView.translatesAutoresizingMaskIntoConstraints = NO; + scrollView.backgroundColor = [UIColor blackColor]; + [self.view addSubview:scrollView]; + + UIView *contentView = [[UIView alloc] init]; + contentView.translatesAutoresizingMaskIntoConstraints = NO; + contentView.backgroundColor = [UIColor blackColor]; + [scrollView addSubview:contentView]; + + [self setupUserHeaderInContentView:contentView]; + [self setupCoinDiamondInContentView:contentView]; + [self setupSettingListInContentView:contentView]; + [self setupLogoutButtonInContentView:contentView]; + [self setupTabBar]; + + [NSLayoutConstraint activateConstraints:@[ + [scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [scrollView.bottomAnchor constraintEqualToAnchor:self.tabBar.topAnchor], + + [contentView.topAnchor constraintEqualToAnchor:scrollView.topAnchor], + [contentView.leadingAnchor constraintEqualToAnchor:scrollView.leadingAnchor], + [contentView.trailingAnchor constraintEqualToAnchor:scrollView.trailingAnchor], + [contentView.bottomAnchor constraintEqualToAnchor:scrollView.bottomAnchor], + [contentView.widthAnchor constraintEqualToAnchor:scrollView.widthAnchor] + ]]; +} + +#pragma mark - 上边儿 +- (void)setupUserHeaderInContentView:(UIView *)contentView { + UIButton *settingBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [settingBtn setImage:[UIImage systemImageNamed:@"gearshape"] forState:UIControlStateNormal]; + settingBtn.tintColor = [UIColor whiteColor]; + settingBtn.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:settingBtn]; + + UIImageView *avatar = [self createImageViewWithImage:@"hqz" contentMode:UIViewContentModeScaleAspectFill cornerRadius:40]; + [contentView addSubview:avatar]; + + UILabel *nameLabel = [self createLabelWithText:@"演示机李慧琳" fontSize:18 textColor:[UIColor whiteColor]]; + [contentView addSubview:nameLabel]; + + UILabel *idLabel = [self createLabelWithText:@"ID: 90047681" fontSize:14 textColor:[UIColor whiteColor]]; + [contentView addSubview:idLabel]; + + UIButton *signBtn = [self createButtonWithTitle:@"已签到" bgColor:[UIColor whiteColor] cornerRadius:15]; + [signBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [contentView addSubview:signBtn]; + + [NSLayoutConstraint activateConstraints:@[ + [avatar.topAnchor constraintEqualToAnchor:contentView.topAnchor constant:20], + [avatar.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor constant:20], + [avatar.widthAnchor constraintEqualToConstant:80], + [avatar.heightAnchor constraintEqualToConstant:80], + + [nameLabel.centerYAnchor constraintEqualToAnchor:avatar.centerYAnchor constant:-10], + [nameLabel.leadingAnchor constraintEqualToAnchor:avatar.trailingAnchor constant:15], + + [idLabel.topAnchor constraintEqualToAnchor:nameLabel.bottomAnchor constant:5], + [idLabel.leadingAnchor constraintEqualToAnchor:nameLabel.leadingAnchor], + + [signBtn.centerYAnchor constraintEqualToAnchor:avatar.centerYAnchor], + [signBtn.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor constant:-20], + [signBtn.widthAnchor constraintEqualToConstant:90], + [signBtn.heightAnchor constraintEqualToConstant:30], + + [settingBtn.topAnchor constraintEqualToAnchor:contentView.topAnchor constant:-35], + [settingBtn.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor constant:-20], + [settingBtn.widthAnchor constraintEqualToConstant:24], + [settingBtn.heightAnchor constraintEqualToConstant:24] + ]]; +} + +#pragma mark - 金币钻石 +- (void)setupCoinDiamondInContentView:(UIView *)contentView { + NSArray *itemConfigs = @[ + @{@"icon":@"hqz", @"text":@"6011.56"}, + @{@"icon":@"hqz", @"text":@"0"} + ]; + + UIView *containerView = [[UIView alloc] init]; + containerView.translatesAutoresizingMaskIntoConstraints = NO; + [contentView addSubview:containerView]; + + for (int i = 0; i < itemConfigs.count; i++) { + NSDictionary *config = itemConfigs[i]; + UIButton *btn = [self createInfoButtonWithConfig:config]; + btn.tag = 100 + i; + [containerView addSubview:btn]; + + [NSLayoutConstraint activateConstraints:@[ + [btn.topAnchor constraintEqualToAnchor:containerView.topAnchor], + [btn.bottomAnchor constraintEqualToAnchor:containerView.bottomAnchor], + [btn.widthAnchor constraintEqualToAnchor:containerView.widthAnchor multiplier:0.5], + (i == 0) ? [btn.leadingAnchor constraintEqualToAnchor:containerView.leadingAnchor] : [btn.trailingAnchor constraintEqualToAnchor:containerView.trailingAnchor] + ]]; + } + + UIView *verticalDivider = [self createVerticalDivider]; + [containerView addSubview:verticalDivider]; + + [NSLayoutConstraint activateConstraints:@[ + [containerView.topAnchor constraintEqualToAnchor:contentView.subviews[1].bottomAnchor constant:20], + [containerView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor], + [containerView.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor], + [containerView.heightAnchor constraintEqualToConstant:80], + + [verticalDivider.centerXAnchor constraintEqualToAnchor:containerView.centerXAnchor], + [verticalDivider.topAnchor constraintEqualToAnchor:containerView.topAnchor constant:10], + [verticalDivider.bottomAnchor constraintEqualToAnchor:containerView.bottomAnchor constant:-10], + [verticalDivider.widthAnchor constraintEqualToConstant:0.5] + ]]; +} + +#pragma mark - 设置列表 +- (void)setupSettingListInContentView:(UIView *)contentView { + NSArray *rowTexts = @[ + @"账号与安全", + @"服务期限", + @"行情设置", + @"通用设置", + @"金币记录", + @"分享奖励", + @"联系我们", + @"新版本更新", + @"意见反馈", + @"关于Homily Chart" + ]; + + // 金币钻石容器 + UIView *coinContainer = contentView.subviews.lastObject; + CGFloat topOffset = 0; + + for (int i = 0; i < rowTexts.count; i++) { + UIView *itemView = [self createCommonRowWithText:rowTexts[i]]; + [contentView addSubview:itemView]; + + [NSLayoutConstraint activateConstraints:@[ + [itemView.topAnchor constraintEqualToAnchor:coinContainer.bottomAnchor constant:topOffset + 20], + [itemView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor], + [itemView.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor], + [itemView.heightAnchor constraintEqualToConstant:60] + ]]; + + if (i < rowTexts.count - 1) { + UIView *divider = [self createDividerWithLeading:20]; + [contentView addSubview:divider]; + [NSLayoutConstraint activateConstraints:@[ + [divider.topAnchor constraintEqualToAnchor:itemView.bottomAnchor], + [divider.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor constant:20], + [divider.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor], + [divider.heightAnchor constraintEqualToConstant:0.5] + ]]; + } + + topOffset += 60; + } + + self.lastSettingItem = contentView.subviews.lastObject; +} + +#pragma mark - 退出登录 +- (void)setupLogoutButtonInContentView:(UIView *)contentView { + UIButton *logoutBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [logoutBtn setTitle:@"退出登录" forState:UIControlStateNormal]; + [logoutBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; + logoutBtn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + logoutBtn.translatesAutoresizingMaskIntoConstraints = NO; + [logoutBtn addTarget:self action:@selector(logoutTapped) forControlEvents:UIControlEventTouchUpInside]; + [contentView addSubview:logoutBtn]; + + [NSLayoutConstraint activateConstraints:@[ + [logoutBtn.topAnchor constraintEqualToAnchor:self.lastSettingItem.bottomAnchor constant:20], + [logoutBtn.centerXAnchor constraintEqualToAnchor:contentView.centerXAnchor], + [logoutBtn.widthAnchor constraintEqualToConstant:120], + [logoutBtn.heightAnchor constraintEqualToConstant:40], + + [contentView.bottomAnchor constraintEqualToAnchor:logoutBtn.bottomAnchor constant:20] + ]]; +} + +#pragma mark - 退出登录方法 +- (void)logoutTapped { + ViewController *loginVC = [[ViewController alloc] init]; + loginVC.hidesBottomBarWhenPushed = YES; // 隐藏TabBar + [self.navigationController pushViewController:loginVC animated:YES]; +} + +#pragma mark - 底部TabBar +- (void)setupTabBar { + NSArray *tabItems = @[ + @{@"title":@"首页", @"icon":@"house.fill", @"selected":@NO}, + @{@"title":@"行情", @"icon":@"chart.line.uptrend.xyaxis", @"selected":@NO}, + @{@"title":@"自选", @"icon":@"plus", @"selected":@NO}, + @{@"title":@"我的", @"icon":@"person", @"selected":@YES} + ]; + self.tabBar = [[CommonTabBar alloc] initWithTabItems:tabItems]; + self.tabBar.delegate = self; + self.tabBar.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.tabBar]; + + [NSLayoutConstraint activateConstraints:@[ + [self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor], + [self.tabBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.tabBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [self.tabBar.heightAnchor constraintEqualToConstant:49] + ]]; +} + +#pragma mark - 工具方法 +- (UIButton *)createInfoButtonWithConfig:(NSDictionary *)config { + UIButtonConfiguration *btnConfig = [UIButtonConfiguration plainButtonConfiguration]; + + NSString *iconName = config[@"icon"]; + UIImage *iconImage = [UIImage imageNamed:iconName]; + + if (!iconImage) { + UIImageSymbolConfiguration *symbolConfig = [UIImageSymbolConfiguration configurationWithPointSize:24 weight:UIFontWeightRegular]; + iconImage = [UIImage systemImageNamed:@"dollarsign.circle" withConfiguration:symbolConfig]; + } else { + UIGraphicsBeginImageContextWithOptions(CGSizeMake(40, 40), NO, 0); + [iconImage drawInRect:CGRectMake(0, 0, 40, 40)]; + iconImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + + btnConfig.image = iconImage; + btnConfig.imagePlacement = NSDirectionalRectEdgeTop; + btnConfig.imagePadding = 15; + + // 富文本吧 + NSAttributedString *titleAttr = [[NSAttributedString alloc] initWithString:config[@"text"] attributes:@{ + NSFontAttributeName: [UIFont systemFontOfSize:14], + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + btnConfig.attributedTitle = titleAttr; + + btnConfig.baseBackgroundColor = [UIColor clearColor]; + btnConfig.baseForegroundColor = [UIColor whiteColor]; + + UIButton *btn = [UIButton buttonWithConfiguration:btnConfig primaryAction:nil]; + btn.translatesAutoresizingMaskIntoConstraints = NO; + + [btn addTarget:self action:@selector(infoButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + + return btn; +} + +- (void)infoButtonTapped:(UIButton *)sender { + if (sender.tag == 100) { + NSLog(@"金币按钮被点击"); + } else if (sender.tag == 101) { + NSLog(@"钻石按钮被点击"); + } +} + +- (UIView *)createVerticalDivider { + UIView *divider = [[UIView alloc] init]; + divider.backgroundColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1]; + divider.translatesAutoresizingMaskIntoConstraints = NO; + return divider; +} + +- (UIImageView *)createImageViewWithImage:(NSString *)imageName contentMode:(UIViewContentMode)mode cornerRadius:(CGFloat)radius { + UIImageView *uiImageView = [[UIImageView alloc] init]; + uiImageView.image = [UIImage imageNamed:imageName]; + uiImageView.contentMode = mode; + uiImageView.layer.cornerRadius = radius; + uiImageView.clipsToBounds = YES; + uiImageView.translatesAutoresizingMaskIntoConstraints = NO; + return uiImageView; +} + +- (UILabel *)createLabelWithText:(NSString *)text fontSize:(CGFloat)size textColor:(UIColor *)color { + UILabel *label = [[UILabel alloc] init]; + label.text = text; + label.font = [UIFont systemFontOfSize:size weight:UIFontWeightMedium]; + label.textColor = color; + label.translatesAutoresizingMaskIntoConstraints = NO; + return label; +} + +- (UIButton *)createButtonWithTitle:(NSString *)title bgColor:(UIColor *)bgColor cornerRadius:(CGFloat)radius { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; + btn.backgroundColor = bgColor; + btn.layer.cornerRadius = radius; + btn.translatesAutoresizingMaskIntoConstraints = NO; + return btn; +} + +- (UIView *)createDividerWithLeading:(CGFloat)leading { + UIView *divider = [[UIView alloc] init]; + divider.backgroundColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1]; + divider.translatesAutoresizingMaskIntoConstraints = NO; + return divider; +} + +- (UIView *)createCommonRowWithText:(NSString *)text { + UIView *rowView = [[UIView alloc] init]; + rowView.translatesAutoresizingMaskIntoConstraints = NO; + rowView.backgroundColor = [UIColor clearColor]; + + UIImageView *logoView = [self createImageViewWithImage:@"hqz" + contentMode:UIViewContentModeScaleAspectFit + cornerRadius:0]; + logoView.tintColor = [UIColor blueColor]; + [rowView addSubview:logoView]; + + UILabel *textLabel = [self createLabelWithText:text + fontSize:16 + textColor:[UIColor whiteColor]]; + [rowView addSubview:textLabel]; + + UIButton *arrowBtn = [UIButton buttonWithType:UIButtonTypeSystem]; + [arrowBtn setImage:[UIImage systemImageNamed:@"chevron.right"] forState:UIControlStateNormal]; + [arrowBtn setTintColor:[UIColor lightGrayColor]]; + arrowBtn.translatesAutoresizingMaskIntoConstraints = NO; + [rowView addSubview:arrowBtn]; + + [NSLayoutConstraint activateConstraints:@[ + // logo左侧固定 + [logoView.centerYAnchor constraintEqualToAnchor:rowView.centerYAnchor], + [logoView.leadingAnchor constraintEqualToAnchor:rowView.leadingAnchor constant:20], + [logoView.widthAnchor constraintEqualToConstant:24], + [logoView.heightAnchor constraintEqualToConstant:24], + + // 文字 logo右侧 + [textLabel.centerYAnchor constraintEqualToAnchor:logoView.centerYAnchor], + [textLabel.leadingAnchor constraintEqualToAnchor:logoView.trailingAnchor constant:15], + + // 箭头 右侧固定 + [arrowBtn.centerYAnchor constraintEqualToAnchor:logoView.centerYAnchor], + [arrowBtn.trailingAnchor constraintEqualToAnchor:rowView.trailingAnchor constant:-20] + ]]; + + return rowView; +} + +#pragma mark - TabBar +- (void) pushHome { + HomeViewController *homeViewController = [[HomeViewController alloc] init]; + [self.navigationController pushViewController:homeViewController animated:YES]; +} + +- (void) pushQuotation { + QuotationViewController *quotationViewController = [[QuotationViewController alloc] init]; + [self.navigationController pushViewController:quotationViewController animated:YES]; +} + +- (void)tabBarDidSelectIndex:(NSInteger)index { + if (index == 3) { + + } else if (index == 0) { + [self pushHome]; + } else if (index == 1) { + [self pushQuotation]; + } else if (index == 2) { + // 自选 + } +} + +@end diff --git a/HC/QuotationViewController.h b/HC/QuotationViewController.h new file mode 100644 index 0000000..6727026 --- /dev/null +++ b/HC/QuotationViewController.h @@ -0,0 +1,16 @@ +// +// QuotationViewController.h +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import +#import "MLXYViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface QuotationViewController : UIViewController +@end + +NS_ASSUME_NONNULL_END diff --git a/HC/QuotationViewController.m b/HC/QuotationViewController.m new file mode 100644 index 0000000..012dea1 --- /dev/null +++ b/HC/QuotationViewController.m @@ -0,0 +1,258 @@ +// +// QuotationViewController.m +// HC +// +// Created by huilinLi on 2025/11/26. +// + +#import "QuotationViewController.h" +#import "CountryModel.h" +#import "MLXYViewController.h" // 马来西亚 +#import "CNViewController.h" // 中国 +#import "CommonTabBar.h" +#import "HomeViewController.h" +#import "MyViewController.h" + +@interface QuotationViewController () +@property (nonatomic, strong) CommonTabBar *commonTabBar; +@property (nonatomic, strong) NSArray *countries; // 国家列表 +@property (nonatomic, strong) UIViewController *currentChildVC; // 当前显示的子控制器 +@property (nonatomic, strong) UICollectionView *countryTabBar; // 国家选择标签栏 +@property (nonatomic, strong) UIView *contentContainer; // 子控制器容器 +@property (nonatomic, assign) NSInteger selectedIndex; // 当前选中的国家索引 + +// 顶部 +@property (nonatomic, strong) UIImageView *logoImage; // logo +@property (nonatomic, strong) UITextField *searchField; // 搜索框 +@property (nonatomic, strong) UIImageView *flagIcon; // 国旗 +@end + +@implementation QuotationViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.view.backgroundColor = [UIColor blackColor]; + + [self initCountries]; + [self setupSubviews]; + [self setupConstraints]; + + // 默认选中第一个 + self.selectedIndex = 0; + [self switchToCountryAtIndex:self.selectedIndex]; +} + +#pragma mark - 初始化国家数据 +- (void)initCountries { + self.countries = @[ + [CountryModel modelWithCode:@"MY" + name:@"马来西亚" + vcClassName:NSStringFromClass([MLXYViewController class])], + [CountryModel modelWithCode:@"CN" + name:@"中国" + vcClassName:NSStringFromClass([CNViewController class])] + ]; +} + +#pragma mark - 创建子视图 +- (void)setupSubviews { + self.logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo"]]; + self.logoImage.contentMode = UIViewContentModeScaleAspectFit; + self.logoImage.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.logoImage]; + + self.searchField = [[UITextField alloc] init]; + self.searchField.placeholder = @"股票名称/代码"; + NSAttributedString *placeholder = [[NSAttributedString alloc] initWithString:@"股票名称/代码" attributes:@{ + NSForegroundColorAttributeName: [UIColor whiteColor] + }]; + self.searchField.attributedPlaceholder = placeholder; + self.searchField.textColor = [UIColor whiteColor]; + self.searchField.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1]; + self.searchField.layer.cornerRadius = 15; + self.searchField.leftView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"magnifyingglass"]]; + self.searchField.leftViewMode = UITextFieldViewModeAlways; + self.searchField.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.searchField]; + + self.flagIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo"]]; + self.flagIcon.contentMode = UIViewContentModeScaleAspectFit; + self.flagIcon.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.flagIcon]; + + UICollectionViewFlowLayout *tabLayout = [[UICollectionViewFlowLayout alloc] init]; + tabLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;// 横向滚动 + tabLayout.itemSize = CGSizeMake(100, 40); // 每个标签宽100,高40 + tabLayout.minimumInteritemSpacing = 0; + + self.countryTabBar = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:tabLayout]; + self.countryTabBar.backgroundColor = [UIColor blackColor]; + self.countryTabBar.delegate = self; + self.countryTabBar.dataSource = self; + [self.countryTabBar registerClass:[UICollectionViewCell class]// 单元格复用类 + forCellWithReuseIdentifier:@"CountryTabCell"]; + self.countryTabBar.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.countryTabBar]; + + // 5. 内容容器,这个承接子视图 + self.contentContainer = [[UIView alloc] init]; + self.contentContainer.backgroundColor = [UIColor blackColor]; + self.contentContainer.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.contentContainer]; + + NSArray *tabItems = @[ + @{@"title":@"首页", @"icon":@"house.fill", @"selected":@NO}, + @{@"title":@"行情", @"icon":@"chart.line.uptrend.xyaxis", @"selected":@YES}, + @{@"title":@"自选", @"icon":@"plus", @"selected":@NO}, + @{@"title":@"我的", @"icon":@"person", @"selected":@NO} + ]; + self.commonTabBar = [[CommonTabBar alloc] initWithTabItems:tabItems]; + self.commonTabBar.delegate = self; + self.commonTabBar.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.commonTabBar]; +} + +#pragma mark - 布局约束 +- (void)setupConstraints { + // Logo + [NSLayoutConstraint activateConstraints:@[ + [self.logoImage.centerYAnchor constraintEqualToAnchor:self.searchField.centerYAnchor], + [self.logoImage.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:15], + [self.logoImage.widthAnchor constraintEqualToConstant:40], + [self.logoImage.heightAnchor constraintEqualToConstant:40] + ]]; + + // 搜索框 + [NSLayoutConstraint activateConstraints:@[ + [self.searchField.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:50], + [self.searchField.leadingAnchor constraintEqualToAnchor:self.logoImage.trailingAnchor constant:10], + [self.searchField.trailingAnchor constraintEqualToAnchor:self.flagIcon.leadingAnchor constant:-10], + [self.searchField.heightAnchor constraintEqualToConstant:30] + ]]; + + // 国旗 + [NSLayoutConstraint activateConstraints:@[ + [self.flagIcon.centerYAnchor constraintEqualToAnchor:self.searchField.centerYAnchor], + [self.flagIcon.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-15], + [self.flagIcon.widthAnchor constraintEqualToConstant:40], + [self.flagIcon.heightAnchor constraintEqualToConstant:40] + ]]; + + // 国家 + [NSLayoutConstraint activateConstraints:@[ + [self.countryTabBar.topAnchor constraintEqualToAnchor:self.searchField.bottomAnchor constant:15], + [self.countryTabBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.countryTabBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [self.countryTabBar.heightAnchor constraintEqualToConstant:40] + ]]; + + // 子视图容器 + [NSLayoutConstraint activateConstraints:@[ + [self.contentContainer.topAnchor constraintEqualToAnchor:self.countryTabBar.bottomAnchor], + [self.contentContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.contentContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [self.contentContainer.bottomAnchor constraintEqualToAnchor:self.commonTabBar.topAnchor] + ]]; + + // 底部TabBar + [NSLayoutConstraint activateConstraints:@[ + [self.commonTabBar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor], + [self.commonTabBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.commonTabBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] + ]]; +} + +#pragma mark - 切换子控制器 +- (void)switchToCountryAtIndex:(NSInteger)index { + // 先移除 + if (self.currentChildVC) { + [self.currentChildVC willMoveToParentViewController:nil]; + [self.currentChildVC.view removeFromSuperview]; + [self.currentChildVC removeFromParentViewController]; + self.currentChildVC = nil; + } + + // 创建新的 + CountryModel *selectedCountry = self.countries[index]; + Class childVCClass = NSClassFromString(selectedCountry.vcClassName);// 字符串转Class???? + UIViewController *childVC = [[childVCClass alloc] init]; + + // 添加 + [self addChildViewController:childVC]; + childVC.view.frame = self.contentContainer.bounds;// 适配容器 + childVC.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;// 自适应容器大小 + [self.contentContainer addSubview:childVC.view]; + [childVC didMoveToParentViewController:self]; + + self.currentChildVC = childVC; +} + +#pragma mark - 国家数据源 +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.countries.count; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CountryTabCell" forIndexPath:indexPath]; + cell.backgroundColor = [UIColor blackColor]; + + // 国家名称 + UILabel *nameLabel = [cell viewWithTag:100]; + if (!nameLabel) { + nameLabel = [[UILabel alloc] init]; + nameLabel.tag = 100; + nameLabel.textColor = [UIColor whiteColor]; + nameLabel.font = [UIFont systemFontOfSize:15]; + nameLabel.textAlignment = NSTextAlignmentCenter; + [cell.contentView addSubview:nameLabel]; + nameLabel.frame = cell.contentView.bounds;// 撑满单元格 + } + nameLabel.text = self.countries[indexPath.item].name; + + // 选中下划线 + UIView *selectedLine = [cell viewWithTag:101]; + if (!selectedLine) { + selectedLine = [[UIView alloc] init]; + selectedLine.tag = 101; + selectedLine.backgroundColor = [UIColor blueColor]; + [cell.contentView addSubview:selectedLine]; + selectedLine.frame = CGRectMake(30, cell.contentView.bounds.size.height - 7, 40, 4); + } + selectedLine.hidden = !(indexPath.item == self.selectedIndex); + + return cell; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { + self.selectedIndex = indexPath.item; + [self.countryTabBar reloadData]; // 刷新标签选中状态 + [self switchToCountryAtIndex:indexPath.item]; // 切换到对应国家页面 +} + +#pragma mark - 底部跳转方法 +- (void)tabBarDidSelectIndex:(NSInteger)index { + switch (index) { + case 0: + [self pushHome]; + break; + case 1: + break; + case 2: + break; + case 3: + [self pushMine]; + break; + } +} + +- (void) pushMine { + MyViewController *myViewController = [[MyViewController alloc] init]; + [self.navigationController pushViewController:myViewController animated:YES]; +} + +- (void) pushHome { + HomeViewController *myViewController = [[HomeViewController alloc] init]; + [self.navigationController pushViewController:myViewController animated:YES]; +} + +@end diff --git a/HC/SceneDelegate.m b/HC/SceneDelegate.m index 738cfd8..9be9ac3 100644 --- a/HC/SceneDelegate.m +++ b/HC/SceneDelegate.m @@ -7,6 +7,8 @@ #import "SceneDelegate.h" #import "AppDelegate.h" +#import "ViewController.h" +#import "ChartViewController.h" @interface SceneDelegate () @@ -16,9 +18,23 @@ - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + UIWindowScene *windowScene = (UIWindowScene *)scene; + if (!windowScene) return; + + self.window = [[UIWindow alloc] initWithWindowScene:windowScene]; + // 改用窗口场景的屏幕尺寸(兼容 iOS 26+) + self.window.frame = windowScene.screen.bounds; + self.window.backgroundColor = [UIColor blackColor]; + + //ViewController *loginVC = [[ViewController alloc] init]; + //UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:loginVC]; + //self.window.rootViewController = navVC; + // 实例化 ChartViewController + ChartViewController *chartVC = [[ChartViewController alloc] init]; + + // **设置 ChartViewController 为根视图控制器** + self.window.rootViewController = chartVC; + [self.window makeKeyAndVisible]; } diff --git a/HC/StockKLineModel.h b/HC/StockKLineModel.h new file mode 100644 index 0000000..c6aa38f --- /dev/null +++ b/HC/StockKLineModel.h @@ -0,0 +1,36 @@ +// +// StockKLineModel.h +// HomilyChartFake +// +// Created by 洪锡林 on 2025/11/28. +// + + +#import + + +NS_ASSUME_NONNULL_BEGIN + + +@interface StockKLineModel : NSObject + + +@property (nonatomic, copy) NSString *date; // 时间,如 "2025-11-27" +@property (nonatomic, assign) CGFloat open; // 开盘价 +@property (nonatomic, assign) CGFloat close;// 收盘价 +@property (nonatomic, assign) CGFloat high; // 最高价 +@property (nonatomic, assign) CGFloat low; // 最低价 +@property (nonatomic, assign) CGFloat volume; // 成交量 + +// 预留给MA均线(后面章节会用到) +@property (nonatomic, assign) CGFloat ma5; +@property (nonatomic, assign) CGFloat ma10; +@property (nonatomic, assign) CGFloat ma20; + +// 辅助方法:判断是否是阳线(涨) +- (BOOL)isUp; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/HC/StockKLineModel.m b/HC/StockKLineModel.m new file mode 100644 index 0000000..4f3711a --- /dev/null +++ b/HC/StockKLineModel.m @@ -0,0 +1,21 @@ +// +// StockKLineModel.m +// HomilyChartFake +// +// Created by 洪锡林 on 2025/11/28. +// + + +#import "StockKLineModel.h" + + +@implementation StockKLineModel + + +- (BOOL)isUp { + // 在A股,收盘 >= 开盘 认为是阳线(红色),这里包含平盘情况 + return self.close >= self.open; +} + + +@end diff --git a/HC/ViewController.h b/HC/ViewController.h index dd337a3..9e12084 100644 --- a/HC/ViewController.h +++ b/HC/ViewController.h @@ -7,8 +7,7 @@ #import -@interface ViewController : UIViewController - +@interface ViewController : UIViewController @end diff --git a/HC/ViewController.m b/HC/ViewController.m index 5f57644..6c66a4e 100644 --- a/HC/ViewController.m +++ b/HC/ViewController.m @@ -6,17 +6,294 @@ // #import "ViewController.h" +#import "HomeViewController.h" @interface ViewController () +@property (nonatomic, strong) UIImageView *logoImage; +@property (nonatomic, strong) UILabel *headLabel;// 账号密码登录 +@property (nonatomic, strong) UILabel *idLabel;// Homily ID +@property (nonatomic, strong) UILabel *pwdLabel;// 密码 +@property (nonatomic, strong) UITextField *account;// 输入框 +@property (nonatomic, strong) UITextField *pwd; +@property (nonatomic, strong) UIButton *loginButton;// 登录 +@property (nonatomic, strong) UIButton *agreementButton;// 协议 +@property (nonatomic, strong) UILabel *agreementLabel;// 协议文字 +@property (nonatomic, strong) UILabel *loseLabel;// 忘记密码? +@property (nonatomic, strong) UILabel *questionLabel;// 登录遇到问题? +@property (nonatomic, strong) UIButton *emailButton;// 邮箱登录 + @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view. + self.view.backgroundColor = [UIColor blackColor]; + self.view.userInteractionEnabled = YES;// 开启视图交互 + [self setupSubviews]; + [self setupConstraints]; + + NSLog(@"看看导航控制器:%@", self.navigationController ? @"有" : @"哪去了"); +} +#pragma mark - 控件 +-(void) setupSubviews{ + _headLabel = [[UILabel alloc] init]; + _headLabel.text = @"账号密码登录"; + _headLabel.textColor = [UIColor whiteColor]; + _headLabel.font = [UIFont systemFontOfSize:20]; + _headLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_headLabel]; + + // 账号 + _idLabel = [[UILabel alloc] init]; + _idLabel.text = @"Homily ID | "; + _idLabel.textColor = [UIColor whiteColor]; + _idLabel.font = [UIFont systemFontOfSize:16]; + _idLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_idLabel]; + + // 密码 + _pwdLabel = [[UILabel alloc] init]; + _pwdLabel.text = @"密码 | "; + _pwdLabel.textColor = [UIColor whiteColor]; + _pwdLabel.font = [UIFont systemFontOfSize:16]; + _pwdLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_pwdLabel]; + + // 账号输入 + _account = [[UITextField alloc] init]; + NSDictionary *placeholder = @{ + NSForegroundColorAttributeName: [UIColor whiteColor], + NSFontAttributeName: _account.font + }; + _account.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@" 请输入帐号" attributes:placeholder]; + _account.textColor = [UIColor whiteColor]; + _account.layer.borderWidth = 0; + _account.layer.cornerRadius = 5; + _account.delegate = self; + _account.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_account]; + + // 密码输入 + _pwd = [[UITextField alloc] init]; + NSDictionary *placeholderAttrs1 = @{ + NSForegroundColorAttributeName: [UIColor whiteColor], + NSFontAttributeName: _pwd.font + }; + _pwd.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@" 请输入密码" attributes:placeholderAttrs1]; + _pwd.secureTextEntry = YES; + _pwd.textColor = [UIColor whiteColor]; + _pwd.layer.borderWidth = 0; + _pwd.layer.cornerRadius = 5; + _pwd.delegate = self; + _pwd.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_pwd]; + + // 登录 + _loginButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_loginButton setTitle:@"登录" forState:UIControlStateNormal]; + [_loginButton setTitle:@"这是一个高亮" forState:UIControlStateHighlighted]; + [_loginButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [_loginButton setTitleColor:[UIColor yellowColor] forState:UIControlStateHighlighted]; + _loginButton.backgroundColor = [UIColor blueColor]; + _loginButton.layer.cornerRadius = 25;// 圆角是高度一半就是圆形按钮 + _loginButton.translatesAutoresizingMaskIntoConstraints = NO; + [_loginButton addTarget:self + action:@selector(handleLogin) + forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_loginButton]; + + // 协议勾选 + _agreementButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _agreementButton.layer.borderColor = [UIColor whiteColor].CGColor; + _agreementButton.layer.borderWidth = 1; + _agreementButton.layer.cornerRadius = 3; + _agreementButton.translatesAutoresizingMaskIntoConstraints = NO; + [_agreementButton addTarget:self + action:@selector(agreementButtonSelect:) + forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:_agreementButton]; + + // 协议 + _agreementLabel = [[UILabel alloc] init]; + _agreementLabel.text = @"我已阅读且同意《注册协议》和《隐私政策》"; + _agreementLabel.textColor = [UIColor whiteColor]; + _agreementLabel.font = [UIFont systemFontOfSize:12]; + _agreementLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_agreementLabel]; + + // 忘记密码? + _loseLabel = [[UILabel alloc] init]; + _loseLabel.text = @"忘记密码?"; + _loseLabel.textColor = [UIColor blueColor]; + _loseLabel.font = [UIFont systemFontOfSize:14]; + _loseLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_loseLabel]; + + // 登录遇到问题? + _questionLabel = [[UILabel alloc] init]; + _questionLabel.text = @"登录遇到问题?"; + _questionLabel.textColor = [UIColor whiteColor]; + _questionLabel.font = [UIFont systemFontOfSize:14]; + _questionLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:_questionLabel]; + + // 邮箱登录 + _emailButton = [UIButton buttonWithConfiguration:[self createEmailButtonConfig] primaryAction:nil]; + _emailButton.translatesAutoresizingMaskIntoConstraints = NO;// 禁用自动布局!!!! + [self.view addSubview:_emailButton]; + + // logo的image + _logoImage = [[UIImageView alloc] init]; + _logoImage.image = [UIImage imageNamed:@"logo"]; + _logoImage.contentMode = UIViewContentModeScaleAspectFit; + _logoImage.translatesAutoresizingMaskIntoConstraints = NO;// 禁用自动布局!!!! + [self.view addSubview:_logoImage]; + + [self.view bringSubviewToFront:_account]; + [self.view bringSubviewToFront:_pwd]; } +#pragma mark - 协议选中 +- (void) agreementButtonSelect:(UIButton *) button { + button.selected = !button.selected; + + if (button.selected) { + [button setImage:[UIImage systemImageNamed:@"checkmark"] forState:UIControlStateNormal]; + button.tintColor = [UIColor whiteColor]; + button.backgroundColor = [UIColor blueColor]; + } else { + [button setImage:nil forState:UIControlStateNormal]; + button.backgroundColor = [UIColor clearColor]; + } +} +#pragma mark - 弹窗提示 +// 弹窗 +- (void) showAlertWithMessage:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"确定" + style:UIAlertActionStyleDefault + handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void) handleLogin { +// NSString *account = _account.text; +// if (account.length == 0 || ![account isEqualToString:@"90047681"]) { +// [self showAlertWithMessage:@"请输入正确的账号"]; +// return; +// } +// +// NSString *pwdText = _pwd.text; +// if (pwdText.length == 0 || ![pwdText isEqualToString:@"123456"]) { +// [self showAlertWithMessage:@"请输入正确的密码"]; +// return; +// } +// +// if (!_agreementButton.selected) { +// [self showAlertWithMessage:@"请勾选协议"]; +// return; +// } + + HomeViewController *homeViewController = [[HomeViewController alloc] init]; + [self.navigationController pushViewController:homeViewController animated:YES]; +} + +#pragma mark - 约束 +- (void) setupConstraints { + [NSLayoutConstraint activateConstraints:@[ + // logo + [_logoImage.bottomAnchor constraintEqualToAnchor:_headLabel.topAnchor constant:-30], + [_logoImage.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_logoImage.widthAnchor constraintEqualToConstant:50], + [_logoImage.heightAnchor constraintEqualToConstant:50], + + // 标题 顶210,左40,宽200,高20 + [_headLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:210], + [_headLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_headLabel.widthAnchor constraintEqualToConstant:200], + [_headLabel.heightAnchor constraintEqualToConstant:20], + + // ID 顶310,左40,宽200,高20 + [_idLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:310], + [_idLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_idLabel.widthAnchor constraintEqualToConstant:200], + [_idLabel.heightAnchor constraintEqualToConstant:20], + + // 密码 ID下60,左40,宽200,高20 + [_pwdLabel.topAnchor constraintEqualToAnchor:_idLabel.topAnchor constant:60], + [_pwdLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_account.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-40], + [_pwdLabel.heightAnchor constraintEqualToConstant:20], + + // 账号输入框:ID上10,左120,宽200,高40 + [_account.topAnchor constraintEqualToAnchor:_idLabel.topAnchor constant:-10], + [_account.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:120], + [_pwd.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-40], + [_account.heightAnchor constraintEqualToConstant:40], + + // 密码输入框:密码上10,左120,宽200,高40 + [_pwd.topAnchor constraintEqualToAnchor:_pwdLabel.topAnchor constant:-10], + [_pwd.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:120], + [_pwd.widthAnchor constraintEqualToConstant:200], + [_pwd.heightAnchor constraintEqualToConstant:40], + + // 登录按钮:密码框下80,左右40,高50 + [_loginButton.topAnchor constraintEqualToAnchor:_pwd.bottomAnchor constant:60], + [_loginButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_loginButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-40], + [_loginButton.heightAnchor constraintEqualToConstant:50], + + // 协议按钮:登录下70,左40,宽高20 + [_agreementButton.topAnchor constraintEqualToAnchor:_loginButton.bottomAnchor constant:30], + [_agreementButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:40], + [_agreementButton.widthAnchor constraintEqualToConstant:20], + [_agreementButton.heightAnchor constraintEqualToConstant:20], + + // 协议:同协议按钮顶,左70,右40 + [_agreementLabel.topAnchor constraintEqualToAnchor:_agreementButton.topAnchor], + [_agreementLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:70], + [_agreementLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-40], + [_agreementLabel.heightAnchor constraintEqualToConstant:20], + + // 忘记密码:协议按钮下65,水平居中,高20 + [_loseLabel.topAnchor constraintEqualToAnchor:_agreementButton.bottomAnchor constant:65], + [_loseLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [_loseLabel.heightAnchor constraintEqualToConstant:20], + + // 登录问题:忘记密码下45,水平居中,高20 + [_questionLabel.topAnchor constraintEqualToAnchor:_loseLabel.bottomAnchor constant:15], + [_questionLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [_questionLabel.heightAnchor constraintEqualToConstant:20], + + // 邮箱登录 + [_emailButton.topAnchor constraintEqualToAnchor:_loseLabel.bottomAnchor constant:55], + [_emailButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [_emailButton.widthAnchor constraintEqualToConstant:100], + [_emailButton.heightAnchor constraintEqualToConstant:100], + ]]; +} +// 单写一个 +- (UIButtonConfiguration *) createEmailButtonConfig { + UIButtonConfiguration *config = [UIButtonConfiguration plainButtonConfiguration]; + config.title = @"邮箱登录"; + config.image = [UIImage imageNamed:@"email"]; + config.imagePlacement = NSDirectionalRectEdgeTop;// 这里也不对???? + config.imagePadding = 8; + + return config; +} +#pragma mark - UITextFieldDelegate +- (BOOL) textFieldShouldReturn:(UITextField *)textField { + [textField resignFirstResponder];// 点击return键收起键盘 + return YES; +} + +- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self.view endEditing:YES];// 点空白也收起键盘 +} @end