Files
keyboard/keyBoard/Class/Me/VC/KBSkinDetailVC.m
2025-11-10 15:38:30 +08:00

202 lines
7.9 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBSkinDetailVC.m
// keyBoard
#import "KBSkinDetailVC.h"
#import <Masonry/Masonry.h>
#import "UIColor+Extension.h"
#import "UICollectionViewLeftAlignedLayout.h"
#import "KBSkinDetailHeaderCell.h"
#import "KBSkinTagsContainerCell.h"
#import "KBSkinCardCell.h"
#import "KBSkinSectionTitleCell.h"
#import "KBSkinBottomActionView.h"
static NSString * const kHeaderCellId = @"kHeaderCellId";
static NSString * const kTagsContainerCellId = @"kTagsContainerCellId";
static NSString * const kSectionTitleCellId = @"kSectionTitleCellId";
static NSString * const kGridCellId = @"kGridCellId"; // 直接复用 KBSkinCardCell
typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
KBSkinDetailSectionHeader = 0,
KBSkinDetailSectionTags,
KBSkinDetailSectionTitle,
KBSkinDetailSectionGrid,
KBSkinDetailSectionCount
};
@interface KBSkinDetailVC () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionView; // 主列表
@property (nonatomic, strong) KBSkinBottomActionView *bottomBar; // 底部操作条
@property (nonatomic, copy) NSArray<NSString *> *tags; // 标签数据
@property (nonatomic, copy) NSArray<NSDictionary *> *gridData; // 底部网格数据
@end
@implementation KBSkinDetailVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// 简单数据(演示)
self.tags = @[ @"Cute", @"Fresh", @"Cute", @"Fresh", @"Cute", @"Fresh" ];
self.gridData = @[
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
];
// 1. 列表
[self.view addSubview:self.collectionView];
// 2. 底部操作条(左右 15高 45可点击
[self.view addSubview:self.bottomBar];
[self.bottomBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(15);
make.right.equalTo(self.view).offset(-15);
make.height.mas_equalTo([KBSkinBottomActionView preferredHeight]);
if (@available(iOS 11.0, *)) {
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
} else {
make.bottom.equalTo(self.view);
}
}];
// 列表底部距离操作条顶部 10
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self.view);
make.bottom.equalTo(self.bottomBar.mas_top).offset(-10);
}];
}
#pragma mark - UICollectionView DataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return KBSkinDetailSectionCount;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
switch (section) {
case KBSkinDetailSectionHeader: return 1; // 顶部大卡片
case KBSkinDetailSectionTags: return 1; // 标签容器
case KBSkinDetailSectionTitle: return 1; // 标题
case KBSkinDetailSectionGrid: return self.gridData.count; // 2 列网格
}
return 0;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case KBSkinDetailSectionHeader: {
KBSkinDetailHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kHeaderCellId forIndexPath:indexPath];
[cell configWithTitle:@"Dopamine" right:@"Download: 1 Million"];
return cell;
}
case KBSkinDetailSectionTags: {
KBSkinTagsContainerCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kTagsContainerCellId forIndexPath:indexPath];
[cell configWithTags:self.tags];
return cell;
}
case KBSkinDetailSectionTitle: {
KBSkinSectionTitleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kSectionTitleCellId forIndexPath:indexPath];
[cell config:@"Recommended Skin"];
return cell;
}
case KBSkinDetailSectionGrid: {
KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kGridCellId forIndexPath:indexPath];
NSDictionary *d = self.gridData[indexPath.item];
[cell configWithTitle:d[@"title"] imageURL:nil price:@"20"];
return cell;
}
}
return [UICollectionViewCell new];
}
#pragma mark - UICollectionView DelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat W = collectionView.bounds.size.width;
CGFloat insetLR = 16.0;
CGFloat contentW = W - insetLR * 2;
switch (indexPath.section) {
case KBSkinDetailSectionHeader: {
// 高度 = 图片 0.58W + 文案与上下留白≈56
CGFloat h = contentW * 0.58 + 56;
return CGSizeMake(contentW, h);
}
case KBSkinDetailSectionTags: {
CGFloat h = [KBSkinTagsContainerCell heightForTags:self.tags width:W];
return CGSizeMake(contentW, h);
}
case KBSkinDetailSectionTitle: {
return CGSizeMake(contentW, 44);
}
case KBSkinDetailSectionGrid: {
// 2 列
CGFloat spacing = 12.0;
CGFloat itemW = floor((contentW - spacing) / 2.0);
CGFloat itemH = itemW * 0.75 + 56; // 参考 KBSkinCardCell 内部布局
return CGSizeMake(itemW, itemH);
}
}
return CGSizeZero;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(12, 16, 12, 16);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 12.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
// 网格区需要这个间距,其它区也保持统一
return 12.0;
}
#pragma mark - Lazy
- (UICollectionView *)collectionView {
if (!_collectionView) {
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.dataSource = self;
_collectionView.delegate = self;
// 注册 cell
[_collectionView registerClass:KBSkinDetailHeaderCell.class forCellWithReuseIdentifier:kHeaderCellId];
[_collectionView registerClass:KBSkinTagsContainerCell.class forCellWithReuseIdentifier:kTagsContainerCellId];
[_collectionView registerClass:KBSkinSectionTitleCell.class forCellWithReuseIdentifier:kSectionTitleCellId];
[_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:kGridCellId];
}
return _collectionView;
}
#pragma mark - Lazy (Bottom Bar)
- (KBSkinBottomActionView *)bottomBar {
if (!_bottomBar) {
_bottomBar = [[KBSkinBottomActionView alloc] init];
// 中文注释:配置文案与图标,可根据业务传入金币图/价格
[_bottomBar configWithTitle:@"Download" price:@"20" icon:nil];
KBWeakSelf
_bottomBar.tapHandler = ^{
// 示例:点击下载/购买
// [KBHUD showText:@"点击了下载"];
// TODO: 在此处触发下载/购买逻辑
[weakSelf handleDownloadAction];
};
}
return _bottomBar;
}
#pragma mark - Actions
- (void)handleDownloadAction {
// 预留:下载/购买动作
}
@end