添加底部view

This commit is contained in:
2025-11-10 15:29:21 +08:00
parent fac5e7657c
commit 97316c7989
6 changed files with 243 additions and 6 deletions

View File

@@ -75,6 +75,7 @@
048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048909F32EC0AAAA00FABA60 /* KBCategoryTitleView.m */; };
04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */; };
04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */; };
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */; };
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */; };
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */; };
@@ -263,6 +264,8 @@
04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageCell.m; sourceTree = "<group>"; };
04890A022EC0BBBB00FABA60 /* KBCategoryTitleImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCategoryTitleImageView.h; sourceTree = "<group>"; };
04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageView.m; sourceTree = "<group>"; };
049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinBottomActionView.h; sourceTree = "<group>"; };
049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinBottomActionView.m; sourceTree = "<group>"; };
04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; sourceTree = "<group>"; };
04A9FE102EB4D0D20020DB6D /* KBFullAccessManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFullAccessManager.h; sourceTree = "<group>"; };
04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessManager.m; sourceTree = "<group>"; };
@@ -823,6 +826,8 @@
048908EB2EBF849300FABA60 /* KBSkinTagsContainerCell.m */,
048908ED2EBF861800FABA60 /* KBSkinSectionTitleCell.h */,
048908EE2EBF861800FABA60 /* KBSkinSectionTitleCell.m */,
049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */,
049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */,
);
path = V;
sourceTree = "<group>";
@@ -1352,6 +1357,7 @@
047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */,
047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */,
048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */,
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */,
047C655E2EBCD5B20035E841 /* UIImage+KBColor.m in Sources */,
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */,

View File

@@ -3,7 +3,6 @@
// keyBoard
//
// 统一封装基于 LYEmptyView 的空态视图挂载方法,适用于 UITableView/UICollectionView。
// 注意:仅在对应页面已通过 CocoaPods 集成 LYEmptyView 时生效。
//
#import <UIKit/UIKit.h>

View File

