diff --git a/keyBoard/VC/KBPermissionViewController.m b/keyBoard/VC/KBPermissionViewController.m index ab41487..0f734e6 100644 --- a/keyBoard/VC/KBPermissionViewController.m +++ b/keyBoard/VC/KBPermissionViewController.m @@ -8,6 +8,8 @@ #import "KBPermissionViewController.h" #import +static void *KBPermPlayerPresentationSizeContext = &KBPermPlayerPresentationSizeContext; + @interface KBPermissionViewController () @property (nonatomic, strong) UILabel *titleLabel; // 标题 @property (nonatomic, strong) UILabel *tipsLabel; // 步骤提示 @@ -23,6 +25,9 @@ @property (nonatomic, strong) AVPlayer *kb_permPlayer; @property (nonatomic, strong) AVPlayerLayer *kb_permPlayerLayer; +// 承载视频的裁剪容器,高度固定为 KBFit(550),内部内容从顶部开始显示,超出的部分从底部裁剪 +@property (nonatomic, strong) UIView *videoContainerView; + @end @implementation KBPermissionViewController @@ -36,7 +41,7 @@ [self.view addSubview:self.closeButton]; [self.view addSubview:self.titleLabel]; [self.view addSubview:self.tipsLabel]; -// [self.view addSubview:self.videoContainerView]; + [self.view addSubview:self.videoContainerView]; [self.view addSubview:self.openButton]; [self.view addSubview:self.helpLabel]; @@ -70,13 +75,13 @@ 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); -// }]; + // 视频容器:左右各 25,顶部距离 tipsLabel 32,高度固定为 KBFit(550) + [self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.tipsLabel.mas_bottom).offset(32); + make.left.equalTo(self.view).offset(25); + make.right.equalTo(self.view).offset(-25); + make.height.mas_equalTo(KBFit(550)); + }]; [self.openButton mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM-20); @@ -107,13 +112,32 @@ - (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); + // 以「宽度」为基准等比缩放视频,高度按宽高比计算,从 videoContainerView 顶部对齐, + // 多出的部分由容器(固定高度 KBFit(550))从底部裁剪 + CGSize videoSize = self.kb_permPlayer.currentItem.presentationSize; + if (videoSize.width <= 0) { return; } // 尚未拿到真实尺寸时先不布局 + + CGFloat aspect = videoSize.height / videoSize.width; + CGRect containerBounds = self.videoContainerView.bounds; + if (CGRectIsEmpty(containerBounds)) { return; } + + CGFloat width = CGRectGetWidth(containerBounds); // 以容器宽度为基准 + CGFloat height = width * aspect; // 按宽度等比算出真实视频高度 + + // 顶部对齐,y = 0;若 height > 容器高度,则底部会被裁剪 + self.kb_permPlayerLayer.frame = CGRectMake(0, 0, width, height); } - (void)dealloc { // 移除通知监听 [[NSNotificationCenter defaultCenter] removeObserver:self]; + @try { + [self.kb_permPlayer.currentItem removeObserver:self + forKeyPath:@"presentationSize" + context:KBPermPlayerPresentationSizeContext]; + } @catch (__unused NSException *e) { + // ignore if observer not set + } } #pragma mark - Actions @@ -180,13 +204,18 @@ self.kb_permPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_permPlayer]; // 使用等比模式,按我们计算好的 frame 显示;多余部分由容器裁剪 - self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResize; + self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect; self.kb_permPlayerLayer.cornerRadius = 20; self.kb_permPlayerLayer.masksToBounds = true; - // 将视频图层插在按钮下面,保证按钮显示在视频之上 - CALayer *buttonLayer = self.openButton.layer; - [self.view.layer insertSublayer:self.kb_permPlayerLayer below:buttonLayer]; + // 将视频图层添加到裁剪容器内部,由容器控制圆角与裁剪 + [self.videoContainerView.layer addSublayer:self.kb_permPlayerLayer]; + + // 监听 presentationSize 变化,尺寸从 {0,0} 变为真实值时触发布局 + [item addObserver:self + forKeyPath:@"presentationSize" + options:NSKeyValueObservingOptionNew + context:KBPermPlayerPresentationSizeContext]; // 播放结束后从头循环 [[NSNotificationCenter defaultCenter] addObserver:self @@ -208,6 +237,20 @@ }]; } +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (context == KBPermPlayerPresentationSizeContext) { + // presentationSize 从 {0,0} 变为真实尺寸时,触发布局更新 + dispatch_async(dispatch_get_main_queue(), ^{ + [self.view setNeedsLayout]; + }); + return; + } + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; +} + #pragma mark - Lazy Subviews - (UIButton *)backButton { @@ -243,7 +286,6 @@ return _tipsLabel; } - - (UIButton *)openButton { if (!_openButton) { _openButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -286,6 +328,7 @@ } return _bgImageView; } + - (UIImageView *)redImageView{ if (!_redImageView) { _redImageView = [[UIImageView alloc] init]; @@ -294,4 +337,14 @@ return _redImageView; } +- (UIView *)videoContainerView { + if (!_videoContainerView) { + _videoContainerView = [UIView new]; + _videoContainerView.backgroundColor = [UIColor clearColor]; + _videoContainerView.layer.cornerRadius = 20.0; + _videoContainerView.clipsToBounds = YES; // 超出容器高度的部分直接裁剪 + } + return _videoContainerView; +} + @end