// // KBPermissionViewController.m // CustomKeyboard // // Created by Mac on 2025/10/27. // #import "KBPermissionViewController.h" #import @interface KBPermissionViewController () @property (nonatomic, strong) UILabel *titleLabel; // 标题 @property (nonatomic, strong) UILabel *tipsLabel; // 步骤提示 @property (nonatomic, strong) UIButton *openButton; // 去设置 @property (nonatomic, strong) UIButton *closeButton; // 去设置 @property (nonatomic, strong) UILabel *helpLabel; // 底部帮助 @property (nonatomic, strong) UIImageView *redImageView; @property (nonatomic, strong) UIImageView *bgImageView; // 权限引导视频播放器(循环播放,不提供暂停交互) @property (nonatomic, strong) AVPlayer *kb_permPlayer; @property (nonatomic, strong) AVPlayerLayer *kb_permPlayerLayer; @end @implementation KBPermissionViewController - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.bgImageView]; [self.view addSubview:self.redImageView]; // 懒加载控件 + 添加到视图 [self.view addSubview:self.closeButton]; [self.view addSubview:self.titleLabel]; [self.view addSubview:self.tipsLabel]; // [self.view addSubview:self.videoContainerView]; [self.view addSubview:self.openButton]; [self.view addSubview:self.helpLabel]; [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; // Masonry 约束 [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).offset(16); make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(20); make.width.mas_equalTo(26); make.height.mas_equalTo(26); }]; [self.redImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.closeButton.mas_centerY); make.right.equalTo(self.view).offset(20); make.width.mas_equalTo(143); make.height.mas_equalTo(132); }]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.closeButton.mas_bottom).offset(13); make.left.equalTo(self.view).offset(22); make.height.mas_equalTo(24); }]; [self.tipsLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.titleLabel.mas_bottom).offset(8); make.left.equalTo(self.titleLabel); }]; // 视频容器:左右距离 view 16,顶部距离 tipsLabel 30,底部距离按钮 36 // [self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) { // make.top.equalTo(self.tipsLabel.mas_bottom).offset(30); // make.left.equalTo(self.view).offset(16); // make.right.equalTo(self.view).offset(-16); // make.bottom.equalTo(self.openButton.mas_top).offset(-36); // }]; [self.openButton mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM-20); make.left.equalTo(self.view).offset(47); make.right.equalTo(self.view).offset(-47); make.height.mas_equalTo(60); }]; // [self.helpLabel mas_makeConstraints:^(MASConstraintMaker *make) { // make.top.equalTo(self.openButton.mas_bottom).offset(12); // make.left.equalTo(self.view).offset(24); // make.right.equalTo(self.view).offset(-24); // }]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // 进入页面时自动开始播放 [self kb_setupPermissionVideoPlayer]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; // 页面离开时停止播放,避免声音继续在其他界面播放 [self.kb_permPlayer pause]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; if (!self.kb_permPlayerLayer) { return; } // 直接铺满整个视图区域,由 videoGravity 负责等比缩放 self.kb_permPlayerLayer.frame = CGRectMake(25, CGRectGetMaxY(self.tipsLabel.frame) + 32, KB_SCREEN_WIDTH - 50, 700); } - (void)dealloc { // 移除通知监听 [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Actions - (void)onBack { // 支持两种展示方式: // 1) 作为子控制器嵌入(无 presentingViewController)→ 交由回调让父 VC 处理(通常 pop) // 2) 作为模态弹出 → 按原策略先 pop 再 dismiss UIViewController *presenter = self.presentingViewController; if (!presenter) { if (self.backHandler) self.backHandler(); return; } UINavigationController *nav = nil; if ([presenter isKindOfClass:UINavigationController.class]) { nav = (UINavigationController *)presenter; } else if (presenter.navigationController) { nav = presenter.navigationController; } if (nav) { [nav popViewControllerAnimated:NO]; [nav dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; } else { [self dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; } } - (void)openSettings { NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; UIApplication *app = [UIApplication sharedApplication]; if ([app canOpenURL:url]) { if (@available(iOS 10.0, *)) { [app openURL:url options:@{} completionHandler:nil]; } else { [app openURL:url]; } } } - (void)closeButtonAction{ [self.navigationController popViewControllerAnimated:true]; } #pragma mark - Video Player // 初始化并开始在 cardView 中循环播放视频 - (void)kb_setupPermissionVideoPlayer { // 避免重复初始化 if (self.kb_permPlayer) { [self.kb_permPlayer play]; return; } NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"permiss_video" withExtension:@"mp4"]; if (!videoURL) { return; } AVPlayerItem *item = [AVPlayerItem playerItemWithURL:videoURL]; self.kb_permPlayer = [AVPlayer playerWithPlayerItem:item]; self.kb_permPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; self.kb_permPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_permPlayer]; // 使用等比模式,按我们计算好的 frame 显示;多余部分由容器裁剪 self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResize; self.kb_permPlayerLayer.cornerRadius = 20; self.kb_permPlayerLayer.masksToBounds = true; // 将视频图层插在按钮下面,保证按钮显示在视频之上 CALayer *buttonLayer = self.openButton.layer; [self.view.layer insertSublayer:self.kb_permPlayerLayer below:buttonLayer]; // 播放结束后从头循环 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:item]; [self.kb_permPlayer play]; } - (void)kb_playerItemDidReachEnd:(NSNotification *)note { AVPlayerItem *item = (AVPlayerItem *)note.object; if (!item) return; __weak typeof(self) weakSelf = self; [item seekToTime:kCMTimeZero completionHandler:^(BOOL finished) { __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf.kb_permPlayer play]; }]; } #pragma mark - Lazy Subviews - (UIButton *)backButton { if (!_backButton) { _backButton = [UIButton buttonWithType:UIButtonTypeSystem]; [_backButton setTitle:KBLocalized(@"common_back") forState:UIControlStateNormal]; _backButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; [_backButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal]; [_backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside]; } return _backButton; } - (UILabel *)titleLabel { if (!_titleLabel) { _titleLabel = [UILabel new]; _titleLabel.text = (@"key of love keyboard"); _titleLabel.font = [UIFont systemFontOfSize:20 weight:UIFontWeightSemibold]; _titleLabel.textColor = [UIColor blackColor]; _titleLabel.textAlignment = NSTextAlignmentCenter; } return _titleLabel; } - (UILabel *)tipsLabel { if (!_tipsLabel) { _tipsLabel = [UILabel new]; _tipsLabel.text = (@"One-click to find a partner"); _tipsLabel.font = [UIFont systemFontOfSize:14]; _tipsLabel.textColor = [UIColor darkGrayColor]; _tipsLabel.textAlignment = NSTextAlignmentCenter; } return _tipsLabel; } - (UIButton *)openButton { if (!_openButton) { _openButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_openButton setTitle:@"Turn on the keyboard" forState:UIControlStateNormal]; _openButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; [_openButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; _openButton.backgroundColor = [UIColor colorWithHex:KBBlackValue]; _openButton.layer.cornerRadius = 30; [_openButton addTarget:self action:@selector(openSettings) forControlEvents:UIControlEventTouchUpInside]; } return _openButton; } - (UIButton *)closeButton { if (!_closeButton) { _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_closeButton setImage:[UIImage imageNamed:@"close_icon"] forState:UIControlStateNormal]; [_closeButton addTarget:self action:@selector(closeButtonAction) forControlEvents:UIControlEventTouchUpInside]; } return _closeButton; } - (UILabel *)helpLabel { if (!_helpLabel) { _helpLabel = [UILabel new]; _helpLabel.text = KBLocalized(@"perm_help"); _helpLabel.font = [UIFont systemFontOfSize:12]; _helpLabel.textColor = [UIColor grayColor]; _helpLabel.textAlignment = NSTextAlignmentCenter; _helpLabel.numberOfLines = 2; } return _helpLabel; } - (UIImageView *)bgImageView{ if (!_bgImageView) { _bgImageView = [[UIImageView alloc] init]; _bgImageView.image = [UIImage imageNamed:@"qx_bg_icon"]; } return _bgImageView; } - (UIImageView *)redImageView{ if (!_redImageView) { _redImageView = [[UIImageView alloc] init]; _redImageView.image = [UIImage imageNamed:@"qx_ax_icon"]; } return _redImageView; } @end