This commit is contained in:
2025-11-06 16:05:28 +08:00
parent 41aec6b89e
commit 1f45564539
10 changed files with 395 additions and 15 deletions

View File

@@ -0,0 +1,19 @@
//
// KBPanModalView.h
// keyBoard
//
// Created by Mac on 2025/11/6.
//
#import <UIKit/UIKit.h>
#import <HWPanModal/HWPanModal.h>
#import "HWPanModalContentView.h"
NS_ASSUME_NONNULL_BEGIN
@interface KBPanModalView : HWPanModalContentView<HWPanModalPresentable>
@property (nonatomic, assign) CGFloat minHeight; // 例如 150
@property (nonatomic, assign) CGFloat topInset; // 例如 100
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,267 @@
//
// KBPanModalView.m
// keyBoard
//
// Created by Mac on 2025/11/6.
//
#import "KBPanModalView.h"
#import "KBDirectionIndicatorView.h"
//
#import "HomeHotVC.h"
#import "HomeRankVC.h"
@interface KBPanModalView()
@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 KBPanModalView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor redColor];
HWBackgroundConfig *config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
config.backgroundAlpha = 0.01;
[self.hw_dimmedView reloadConfig:config];
// +
[self setupTopButtonsAndContainer];
//
[self switchToIndex:0 animated:NO];
}
return self;
}
- (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 addSubview:self.topBar];
//
self.topBar.alpha = 0.0;
//
self.hotButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.hotButton setTitle:@"热门" 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:@"排行" 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 addSubview:self.containerView];
// Masonry
CGFloat topPadding = 12; //
[self.topBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.top.equalTo(self).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);
}];
}
#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