Files
keyboard/keyBoard/Class/Home/VC/HomeSheetVC.m
2025-11-17 20:07:39 +08:00

272 lines
8.8 KiB
Objective-C

//
// HomeSheetVC.m
// keyBoard
//
// Created by Mac on 2025/11/5.
//
#import "HomeSheetVC.h"
#import "KBDirectionIndicatorView.h"
// 子控制器
#import "HomeHotVC.h"
#import "HomeRankVC.h"
@interface HomeSheetVC ()
@property (nonatomic, strong) KBDirectionIndicatorView *indicator;
// 顶部切换按钮与指示条
@property (nonatomic, strong) UIView *topBar;
@property (nonatomic, strong) UIButton *hotButton;
@property (nonatomic, strong) UIButton *rankButton;
@property (nonatomic, strong) UIView *underlineView; // 选中下划线
// 承载子控制器内容
@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIViewController *currentChild;
@property (nonatomic, strong) HomeHotVC *hotVC;
@property (nonatomic, strong) HomeRankVC *rankVC;
@end
@implementation HomeSheetVC
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor redColor];
HWBackgroundConfig *config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
config.backgroundAlpha = 0.001;
[self.hw_dimmedView reloadConfig:config];
// 顶部按钮 + 容器
[self setupTopButtonsAndContainer];
// 默认展示“热门”
[self switchToIndex:0 animated:NO];
}
- (UIView<HWPanModalIndicatorProtocol> *)customIndicatorView {
if (!_indicator) _indicator = [KBDirectionIndicatorView new];
return _indicator;
}
- (void)panModalTransitionDidFinish {
// 初次展示后按当前状态设定一次朝向
[self.indicator applyPresentationState:self.hw_presentationState];
// 避免出现内容随弹窗上移的“位移动画”观感:
// 顶部栏在展示动画期间先隐藏,待完成后淡入
if (self.topBar && self.topBar.alpha < 1.0) {
[UIView animateWithDuration:0.18 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.topBar.alpha = 1.0;
} completion:nil];
}
}
- (void)didChangeTransitionToState:(PresentationState)state {
// // 每次状态切换完成后刷新朝向
// [self.indicator applyPresentationState:state];
}
- (PanModalHeight)shortFormHeight {
return PanModalHeightMake(PanModalHeightTypeContent, self.minHeight ?: 300);
}
- (PanModalHeight)longFormHeight {
return PanModalHeightMake(PanModalHeightTypeMaxTopInset, self.topInset ?: 100);
}
- (PresentationState)originPresentationState {
return PresentationStateShort; // 初始就以最小高度展示
}
- (BOOL)anchorModalToLongForm {
return YES; // 到 long 后不再继续往上拖
}
- (BOOL)allowsPullDownWhenShortState {
return NO; // 在 short 状态禁止继续往下拉(锁住最小高度)
}
/// 允许时间穿透
- (BOOL)allowsTouchEventsPassingThroughTransitionView {
return YES;
}
-(BOOL)shouldAutoSetPanScrollContentInset{
return NO;
}
- (UIScrollView *)panScrollable {
return self.hotVC.tableView;
}
// 可选:完全不允许拖拽关闭(避免被拉到底消失)
- (BOOL)allowsDragToDismiss {
return NO;
}
//
//- (BOOL)showDragIndicator{
// return NO;
//}
//
// 点背景不关闭
- (BOOL)allowsTapBackgroundToDismiss {
return NO;
}
// 出现时不做上推动画(瞬时到位)开了下拉动画有问题
//- (NSTimeInterval)transitionDuration {
// return 0;
//}
//// 可选:关闭触觉反馈,避免出现时的轻微震动
//- (BOOL)isHapticFeedbackEnabled {
// return NO;
//}
#pragma mark - UI
- (void)setupTopButtonsAndContainer {
// 顶部栏
self.topBar = [[UIView alloc] init];
self.topBar.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
[self.view addSubview:self.topBar];
// 首次展示时先隐藏,待转场完成后再淡入,避免“自底向上滑入”的错觉
self.topBar.alpha = 0.0;
// 两个按钮
self.hotButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.hotButton setTitle:KBLocalized(@"热门") forState:UIControlStateNormal];
[self.hotButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[self.hotButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
self.hotButton.titleLabel.font = [UIFont boldSystemFontOfSize:16];
self.hotButton.tag = 0;
[self.hotButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside];
[self.topBar addSubview:self.hotButton];
self.rankButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.rankButton setTitle:KBLocalized(@"排行") forState:UIControlStateNormal];
[self.rankButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
[self.rankButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
self.rankButton.titleLabel.font = [UIFont boldSystemFontOfSize:16];
self.rankButton.tag = 1;
[self.rankButton addTarget:self action:@selector(onTapTopButton:) forControlEvents:UIControlEventTouchUpInside];
[self.topBar addSubview:self.rankButton];
// 下划线(跟随选中按钮)
self.underlineView = [[UIView alloc] init];
self.underlineView.backgroundColor = [UIColor blackColor];
self.underlineView.layer.cornerRadius = 1.0;
[self.topBar addSubview:self.underlineView];
// 容器视图
self.containerView = [[UIView alloc] init];
self.containerView.backgroundColor = [UIColor whiteColor];
self.containerView.clipsToBounds = YES;
[self.view addSubview:self.containerView];
// Masonry 约束
CGFloat topPadding = 12; // 与顶部小指示器留点空间
[self.topBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.top.equalTo(self.view).offset(topPadding);
make.height.mas_equalTo(44);
}];
[self.hotButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self.topBar);
make.left.equalTo(self.topBar);
}];
[self.rankButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self.topBar);
make.right.equalTo(self.topBar);
make.left.equalTo(self.hotButton.mas_right);
make.width.equalTo(self.hotButton);
}];
// 初始先放在“热门”下方,宽度稍小于按钮文字
[self.underlineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(2);
make.bottom.equalTo(self.topBar.mas_bottom).offset(-2);
make.centerX.equalTo(self.hotButton);
make.width.mas_equalTo(24);
}];
[self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.topBar.mas_bottom).offset(8);
make.left.right.bottom.equalTo(self.view);
}];
}
#pragma mark - Action
- (void)onTapTopButton:(UIButton *)sender {
[self switchToIndex:sender.tag animated:YES];
[self hw_panModalSetNeedsLayoutUpdate];
}
#pragma mark - Switch Child
- (void)switchToIndex:(NSInteger)index animated:(BOOL)animated {
UIViewController *target = (index == 0) ? self.hotVC : self.rankVC;
if (!target) {
if (index == 0) {
self.hotVC = [HomeHotVC new];
target = self.hotVC;
} else {
self.rankVC = [HomeRankVC new];
target = self.rankVC;
}
}
if (self.currentChild == target) {
// 已经是目标
[self updateButtonStateForIndex:index animated:animated];
return;
}
// 移除当前
if (self.currentChild) {
[self.currentChild willMoveToParentViewController:nil];
[self.currentChild.view removeFromSuperview];
[self.currentChild removeFromParentViewController];
}
// 添加目标
[self addChildViewController:target];
[self.containerView addSubview:target.view];
target.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1];
[target.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.containerView);
}];
[target didMoveToParentViewController:self];
self.currentChild = target;
[self updateButtonStateForIndex:index animated:animated];
}
- (void)updateButtonStateForIndex:(NSInteger)index animated:(BOOL)animated {
self.hotButton.selected = (index == 0);
self.rankButton.selected = (index == 1);
UIButton *btn = (index == 0) ? self.hotButton : self.rankButton;
// 更新下划线位置
[self.underlineView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(2);
make.bottom.equalTo(self.topBar.mas_bottom).offset(-2);
make.centerX.equalTo(btn);
make.width.mas_equalTo(24);
}];
if (animated) {
[UIView animateWithDuration:0.25 animations:^{
[self.topBar layoutIfNeeded];
}];
} else {
[self.topBar layoutIfNeeded];
}
}
@end