2
This commit is contained in:
209
keyBoard/Class/Shop/VC/KBSkinDetailVC.m
Normal file
209
keyBoard/Class/Shop/VC/KBSkinDetailVC.m
Normal file
@@ -0,0 +1,209 @@
|
||||
//
|
||||
// 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]);
|
||||
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-10);
|
||||
|
||||
}];
|
||||
|
||||
// 列表底部距离操作条顶部 10
|
||||
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.view);
|
||||
make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT);
|
||||
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 = KBFit(264) + 30;
|
||||
return CGSizeMake(contentW, h);
|
||||
}
|
||||
case KBSkinDetailSectionTags: {
|
||||
CGFloat h = [KBSkinTagsContainerCell heightForTags:self.tags width:W];
|
||||
return CGSizeMake(contentW, 25);
|
||||
}
|
||||
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;
|
||||
return CGSizeMake(itemW, KBFit(197));
|
||||
}
|
||||
}
|
||||
return CGSizeZero;
|
||||
}
|
||||
|
||||
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
|
||||
// 控制各区上下留白,缩小 Header 与 Tags 之间的间距
|
||||
switch (section) {
|
||||
case KBSkinDetailSectionHeader:
|
||||
// 顶部与导航之间 12,底部稍微缩小
|
||||
return UIEdgeInsetsMake(12, 16, 4, 16);
|
||||
case KBSkinDetailSectionTags:
|
||||
// 与 Header 更贴近一些
|
||||
return UIEdgeInsetsMake(14, 16, 5, 16);
|
||||
default:
|
||||
return UIEdgeInsetsMake(0, 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
|
||||
Reference in New Issue
Block a user