2
This commit is contained in:
@@ -8,6 +8,11 @@
|
|||||||
#ifndef KBConfig_h
|
#ifndef KBConfig_h
|
||||||
#define KBConfig_h
|
#define KBConfig_h
|
||||||
|
|
||||||
|
// UIKit is needed for CGFloat and UIScreen used by size-adaptation helpers
|
||||||
|
#if __OBJC__
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// 基础baseUrl
|
// 基础baseUrl
|
||||||
#ifndef KB_BASE_URL
|
#ifndef KB_BASE_URL
|
||||||
#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/"
|
#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/"
|
||||||
@@ -45,6 +50,27 @@
|
|||||||
#define KB_APP_SCHEME @"kbkeyboardAppExtension"
|
#define KB_APP_SCHEME @"kbkeyboardAppExtension"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- 尺寸适配(以 375 设计稿为基准) ---
|
||||||
|
// 用法:传入设计稿上的数值,返回按当前屏幕宽度缩放后的值。
|
||||||
|
// 例如:CGFloat padding = KBFit(16);
|
||||||
|
#ifndef KB_DESIGN_WIDTH
|
||||||
|
#define KB_DESIGN_WIDTH 375.0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __OBJC__
|
||||||
|
static inline CGFloat KBScreenWidth(void) {
|
||||||
|
return [UIScreen mainScreen].bounds.size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CGFloat KBScaleFactor(void) {
|
||||||
|
return KBScreenWidth() / (CGFloat)KB_DESIGN_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline CGFloat KBFit(CGFloat designValue) {
|
||||||
|
return designValue * KBScaleFactor();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// --- 常用宏 ---
|
// --- 常用宏 ---
|
||||||
// 弱引用 self(在 block 中避免循环引用):使用处直接写 KBWeakSelf;
|
// 弱引用 self(在 block 中避免循环引用):使用处直接写 KBWeakSelf;
|
||||||
#ifndef KBWeakSelf
|
#ifndef KBWeakSelf
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; };
|
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; };
|
||||||
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF62EBC63A80055D639 /* KBTestVC.m */; };
|
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF62EBC63A80055D639 /* KBTestVC.m */; };
|
||||||
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF92EBC66340055D639 /* HomeHeadView.m */; };
|
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF92EBC66340055D639 /* HomeHeadView.m */; };
|
||||||
|
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFC2EBC6A170055D639 /* HomeHotVC.m */; };
|
||||||
|
0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDFF2EBC6A330055D639 /* HomeRankVC.m */; };
|
||||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
||||||
04A9FE132EB4D0D20020DB6D /* KBFullAccessManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.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 */; };
|
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04A9FE152EB873C80020DB6D /* UIViewController+Extension.m */; };
|
||||||
@@ -109,6 +111,10 @@
|
|||||||
0477BDF62EBC63A80055D639 /* KBTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTestVC.m; sourceTree = "<group>"; };
|
0477BDF62EBC63A80055D639 /* KBTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBTestVC.m; sourceTree = "<group>"; };
|
||||||
0477BDF82EBC66340055D639 /* HomeHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHeadView.h; sourceTree = "<group>"; };
|
0477BDF82EBC66340055D639 /* HomeHeadView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHeadView.h; sourceTree = "<group>"; };
|
||||||
0477BDF92EBC66340055D639 /* HomeHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHeadView.m; sourceTree = "<group>"; };
|
0477BDF92EBC66340055D639 /* HomeHeadView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHeadView.m; sourceTree = "<group>"; };
|
||||||
|
0477BDFB2EBC6A170055D639 /* HomeHotVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHotVC.h; sourceTree = "<group>"; };
|
||||||
|
0477BDFC2EBC6A170055D639 /* HomeHotVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHotVC.m; sourceTree = "<group>"; };
|
||||||
|
0477BDFE2EBC6A330055D639 /* HomeRankVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankVC.h; sourceTree = "<group>"; };
|
||||||
|
0477BDFF2EBC6A330055D639 /* HomeRankVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeRankVC.m; sourceTree = "<group>"; };
|
||||||
04A9A67D2EB9E1690023B8F4 /* KBResponderUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBResponderUtils.h; 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>"; };
|
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>"; };
|
04A9FE112EB4D0D20020DB6D /* KBFullAccessManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFullAccessManager.m; sourceTree = "<group>"; };
|
||||||
@@ -241,6 +247,19 @@
|
|||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
0477BE012EBC6D420055D639 /* FunctionTest */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0477BDF52EBC63A80055D639 /* KBTestVC.h */,
|
||||||
|
0477BDF62EBC63A80055D639 /* KBTestVC.m */,
|
||||||
|
A1B2D7002EB8C00100000001 /* KBLangTestVC.h */,
|
||||||
|
A1B2D7012EB8C00100000001 /* KBLangTestVC.m */,
|
||||||
|
0459D1B22EBA284C00F2D189 /* KBSkinCenterVC.h */,
|
||||||
|
0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */,
|
||||||
|
);
|
||||||
|
path = FunctionTest;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
04A9FE122EB4D0D20020DB6D /* Manager */ = {
|
04A9FE122EB4D0D20020DB6D /* Manager */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -363,14 +382,13 @@
|
|||||||
children = (
|
children = (
|
||||||
04FC95CD2EB1E7A1007BD342 /* HomeVC.h */,
|
04FC95CD2EB1E7A1007BD342 /* HomeVC.h */,
|
||||||
04FC95CE2EB1E7A1007BD342 /* HomeVC.m */,
|
04FC95CE2EB1E7A1007BD342 /* HomeVC.m */,
|
||||||
A1B2D7002EB8C00100000001 /* KBLangTestVC.h */,
|
|
||||||
A1B2D7012EB8C00100000001 /* KBLangTestVC.m */,
|
|
||||||
0459D1B22EBA284C00F2D189 /* KBSkinCenterVC.h */,
|
|
||||||
0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */,
|
|
||||||
0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */,
|
0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */,
|
||||||
0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */,
|
0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */,
|
||||||
0477BDF52EBC63A80055D639 /* KBTestVC.h */,
|
0477BDFB2EBC6A170055D639 /* HomeHotVC.h */,
|
||||||
0477BDF62EBC63A80055D639 /* KBTestVC.m */,
|
0477BDFC2EBC6A170055D639 /* HomeHotVC.m */,
|
||||||
|
0477BDFE2EBC6A330055D639 /* HomeRankVC.h */,
|
||||||
|
0477BDFF2EBC6A330055D639 /* HomeRankVC.m */,
|
||||||
|
0477BE012EBC6D420055D639 /* FunctionTest */,
|
||||||
);
|
);
|
||||||
path = VC;
|
path = VC;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -885,6 +903,7 @@
|
|||||||
files = (
|
files = (
|
||||||
04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */,
|
04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */,
|
||||||
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */,
|
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */,
|
||||||
|
0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */,
|
||||||
043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */,
|
043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */,
|
||||||
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */,
|
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */,
|
||||||
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
|
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
|
||||||
@@ -910,6 +929,7 @@
|
|||||||
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */,
|
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */,
|
||||||
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
||||||
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
||||||
|
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
|
||||||
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */,
|
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */,
|
||||||
04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */,
|
04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */,
|
||||||
04C6EAC12EAF86530089C901 /* ViewController.m in Sources */,
|
04C6EAC12EAF86530089C901 /* ViewController.m in Sources */,
|
||||||
|
|||||||
@@ -9,12 +9,11 @@
|
|||||||
|
|
||||||
@implementation HomeHeadView
|
@implementation HomeHeadView
|
||||||
|
|
||||||
/*
|
- (instancetype)initWithFrame:(CGRect)frame{
|
||||||
// Only override drawRect: if you perform custom drawing.
|
if (self = [super initWithFrame:frame]) {
|
||||||
// An empty implementation adversely affects performance during animation.
|
self.backgroundColor = [UIColor blueColor];
|
||||||
- (void)drawRect:(CGRect)rect {
|
}
|
||||||
// Drawing code
|
return self;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
16
keyBoard/Class/Home/VC/HomeHotVC.h
Normal file
16
keyBoard/Class/Home/VC/HomeHotVC.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// HomeHotVC.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/11/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface HomeHotVC : UIViewController
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
31
keyBoard/Class/Home/VC/HomeHotVC.m
Normal file
31
keyBoard/Class/Home/VC/HomeHotVC.m
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// HomeHotVC.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/11/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "HomeHotVC.h"
|
||||||
|
|
||||||
|
@interface HomeHotVC ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation HomeHotVC
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
// Do any additional setup after loading the view.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#pragma mark - Navigation
|
||||||
|
|
||||||
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||||
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||||
|
// Get the new view controller using [segue destinationViewController].
|
||||||
|
// Pass the selected object to the new view controller.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
16
keyBoard/Class/Home/VC/HomeRankVC.h
Normal file
16
keyBoard/Class/Home/VC/HomeRankVC.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// HomeRankVC.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/11/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface HomeRankVC : UIViewController
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
31
keyBoard/Class/Home/VC/HomeRankVC.m
Normal file
31
keyBoard/Class/Home/VC/HomeRankVC.m
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// HomeRankVC.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/11/6.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "HomeRankVC.h"
|
||||||
|
|
||||||
|
@interface HomeRankVC ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation HomeRankVC
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
// Do any additional setup after loading the view.
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#pragma mark - Navigation
|
||||||
|
|
||||||
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||||
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||||
|
// Get the new view controller using [segue destinationViewController].
|
||||||
|
// Pass the selected object to the new view controller.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -7,9 +7,24 @@
|
|||||||
|
|
||||||
#import "HomeSheetVC.h"
|
#import "HomeSheetVC.h"
|
||||||
#import "KBDirectionIndicatorView.h"
|
#import "KBDirectionIndicatorView.h"
|
||||||
|
// 子控制器
|
||||||
|
#import "HomeHotVC.h"
|
||||||
|
#import "HomeRankVC.h"
|
||||||
|
|
||||||
@interface HomeSheetVC ()
|
@interface HomeSheetVC ()
|
||||||
@property (nonatomic, strong) KBDirectionIndicatorView *indicator;
|
@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
|
@end
|
||||||
|
|
||||||
@implementation HomeSheetVC
|
@implementation HomeSheetVC
|
||||||
@@ -22,6 +37,11 @@
|
|||||||
config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
|
config = [HWBackgroundConfig configWithBehavior:HWBackgroundBehaviorDefault];
|
||||||
config.backgroundAlpha = 0.01;
|
config.backgroundAlpha = 0.01;
|
||||||
[self.hw_dimmedView reloadConfig:config];
|
[self.hw_dimmedView reloadConfig:config];
|
||||||
|
|
||||||
|
// 顶部按钮 + 容器
|
||||||
|
[self setupTopButtonsAndContainer];
|
||||||
|
// 默认展示“热门”
|
||||||
|
[self switchToIndex:0 animated:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIView<HWPanModalIndicatorProtocol> *)customIndicatorView {
|
- (UIView<HWPanModalIndicatorProtocol> *)customIndicatorView {
|
||||||
@@ -32,6 +52,13 @@
|
|||||||
- (void)panModalTransitionDidFinish {
|
- (void)panModalTransitionDidFinish {
|
||||||
// 初次展示后按当前状态设定一次朝向
|
// 初次展示后按当前状态设定一次朝向
|
||||||
[self.indicator applyPresentationState:self.hw_presentationState];
|
[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 {
|
- (void)didChangeTransitionToState:(PresentationState)state {
|
||||||
@@ -77,5 +104,157 @@
|
|||||||
return NO;
|
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:@"热门" 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.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];
|
||||||
|
}
|
||||||
|
|
||||||
|
#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
|
@end
|
||||||
|
|||||||
@@ -19,19 +19,22 @@
|
|||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
self.view.backgroundColor = [UIColor whiteColor];
|
self.view.backgroundColor = [UIColor whiteColor];
|
||||||
|
CGFloat topV = KBFit(500);
|
||||||
|
|
||||||
[self.view addSubview:self.headView];
|
[self.view addSubview:self.headView];
|
||||||
|
[self setupMas:topV];
|
||||||
// 创建sheetVC
|
// 创建sheetVC
|
||||||
HomeSheetVC *vc = [HomeSheetVC new];
|
HomeSheetVC *vc = [[HomeSheetVC alloc] init];
|
||||||
vc.minHeight = 300;
|
vc.minHeight = KB_SCREEN_HEIGHT - topV - 30;
|
||||||
vc.topInset = 100;
|
vc.topInset = 100;
|
||||||
[self presentPanModal:vc];
|
[self presentPanModal:vc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setupMas{
|
- (void)setupMas:(CGFloat)headViewTopV{
|
||||||
[self.headView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.headView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.right.equalTo(self.view);
|
make.left.right.equalTo(self.view);
|
||||||
make.top.equalTo(self.view);
|
make.top.equalTo(self.view);
|
||||||
|
make.height.mas_equalTo(headViewTopV);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user