1
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
#import "KBPermissionViewController.h"
|
#import "KBPermissionViewController.h"
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
static void *KBPermPlayerPresentationSizeContext = &KBPermPlayerPresentationSizeContext;
|
||||||
|
|
||||||
@interface KBPermissionViewController ()
|
@interface KBPermissionViewController ()
|
||||||
@property (nonatomic, strong) UILabel *titleLabel; // 标题
|
@property (nonatomic, strong) UILabel *titleLabel; // 标题
|
||||||
@property (nonatomic, strong) UILabel *tipsLabel; // 步骤提示
|
@property (nonatomic, strong) UILabel *tipsLabel; // 步骤提示
|
||||||
@@ -23,6 +25,9 @@
|
|||||||
@property (nonatomic, strong) AVPlayer *kb_permPlayer;
|
@property (nonatomic, strong) AVPlayer *kb_permPlayer;
|
||||||
@property (nonatomic, strong) AVPlayerLayer *kb_permPlayerLayer;
|
@property (nonatomic, strong) AVPlayerLayer *kb_permPlayerLayer;
|
||||||
|
|
||||||
|
// 承载视频的裁剪容器,高度固定为 KBFit(550),内部内容从顶部开始显示,超出的部分从底部裁剪
|
||||||
|
@property (nonatomic, strong) UIView *videoContainerView;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation KBPermissionViewController
|
@implementation KBPermissionViewController
|
||||||
@@ -36,7 +41,7 @@
|
|||||||
[self.view addSubview:self.closeButton];
|
[self.view addSubview:self.closeButton];
|
||||||
[self.view addSubview:self.titleLabel];
|
[self.view addSubview:self.titleLabel];
|
||||||
[self.view addSubview:self.tipsLabel];
|
[self.view addSubview:self.tipsLabel];
|
||||||
// [self.view addSubview:self.videoContainerView];
|
[self.view addSubview:self.videoContainerView];
|
||||||
[self.view addSubview:self.openButton];
|
[self.view addSubview:self.openButton];
|
||||||
[self.view addSubview:self.helpLabel];
|
[self.view addSubview:self.helpLabel];
|
||||||
|
|
||||||
@@ -70,13 +75,13 @@
|
|||||||
make.left.equalTo(self.titleLabel);
|
make.left.equalTo(self.titleLabel);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// 视频容器:左右距离 view 16,顶部距离 tipsLabel 30,底部距离按钮 36
|
// 视频容器:左右各 25,顶部距离 tipsLabel 32,高度固定为 KBFit(550)
|
||||||
// [self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
// make.top.equalTo(self.tipsLabel.mas_bottom).offset(30);
|
make.top.equalTo(self.tipsLabel.mas_bottom).offset(32);
|
||||||
// make.left.equalTo(self.view).offset(16);
|
make.left.equalTo(self.view).offset(25);
|
||||||
// make.right.equalTo(self.view).offset(-16);
|
make.right.equalTo(self.view).offset(-25);
|
||||||
// make.bottom.equalTo(self.openButton.mas_top).offset(-36);
|
make.height.mas_equalTo(KBFit(550));
|
||||||
// }];
|
}];
|
||||||
|
|
||||||
[self.openButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.openButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM-20);
|
make.bottom.equalTo(self.view).offset(-KB_SAFE_BOTTOM-20);
|
||||||
@@ -107,13 +112,32 @@
|
|||||||
- (void)viewDidLayoutSubviews {
|
- (void)viewDidLayoutSubviews {
|
||||||
[super viewDidLayoutSubviews];
|
[super viewDidLayoutSubviews];
|
||||||
if (!self.kb_permPlayerLayer) { return; }
|
if (!self.kb_permPlayerLayer) { return; }
|
||||||
// 直接铺满整个视图区域,由 videoGravity 负责等比缩放
|
// 以「宽度」为基准等比缩放视频,高度按宽高比计算,从 videoContainerView 顶部对齐,
|
||||||
self.kb_permPlayerLayer.frame = CGRectMake(25, CGRectGetMaxY(self.tipsLabel.frame) + 32, KB_SCREEN_WIDTH - 50, 700);
|
// 多出的部分由容器(固定高度 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 {
|
- (void)dealloc {
|
||||||
// 移除通知监听
|
// 移除通知监听
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[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
|
#pragma mark - Actions
|
||||||
@@ -180,13 +204,18 @@
|
|||||||
|
|
||||||
self.kb_permPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_permPlayer];
|
self.kb_permPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.kb_permPlayer];
|
||||||
// 使用等比模式,按我们计算好的 frame 显示;多余部分由容器裁剪
|
// 使用等比模式,按我们计算好的 frame 显示;多余部分由容器裁剪
|
||||||
self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResize;
|
self.kb_permPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
|
||||||
self.kb_permPlayerLayer.cornerRadius = 20;
|
self.kb_permPlayerLayer.cornerRadius = 20;
|
||||||
self.kb_permPlayerLayer.masksToBounds = true;
|
self.kb_permPlayerLayer.masksToBounds = true;
|
||||||
|
|
||||||
// 将视频图层插在按钮下面,保证按钮显示在视频之上
|
// 将视频图层添加到裁剪容器内部,由容器控制圆角与裁剪
|
||||||
CALayer *buttonLayer = self.openButton.layer;
|
[self.videoContainerView.layer addSublayer:self.kb_permPlayerLayer];
|
||||||
[self.view.layer insertSublayer:self.kb_permPlayerLayer below:buttonLayer];
|
|
||||||
|
// 监听 presentationSize 变化,尺寸从 {0,0} 变为真实值时触发布局
|
||||||
|
[item addObserver:self
|
||||||
|
forKeyPath:@"presentationSize"
|
||||||
|
options:NSKeyValueObservingOptionNew
|
||||||
|
context:KBPermPlayerPresentationSizeContext];
|
||||||
|
|
||||||
// 播放结束后从头循环
|
// 播放结束后从头循环
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
@@ -208,6 +237,20 @@
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||||
|
ofObject:(id)object
|
||||||
|
change:(NSDictionary<NSKeyValueChangeKey,id> *)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
|
#pragma mark - Lazy Subviews
|
||||||
|
|
||||||
- (UIButton *)backButton {
|
- (UIButton *)backButton {
|
||||||
@@ -243,7 +286,6 @@
|
|||||||
return _tipsLabel;
|
return _tipsLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (UIButton *)openButton {
|
- (UIButton *)openButton {
|
||||||
if (!_openButton) {
|
if (!_openButton) {
|
||||||
_openButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
_openButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
@@ -286,6 +328,7 @@
|
|||||||
}
|
}
|
||||||
return _bgImageView;
|
return _bgImageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIImageView *)redImageView{
|
- (UIImageView *)redImageView{
|
||||||
if (!_redImageView) {
|
if (!_redImageView) {
|
||||||
_redImageView = [[UIImageView alloc] init];
|
_redImageView = [[UIImageView alloc] init];
|
||||||
@@ -294,4 +337,14 @@
|
|||||||
return _redImageView;
|
return _redImageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UIView *)videoContainerView {
|
||||||
|
if (!_videoContainerView) {
|
||||||
|
_videoContainerView = [UIView new];
|
||||||
|
_videoContainerView.backgroundColor = [UIColor clearColor];
|
||||||
|
_videoContainerView.layer.cornerRadius = 20.0;
|
||||||
|
_videoContainerView.clipsToBounds = YES; // 超出容器高度的部分直接裁剪
|
||||||
|
}
|
||||||
|
return _videoContainerView;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user