@@ -0,0 +1,37 @@
//
// KBSkinBottomActionView.h
// keyBoard
//
// 底部操作条(圆角胶囊样式),支持点击。用于皮肤详情页下载/购买。
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// 底部操作条45 高,左右圆角)。
/// 结构: [ Title [coinIcon] [price] ] 居中对齐
@interface KBSkinBottomActionView : UIControl
/// 标题,例如:@"Download"
@property (nonatomic, copy) NSString *titleText;
/// 价格/金币数,例如:@"20"
@property (nonatomic, copy) NSString *priceText;
/// 图标(可选),例如金币图
@property (nonatomic, strong, nullable) UIImage *iconImage;
/// 点击回调(也可直接 addTarget 使用)
@property (nonatomic, copy, nullable) void (^tapHandler)(void);
/// 配置便捷方法
- (void)configWithTitle:(nullable NSString *)title price:(nullable NSString *)price icon:(nullable UIImage *)icon;
/// 建议固定高度
+ (CGFloat)preferredHeight;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,153 @@
//
// KBSkinBottomActionView.m
// keyBoard
//
//
#import "KBSkinBottomActionView.h"
@interface KBSkinBottomActionView ()
@property (nonatomic, strong) UIView *contentView; // 使
@property (nonatomic, strong) UILabel *titleLabel; //
@property (nonatomic, strong) UIImageView *coinImageView; //
@property (nonatomic, strong) UILabel *priceLabel; //
@end
@implementation KBSkinBottomActionView
+ (CGFloat)preferredHeight { return 45.0; }
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor colorWithHex:0x02BEAC];
self.layer.masksToBounds = YES; //
//
[self addTarget:self action:@selector(onTouchDown) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(onTouchUp) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside | UIControlEventTouchCancel];
// /
[self addSubview:self.contentView];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.centerY.equalTo(self);
//
make.left.greaterThanOrEqualTo(self).offset(16);
make.right.lessThanOrEqualTo(self).offset(-16);
}];
// Title - Icon - Price
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.coinImageView];
[self.contentView addSubview:self.priceLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView);
make.centerY.equalTo(self.contentView);
}];
[self.coinImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.titleLabel.mas_right).offset(8);
make.centerY.equalTo(self.contentView);
make.width.height.mas_equalTo(18);
}];
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.coinImageView.mas_right).offset(6);
make.right.equalTo(self.contentView);
make.centerY.equalTo(self.contentView);
}];
//
self.titleText = @"Download";
self.priceText = @"20";
UIImage *img = [UIImage systemImageNamed:@"circle.fill"];
self.iconImage = img; //
self.coinImageView.tintColor = [UIColor colorWithRed:1.0 green:0.85 blue:0.2 alpha:1.0];
//
[self addTarget:self action:@selector(handleTap) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
//
self.layer.cornerRadius = CGRectGetHeight(self.bounds) * 0.5;
}
#pragma mark - Public
- (void)configWithTitle:(nullable NSString *)title price:(nullable NSString *)price icon:(nullable UIImage *)icon {
if (title.length) self.titleText = title;
if (price.length) self.priceText = price;
if (icon) self.iconImage = icon;
}
#pragma mark - Actions
- (void)onTouchDown { self.alpha = 0.85; }
- (void)onTouchUp { self.alpha = 1.0; }
- (void)handleTap {
if (self.tapHandler) { self.tapHandler(); }
}
#pragma mark - Setters
- (void)setTitleText:(NSString *)titleText {
_titleText = [titleText copy];
self.titleLabel.text = _titleText;
}
- (void)setPriceText:(NSString *)priceText {
_priceText = [priceText copy];
self.priceLabel.text = _priceText;
}
- (void)setIconImage:(UIImage *)iconImage {
_iconImage = iconImage;
self.coinImageView.image = _iconImage;
}
#pragma mark - Lazy
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}
- (UIView *)contentView {
if (!_contentView) {
_contentView = [[UIView alloc] init];
_contentView.backgroundColor = [UIColor clearColor];
//
[_contentView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[_contentView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
}
return _contentView;
}
- (UIImageView *)coinImageView {
if (!_coinImageView) {
_coinImageView = [[UIImageView alloc] init];
_coinImageView.contentMode = UIViewContentModeScaleAspectFit;
_coinImageView.clipsToBounds = YES;
}
return _coinImageView;
}
- (UILabel *)priceLabel {
if (!_priceLabel) {
_priceLabel = [[UILabel alloc] init];
_priceLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold];
_priceLabel.textColor = [UIColor whiteColor];
_priceLabel.textAlignment = NSTextAlignmentCenter;
}
return _priceLabel;
}
@end

View File

@@ -8,8 +8,9 @@
#import "UICollectionViewLeftAlignedLayout.h"
#import "KBSkinDetailHeaderCell.h"
#import "KBSkinTagsContainerCell.h"
#import "KBSkinCardCell.h" // cell 2
#import "KBSkinCardCell.h"
#import "KBSkinSectionTitleCell.h"
#import "KBSkinBottomActionView.h"
static NSString * const kHeaderCellId = @"kHeaderCellId";
static NSString * const kTagsContainerCellId = @"kTagsContainerCellId";
@@ -26,6 +27,7 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
@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
@@ -44,9 +46,26 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
@{ @"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.edges.equalTo(self.view);
make.top.left.right.equalTo(self.view);
make.bottom.equalTo(self.bottomBar.mas_top).offset(-10);
}];
}
@@ -156,4 +175,27 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
return _collectionView;
}
#pragma mark - Lazy (Bottom Bar)
- (KBSkinBottomActionView *)bottomBar {
if (!_bottomBar) {
_bottomBar = [[KBSkinBottomActionView alloc] init];
// /
[_bottomBar configWithTitle:@"Download" price:@"20" icon:nil];
__weak typeof(self) weakSelf = self;
_bottomBar.tapHandler = ^{
// /
// [KBHUD showText:@"点击了下载"];
// TODO: /
[weakSelf handleDownloadAction];
};
}
return _bottomBar;
}
#pragma mark - Actions
- (void)handleDownloadAction {
// /
}
@end

View File

@@ -29,10 +29,10 @@
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
MySkinVC *vc = [[MySkinVC alloc] init];
// KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init];
// MySkinVC *vc = [[MySkinVC alloc] init];
KBSkinDetailVC *vc = [[KBSkinDetailVC alloc] init];
[self.navigationController pushViewController:vc animated:true];
// [self.navigationController pushViewController:vc animated:true];
}
/*