hyzp_ybqx-Commit001:代码刚转换好,编译通过

This commit is contained in:
WinUser01
2021-12-09 20:24:36 +08:00
commit 8c74b14e5c
800 changed files with 66912 additions and 0 deletions
@@ -0,0 +1,31 @@
//
// NSString+URL.h
// SuperPlayer
//
// Created by xcoderliu on 12/10/20.
// Copyright © 2020 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (URL)
/// 获取 URL GET 参数
/// @param parameter key
/// @param originUrl url
+ (NSString *)getParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl;
/// 删除 URL GET 参数
/// @param parameter key
/// @param originUrl url
+ (NSString *)deleteParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl;
/// 追加 URL GET 参数
/// @param queryString (@"key=value")
/// @param originUrl url
+ (NSString *)appendParameter:(NSString *)queryString WithOriginUrl:(NSString *)originUrl;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,54 @@
//
// NSString+URL.m
// SuperPlayer
//
// Created by xcoderliu on 12/10/20.
// Copyright © 2020 annidy. All rights reserved.
//
#import "NSString+URL.h"
@implementation NSString (URL)
+ (NSString *)getParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl {
NSError *error;
if (originUrl.length == 0) {
return @"";
}
NSString *regTags = [[NSString alloc] initWithFormat:@"(^|&|\\?)+%@=+([^&]*)(&|$)",parameter];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regTags options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:originUrl options:0 range:NSMakeRange(0, [originUrl length])];
for (NSTextCheckingResult *match in matches) {
NSString *tagValue = [originUrl substringWithRange:[match rangeAtIndex:2]];
return tagValue;
}
return @"";
}
+ (NSString *)deleteParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl {
NSString *finalStr = [NSString string];
NSMutableString * mutStr = [NSMutableString stringWithString:originUrl];
NSArray *strArray = [mutStr componentsSeparatedByString:parameter];
NSMutableString *firstStr = [strArray objectAtIndex:0];
NSMutableString *lastStr = [strArray lastObject];
NSRange characterRange = [lastStr rangeOfString:@"&"];
if (characterRange.location !=NSNotFound) {
NSArray *lastArray = [lastStr componentsSeparatedByString:@"&"];
NSMutableArray *mutArray = [NSMutableArray arrayWithArray:lastArray];
[mutArray removeObjectAtIndex:0];
NSString *modifiedStr = [mutArray componentsJoinedByString:@"&"];
finalStr = [[strArray objectAtIndex:0]stringByAppendingString:modifiedStr];
} else {
finalStr = [firstStr substringToIndex:[firstStr length] -1];
}
return finalStr;
}
+ (NSString *)appendParameter:(NSString *)queryString WithOriginUrl:(NSString *)originUrl {
if (![queryString length]) {
return originUrl;
}
return [NSString stringWithFormat:@"%@%@%@", originUrl,
[originUrl rangeOfString:@"?"].length > 0 ? @"&" : @"?", queryString];
}
@end
@@ -0,0 +1,6 @@
#import <UIKit/UIKit.h>
@interface UINavigationController (SuperPlayerRotation)<UIGestureRecognizerDelegate>
@end
@@ -0,0 +1,34 @@
#import "UINavigationController+SuperPlayerRotation.h"
#import <objc/runtime.h>
@implementation UINavigationController (SuperPlayerRotation)
/**
* 如果window的根视图是UINavigationController,则会先调用这个Category,然后调用UIViewController+SuperPlayerRotation
* 只需要在支持除竖屏以外方向的页面重新下边三个方法
*/
// 是否支持自动转屏
- (BOOL)shouldAutorotate {
return [self.topViewController shouldAutorotate];
}
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
@@ -0,0 +1,93 @@
//
// UIView+MM.h
/*
杜蒙 iOS开发
annidy
*/
#define m_weakify(object) autoreleasepool {} __weak typeof(object) weak##object = object
#define m_strongify(object) autoreleasepool {} __strong typeof(weak##object) object = weak##object
#import <UIKit/UIKit.h>
@class MMLayout;
@interface UIView (Layout)
@property (strong , nonatomic , readonly) MMLayout *mm_selfLayout;
- (void)setMm_x:(CGFloat)mm_x; ///<< set frame.x
- (CGFloat)mm_x; ///<< get frame.x
- (void)setMm_y:(CGFloat)mm_y; ///<< set frame.y
- (CGFloat)mm_y; ///<< get frame.y
- (void)setMm_w:(CGFloat)mm_w; ///<< set frame.bounds.size.width
- (CGFloat)mm_w; ///<< get frame.bounds.size.width
- (void)setMm_h:(CGFloat)mm_h; ///<< set frame.bounds.size.height
- (CGFloat)mm_h; ///<< get frame.bounds.size.height
- (void)setMm_center:(CGPoint )mm_center; ///<< set frame.origin
- (CGPoint)mm_center; ///<< get frame origin
- (CGFloat)mm_centerX; ///<< get self.center.x
- (CGFloat)mm_centerY; ///<< get self.center.y
- (CGFloat)mm_maxY; ///<< get CGRectGetMaxY
- (CGFloat)mm_minY; ///<< get CGRectGetMinY
- (CGFloat)mm_maxX; ///<< get CGRectGetMaxX
- (CGFloat)mm_minX; ///<< get CGRectGetMinX
- (CGFloat)mm_halfW; ///<< get self.width / 2
- (CGFloat)mm_halfH; ///<< get self.height / 2
- (CGFloat)mm_halfX; ///<< get self.x / 2
- (CGFloat)mm_halfY; ///<< get self.y / 2
- (CGFloat)mm_halfCenterX; ///<< get self.centerX / 2
- (CGFloat)mm_halfCenterY; ///<< get self.centerY / 2
- (void)setMm_size:(CGSize)mm_size;
- (CGSize)mm_size; ///<< get self.bounds.size
// iPhoneX adapt
@property (readonly) CGFloat mm_safeAreaBottomGap;
@property (readonly) CGFloat mm_safeAreaTopGap;
@property (readonly) CGFloat mm_safeAreaLeftGap;
@property (readonly) CGFloat mm_safeAreaRightGap;
/*
示例链接编程
self.m_width(100).m_height(100).m_left(10).m_top(10)
*/
- (UIView * (^)(CGFloat top))m_top; ///< set frame y
- (UIView * (^)(CGFloat right))m_flexToTop; ///< set frame y by change height
- (UIView * (^)(CGFloat bottom))m_bottom; ///< set frame y
- (UIView * (^)(CGFloat right))m_flexToBottom; ///< set frame y by change height
- (UIView * (^)(CGFloat left))m_left; ///< set frame x
- (UIView * (^)(CGFloat right))m_flexToLeft; ///< set frame right by chang width
- (UIView * (^)(CGFloat right))m_right; ///< set frame x
- (UIView * (^)(CGFloat right))m_flexToRight; ///< set frame right by chang width
- (UIView * (^)(CGFloat width))m_width; ///< set frame width
- (UIView * (^)(CGFloat height))m_height; ///< set frame height
- (UIView * (^)(CGSize size))m_size; ///< set frame size
- (UIView * (^)(CGPoint center))m__center; ///< set frame center point
- (UIView * (^)(void))m_center; ///< set frame center 前提是有w h 调用次方法居中父类
- (UIView * (^)(void))m_centerY; ///< set frame Ycenter 前提是有h调用次方法居中父类
- (UIView * (^)(void))m_centerX; ///< set frame Xcenter 前提是有w调用次方法居中父类
/*
相对父View
*/
-(UIView *(^)(void))m_fill; ///< 填充
- (UIView * (^)(UIView *obj))m_equalToFrame; /// equalTo frame
- (UIView * (^)(UIView *obj))m_equalToTop; /// equalTo top
- (UIView * (^)(UIView *obj))m_equalToBottom; /// equalTo Bottom
- (UIView * (^)(UIView *obj))m_equalToLeft; /// equalTo left
- (UIView * (^)(UIView *obj))m_equalToRight; /// equalTo right
- (UIView * (^)(UIView *obj))m_equalToWidth; /// equalTo width
- (UIView * (^)(UIView *obj))m_equalToHeight; /// equalTo height
- (UIView * (^)(UIView *obj))m_equalToSize; /// equalTo size
- (UIView * (^)(UIView *obj))m_equalToCenter; /// equalTo center
- (UIView * (^)(void))m_sizeToFit; /// call sizeToFit
- (NSData *)mm_createPDF;/// create self PDF
- (UIViewController *)viewController; //self Responder UIViewControler
@end
@@ -0,0 +1,525 @@
#import "UIView+MMLayout.h"
#import <objc/runtime.h>
#pragma mark - MMLayout
@interface MMLayout : NSObject
/*
@LayoutView 传入进去 View
*/
-(instancetype)initWithLayoutView:(UIView *)LayoutView;
@property (assign , nonatomic) CGFloat top; ///<< frame y
@property (assign , nonatomic) CGFloat bottom; ///<< y = super.h - LayoutView.h - bottom
@property (assign , nonatomic) CGFloat left; ///<< frame x
@property (assign , nonatomic) CGFloat right; ///<< x = super.w - LayoutView.h - right
@property (assign , nonatomic) CGFloat width; ///<< frame w
@property (assign , nonatomic) CGFloat height; ///<< frame height
@property (assign , nonatomic) CGSize size; ///<< frame bounds size width height
@property (assign , nonatomic) CGPoint point; ///<< frame point
- (void)center; ///<<调用此方法前必须先设置自己的宽高 (默认是居中父控件)
- (void)centerX; ///<<调用此方法前必须先设置自己的宽 (默认是居中父控件)
- (void)centerY; ///<<调用此方法前必须先设置自己的高 (默认是居中父控件)
@property (weak , nonatomic) UIView *layoutView;
@end
@implementation MMLayout
-(instancetype)initWithLayoutView:(UIView *)LayoutView{
if (self=[super init]) {
self.layoutView = LayoutView;
}
return self;
}
-(void)setLeft:(CGFloat)left{
CGRect frame = self.layoutView.frame;
frame.origin.x = left;
self.layoutView.frame = frame;
}
- (CGFloat)left {
return self.layoutView.frame.origin.x;
}
-(void)setTop:(CGFloat)top{
_top = top;
CGRect frame = self.layoutView.frame;
frame.origin.y = top;
self.layoutView.frame = frame;
}
-(void)setRight:(CGFloat)right{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_w - self.layoutView.mm_w - right;
}
- (CGFloat)right {
UIView *superview = self.layoutView.superview;
return superview.mm_w - self.layoutView.mm_x - self.layoutView.mm_w;
}
-(void)setBottom:(CGFloat)bottom{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_y = superview.mm_h - self.layoutView.mm_h - bottom;
}
- (CGFloat)bottom {
UIView *superview = self.layoutView.superview;
return superview.mm_h - self.layoutView.mm_maxY;
}
-(void)setHeight:(CGFloat)height{
_height = height;
CGRect frame = self.layoutView.frame;
frame.size.height = height;
self.layoutView.frame = frame;
}
-(void)setWidth:(CGFloat)width{
_width = width;
CGRect frame = self.layoutView.frame;
frame.size.width = width;
self.layoutView.frame = frame;
}
-(void)setPoint:(CGPoint)point{
CGRect frame = self.layoutView.frame;
frame.origin = point;
self.layoutView.frame = frame;
}
-(CGPoint)point{
return CGPointMake(self.layoutView.mm_x, self.layoutView.mm_w);
}
-(void)setSize:(CGSize )size{
CGRect frame = self.layoutView.frame;
frame.size = size;
self.layoutView.frame = frame;
}
-(CGSize)size{
return self.layoutView.mm_size;
}
-(void)setCenter:(CGPoint)center{
CGRect frame = self.layoutView.frame;
frame.origin = CGPointMake(center.x-frame.size.width/2, center.y-frame.size.height/2);
self.layoutView.frame = frame;
}
-(void)center{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_halfW - self.layoutView.mm_halfW;
self.layoutView.mm_y = superview.mm_halfH - self.layoutView.mm_halfH;
}
-(void)centerY{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_y = superview.mm_halfH - self.layoutView.mm_halfH;
}
-(void)centerX{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_halfW - self.layoutView.mm_halfW;
}
@end
const void *_layoutKey;
@implementation UIView (Layout)
#pragma mark - frame
- (void)setMm_x:(CGFloat)mm_x{
[self mm_selfLayout].left = mm_x;
}
- (CGFloat)mm_x{
return self.frame.origin.x;
}
- (void)setMm_y:(CGFloat)mm_y{
[self mm_selfLayout].top = mm_y;
}
- (CGFloat)mm_y{
return self.frame.origin.y;
}
- (void)setMm_w:(CGFloat)mm_w{
[self mm_selfLayout].width = mm_w;
}
- (CGFloat)mm_w{
return self.frame.size.width;
}
- (void)setMm_h:(CGFloat)mm_h{
[self mm_selfLayout].height = mm_h;
}
- (CGFloat)mm_h{
return self.frame.size.height;
}
-(void)setMm_center:(CGPoint)mm_center{
[self mm_selfLayout].point = mm_center;
}
-(CGPoint)mm_center{
return self.frame.origin;
}
-(CGFloat)mm_centerX{
return self.center.x;
}
-(CGFloat)mm_centerY{
return self.center.y;
}
- (CGFloat)mm_maxY{
return CGRectGetMaxY(self.frame);
}
- (CGFloat)mm_minY{
return CGRectGetMinY(self.frame);
}
- (CGFloat)mm_maxX{
return CGRectGetMaxX(self.frame);
}
- (CGFloat)mm_minX{
return CGRectGetMinX(self.frame);
}
- (CGFloat)mm_halfW{
return self.mm_w / 2;
}
- (CGFloat)mm_halfH{
return self.mm_h / 2;
}
- (CGFloat)mm_halfX{
return self.mm_x / 2;
}
- (CGFloat)mm_halfY{
return self.mm_y / 2;
}
-(CGFloat)mm_halfCenterX{
return self.mm_centerX / 2;
}
-(CGFloat)mm_halfCenterY{
return self.mm_centerY / 2;
}
-(void)setMm_size:(CGSize)mm_size{
[self mm_selfLayout].size = mm_size;
}
-(CGSize)mm_size{
return self.bounds.size;
}
#pragma mark - set_ frame
- (MMLayout *)mm_selfLayout{
MMLayout *layout = objc_getAssociatedObject(self, &_layoutKey);
if (layout == nil) {
layout = [[MMLayout alloc] initWithLayoutView:self];
objc_setAssociatedObject(self, &_layoutKey, layout, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return layout;
}
-(UIView *(^)(CGFloat))m_top{
@m_weakify(self);
return ^(CGFloat m_top){
@m_strongify(self);
[self mm_selfLayout].top = m_top;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToTop{
@m_weakify(self);
return ^(CGFloat m_flexToTop){
@m_strongify(self);
CGFloat top = [self mm_selfLayout].top;
[self mm_selfLayout].top = m_flexToTop;
[self mm_selfLayout].height += top-m_flexToTop;
return self;
};
}
-(UIView *(^)(CGFloat))m_bottom{
@m_weakify(self);
return ^(CGFloat m_bottom){
@m_strongify(self);
[self mm_selfLayout].bottom = m_bottom;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToBottom{
@m_weakify(self);
return ^(CGFloat m_flexToBottom){
@m_strongify(self);
CGFloat bottom = [self mm_selfLayout].bottom;
[self mm_selfLayout].height += bottom-m_flexToBottom;
return self;
};
}
-(UIView *(^)(CGFloat))m_left{
@m_weakify(self);
return ^(CGFloat m_left){
@m_strongify(self);
[self mm_selfLayout].left = m_left;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToLeft{
@m_weakify(self);
return ^(CGFloat m_flexToLeft){
@m_strongify(self);
CGFloat left = [self mm_selfLayout].left;
[self mm_selfLayout].left = m_flexToLeft;
[self mm_selfLayout].width += left-m_flexToLeft;
return self;
};
}
-(UIView *(^)(CGFloat))m_right{
@m_weakify(self);
return ^(CGFloat m_right){
@m_strongify(self);
[self mm_selfLayout].right = m_right;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToRight{
@m_weakify(self);
return ^(CGFloat m_flexToRight){
@m_strongify(self);
CGFloat right = [self mm_selfLayout].right;
[self mm_selfLayout].width += right-m_flexToRight;
return self;
};
}
-(UIView *(^)(CGFloat))m_width{
@m_weakify(self);
return ^(CGFloat m_width){
@m_strongify(self);
[self mm_selfLayout].width = m_width;
return self;
};
}
-(UIView *(^)(CGFloat))m_height{
@m_weakify(self);
return ^(CGFloat m_height){
@m_strongify(self);
[self mm_selfLayout].height = m_height;
return self;
};
}
-(UIView *(^)(CGSize))m_size{
@m_weakify(self);
return ^(CGSize m_size){
@m_strongify(self);
[self mm_selfLayout].size = m_size;
return self;
};
}
- (UIView *(^)(CGPoint))m__center{
@m_weakify(self);
return ^(CGPoint m__center){
@m_strongify(self);
[self mm_selfLayout].center = m__center;
return self;
};
}
-(UIView *(^)(void))m_center{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] center];
return self;
};
}
-(UIView *(^)(void))m_centerY{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] centerY];
return self;
};
}
-(UIView *(^)(void))m_centerX{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] centerX];
return self;
};
}
-(UIView *(^)(void))m_fill {
@m_weakify(self);
return ^{
@m_strongify(self);
if (self.superview) {
self.mm_x = self.mm_y = 0;
self.mm_w = self.superview.mm_w;
self.mm_h = self.superview.mm_h;
}
return self;
};
}
#pragma mark - m_equalTo
-(UIView *(^)(UIView *))m_equalToFrame{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.frame = obj.frame;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToTop{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.top = obj.mm_selfLayout.top;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToBottom{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.bottom = obj.mm_selfLayout.bottom;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToLeft{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.left = obj.mm_selfLayout.left;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToRight{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.right = obj.mm_selfLayout.right;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToWidth{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.width = obj.mm_selfLayout.width;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToHeight{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.height = obj.mm_selfLayout.height;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToSize{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
[self mm_selfLayout].size = obj.mm_selfLayout.size;
return self;
};
}
- (UIView *(^)(UIView *))m_equalToCenter{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
[self mm_selfLayout].point = obj.mm_selfLayout.point;
return self;
};
}
- (UIView *(^)(void))m_sizeToFit{
@m_weakify(self);
return ^(void){
@m_strongify(self);
[self sizeToFit];
return self;
};
}
- (NSData *)mm_createPDF{
CGRect bounds = self.bounds;
NSMutableData *data = [NSMutableData data];
CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((__bridge CFMutableDataRef)data);
CGContextRef context = CGPDFContextCreate(consumer, &bounds, NULL);
CGDataConsumerRelease(consumer);
if (!context) return nil;
CGPDFContextBeginPage(context, NULL);
CGContextTranslateCTM(context, 0, bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[self.layer renderInContext:context];
CGPDFContextEndPage(context);
CGPDFContextClose(context);
CGContextRelease(context);
return data;
}
- (UIViewController *)viewController {
UIView *view = self;
while (view) {
UIResponder *nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
view = view.superview;
}
return nil;
}
static void *kUIViewLayoutMethodPropertyBottomGap = &kUIViewLayoutMethodPropertyBottomGap;
static void *kUIViewLayoutMethodPropertyTopGap = &kUIViewLayoutMethodPropertyTopGap;
static void *kUIViewLayoutMethodPropertyLeftGap = &kUIViewLayoutMethodPropertyLeftGap;
static void *kUIViewLayoutMethodPropertyRightGap = &kUIViewLayoutMethodPropertyRightGap;
- (CGFloat)mm_safeAreaBottomGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
if (self.superview.safeAreaLayoutGuide.layoutFrame.size.height > 0) {
gap = @((self.superview.mm_h - self.superview.safeAreaLayoutGuide.layoutFrame.origin.y - self.superview.safeAreaLayoutGuide.layoutFrame.size.height));
} else {
gap = nil;
}
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaTopGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.y);
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaLeftGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.x);
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaRightGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @((self.superview.mm_w - self.superview.safeAreaLayoutGuide.layoutFrame.origin.x - self.superview.safeAreaLayoutGuide.layoutFrame.size.width));
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
@end
@@ -0,0 +1,5 @@
#import <UIKit/UIKit.h>
@interface UIViewController (SuperPlayerRotation)
@end
@@ -0,0 +1,19 @@
#import "UIViewController+SuperPlayerRotation.h"
@implementation UIViewController (SuperPlayerRotation)
/**
* 默认所有都不支持转屏,如需个别页面支持除竖屏外的其他方向,请在viewController重新下边这三个方法
*/
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
@end
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -0,0 +1,18 @@
//
// AdaptiveStream.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface AdaptiveStream : NSObject
@property NSString *url;
@property NSString *drmType;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// AdaptiveStream.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "AdaptiveStream.h"
@implementation AdaptiveStream
@end
@@ -0,0 +1,69 @@
//
// SPPlayCGIParseResult.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
//#import "SPResolutionDefination.h"
#import "SPSubStreamInfo.h"
#import "AdaptiveStream.h"
#import "SuperPlayerSprite.h"
#import "SPVideoFrameDescription.h"
#import "SuperPlayerUrl.h"
@class TXImageSprite;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, SPDrmType) {
SPDrmTypeNone,
SPDrmTypeSimpleAES
};
@interface SPPlayCGIParseResult : NSObject
/// 视频播放url
@property (strong, nonatomic) NSString *url;
/// 视频名称
@property (strong, nonatomic) NSString *name;
/// 雪略图对象
@property (strong, nonatomic) TXImageSprite *imageSprite;
/// 雪略图打点帧信息
@property (strong, nonatomic) NSArray<SPVideoFrameDescription *> *keyFrameDescList;
/// 字流画质信息
@property (strong, nonatomic) NSArray<SPSubStreamInfo *> *resolutionArray;
/// 原视频时长
@property (assign, nonatomic) NSTimeInterval originalDuration;
/// 预留字段,暂不使用
@property (strong, nonatomic) NSArray<AdaptiveStream *> *adaptiveStreamArray;
/// V2协议的多码率URL列表
@property (strong, nonatomic) NSArray<SuperPlayerUrl *> *multiVideoURLs;
/// 加密类型,用于 Drm
@property (assign, nonatomic) SPDrmType drmType;
/// 加密令牌,用于 Drm
@property (copy, nonatomic) NSString *drmToken;
+ (SPDrmType)drmTypeFromString:(NSString *)typeString;
/**
* 获取画质信息
*
* @return 画质信息数组
List<TCVideoQuality> getVideoQualityList();
* 获取默认画质信息
*
* @return 默认画质信息对象
TCVideoQuality getDefaultVideoQuality();
*/
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,20 @@
//
// SPPlayCGIParseResult.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParseResult.h"
#import "TXImageSprite.h"
@implementation SPPlayCGIParseResult
+ (SPDrmType)drmTypeFromString:(NSString *)typeString {
BOOL isSimpleAES = [typeString caseInsensitiveCompare:@"SimpleAES"] == NSOrderedSame;
if (isSimpleAES) {
return SPDrmTypeSimpleAES;
}
return SPDrmTypeNone;
}
@end
@@ -0,0 +1,22 @@
//
// SPSubStreamInfo.h
// SuperPlayer
//
// Created by Steven Choi on 2020/2/11.
// Copyright © 2020 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
/// 自适应码流子流信息
@interface SPSubStreamInfo : NSObject
@property (assign, nonatomic) CGSize size;
@property (copy, nonatomic) NSString *resolutionName;
@property (copy, nonatomic) NSString *type;
+ (instancetype)infoWithDictionary:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,21 @@
//
// SPSubStreamInfo.m
// SuperPlayer
//
// Created by Steven Choi on 2020/2/11.
// Copyright © 2020 annidy. All rights reserved.
//
#import "SPSubStreamInfo.h"
#import "J2Obj.h"
@implementation SPSubStreamInfo
+ (instancetype)infoWithDictionary:(NSDictionary *)dict {
SPSubStreamInfo *info = [[SPSubStreamInfo alloc] init];
double width = [J2Num(dict[@"width"]) doubleValue];
double height = [J2Num(dict[@"height"]) doubleValue];
info.size = CGSizeMake(width, height);
info.resolutionName = J2Str(dict[@"name"]);
info.type = J2Str(dict[@"type"]);
return info;
}
@end
@@ -0,0 +1,21 @@
//
// SPVideoFrameDescription.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SPVideoFrameDescription : NSObject
// updates in SuperPlayerView
@property double where;
@property NSString *text;
@property double time;
+ (instancetype)instanceFromDictionary:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,22 @@
//
// SPVideoFrameDescription.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPVideoFrameDescription.h"
#import "J2Obj.h"
@implementation SPVideoFrameDescription
+ (instancetype)instanceFromDictionary:(NSDictionary *)keyFrameDesc {
if (![keyFrameDesc isKindOfClass:[NSDictionary class]]) {
return nil;
}
SPVideoFrameDescription *ret = [[SPVideoFrameDescription alloc] init];
ret.time = [J2Num([keyFrameDesc valueForKeyPath:@"timeOffset"]) intValue]/1000.0;
ret.text = [J2Str([keyFrameDesc valueForKeyPath:@"content"]) stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return ret;
}
@end
@@ -0,0 +1,18 @@
//
// SuperPlayerSprite.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SuperPlayerSprite : NSObject
@property (strong, nonatomic) NSArray<NSString *> *imageURLs;
@property (strong, nonatomic) NSString *webVttURL;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// SuperPlayerSprite.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SuperPlayerSprite.h"
@implementation SuperPlayerSprite
@end
@@ -0,0 +1,23 @@
//
// SuperPlayerUrl.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
* 多码率地址
* 用于有多个播放地址的多清晰度视频的播放
*/
@interface SuperPlayerUrl : NSObject
/// 播放器展示的对应标题,如“高清”、“低清”等
@property NSString *title;
/// 播放地址
@property NSString *url;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// SuperPlayerUrl.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SuperPlayerUrl.h"
@implementation SuperPlayerUrl
@end
@@ -0,0 +1,18 @@
//
// SPPlayCGIParser.h
// SuperPlayer
//
// Created by cui on 2019/12/26.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser : NSObject
+ (Class<SPPlayCGIParserProtocol>)parserOfVersion:(NSInteger)version;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,22 @@
//
// SPPlayCGIParser.m
// SuperPlayer
//
// Created by cui on 2019/12/26.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParser.h"
#import "SPPlayCGIParser_V2.h"
#import "SPPlayCGIParser_V4.h"
@implementation SPPlayCGIParser
+ (Class<SPPlayCGIParserProtocol>)parserOfVersion:(NSInteger)version {
if (version == 2) {
return [SPPlayCGIParser_V2 class];
} else if (version == 4) {
return [SPPlayCGIParser_V4 class];
}
return Nil;
}
@end
@@ -0,0 +1,18 @@
//
// PlayCGIParserProtocol.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParseResult.h"
NS_ASSUME_NONNULL_BEGIN
@protocol SPPlayCGIParserProtocol <NSObject>
+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)jsonResp;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,18 @@
//
// SPPlayCGIParser_V2.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser_V2 : NSObject <SPPlayCGIParserProtocol>
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,105 @@
//
// SPPlayCGIParser_V2.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParser_V2.h"
#import "J2Obj.h"
#import "SuperPlayerUrl.h"
#import "TXBitrateItemHelper.h"
#import "TXImageSprite.h"
@implementation SPPlayCGIParser_V2
+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)responseObject {
SPPlayCGIParseResult *ret = [[SPPlayCGIParseResult alloc] init];
NSString *masterUrl = J2Str([responseObject valueForKeyPath:@"videoInfo.masterPlayList.url"]);
// masterUrl = nil;
if (masterUrl.length > 0) {
// 1. 如果有master url,优先用这个
ret.url = masterUrl;
} else {
NSString *mainDefinition = J2Str([responseObject valueForKeyPath:@"playerInfo.defaultVideoClassification"]);
NSArray *videoClassification = J2Array([responseObject valueForKeyPath:@"playerInfo.videoClassification"]);
NSArray *transcodeList = J2Array([responseObject valueForKeyPath:@"videoInfo.transcodeList"]);
NSMutableArray<SuperPlayerUrl *> *result = [NSMutableArray new];
// 2. 如果有转码的清晰度,用转码流
for (NSDictionary *transcode in transcodeList) {
SuperPlayerUrl *subModel = [SuperPlayerUrl new];
subModel.url = J2Str(transcode[@"url"]);
NSNumber *theDefinition = J2Num(transcode[@"definition"]);
for (NSDictionary *definition in videoClassification) {
for (NSObject *definition2 in J2Array([definition valueForKeyPath:@"definitionList"])) {
if ([definition2 isEqual:theDefinition]) {
subModel.title = J2Str([definition valueForKeyPath:@"name"]);
NSString *definitionId = J2Str([definition valueForKeyPath:@"id"]);
// 初始播放清晰度
if ([definitionId isEqualToString:mainDefinition]) {
if (![ret.url containsString:@".mp4"])
ret.url = subModel.url;
}
break;
}
}
}
// 同一个清晰度可能存在多个转码格式,这里只保留一种格式,且优先mp4类型
for (SuperPlayerUrl *item in result) {
if ([item.title isEqual:subModel.title]) {
if (![item.url containsString:@".mp4"]) {
item.url = subModel.url;
}
subModel = nil;
break;
}
}
if (subModel) {
[result addObject:subModel];
}
}
ret.multiVideoURLs = result;
}
// 3. 以上都没有,用原始地址
if (ret.url == nil) {
NSString *source = J2Str([responseObject valueForKeyPath:@"videoInfo.sourceVideo.url"]);
ret.url = source;
}
NSArray *imageSprites = J2Array([responseObject valueForKeyPath:@"imageSpriteInfo.imageSpriteList"]);
if (imageSprites.count > 0) {
// id imageSpriteObj = imageSprites[0];
id imageSpriteObj = imageSprites.lastObject;
NSString *vtt = J2Str([imageSpriteObj valueForKeyPath:@"webVttUrl"]);
NSArray *imgUrls = J2Array([imageSpriteObj valueForKeyPath:@"imageUrls"]);
NSMutableArray *imgUrlArray = @[].mutableCopy;
for (NSString *url in imgUrls) {
NSURL *nsurl = [NSURL URLWithString:url];
if (nsurl) {
[imgUrlArray addObject:nsurl];
}
}
TXImageSprite *imageSprite = [[TXImageSprite alloc] init];
[imageSprite setVTTUrl:[NSURL URLWithString:vtt] imageUrls:imgUrlArray];
ret.imageSprite = imageSprite;
}
NSArray *keyFrameDescList = J2Array([responseObject valueForKeyPath:@"keyFrameDescInfo.keyFrameDescList"]);
if (keyFrameDescList.count > 0) {
NSMutableArray<SPVideoFrameDescription *> *checkPoints = [[NSMutableArray alloc] initWithCapacity:keyFrameDescList.count];
for (NSDictionary *info in keyFrameDescList) {
SPVideoFrameDescription *checkPoint = [SPVideoFrameDescription instanceFromDictionary:info];
[checkPoints addObject:checkPoint];
}
ret.keyFrameDescList = checkPoints;
}
return ret;
}
@end
@@ -0,0 +1,18 @@
//
// PlayCGIV4Parser.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser_V4 : NSObject <SPPlayCGIParserProtocol>
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,122 @@
//
// PlayCGIV4Parser.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParser_V4.h"
//#import "SPResolutionDefination.h"
#import "SPSubStreamInfo.h"
#import "AdaptiveStream.h"
#import "TXImageSprite.h"
#import "J2Obj.h"
@implementation SPPlayCGIParser_V4
+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)jsonResp {
SPPlayCGIParseResult *ret = [[SPPlayCGIParseResult alloc] init];
// 获取媒体信息
NSDictionary *media = jsonResp[@"media"];
if ([media isKindOfClass:[NSDictionary class]]) {
do {
//解析视频名称
ret.name = [media valueForKeyPath:@"basicInfo.name"];
NSDictionary *streamInfo = [media valueForKeyPath:@"streamingInfo.plainOutput"];
if (streamInfo == nil) {
NSArray* drmOutputs = [media valueForKeyPath:@"streamingInfo.drmOutput"];
for (NSDictionary *drmOutput in drmOutputs) {
SPDrmType type = [SPPlayCGIParseResult drmTypeFromString:J2Str(drmOutput[@"type"])];
if (type == SPDrmTypeSimpleAES) {
streamInfo = drmOutput;
ret.drmType = SPDrmTypeSimpleAES;
break;
}
}
ret.drmToken = [media valueForKeyPath:@"streamingInfo.drmToken"];
}
if (streamInfo == nil) {
return nil;
}
NSNumber *duration = [media valueForKeyPath:@"basicInfo.duration"];
if ([duration isKindOfClass:[NSNumber class]]) {
ret.originalDuration = duration.doubleValue;
}
// 解析分辨率名称
NSArray *subStreamDictArray = J2Array(streamInfo[@"subStreams"]);
NSMutableArray *subStreamInfoArray = [NSMutableArray arrayWithCapacity:subStreamDictArray.count];
for (NSDictionary *resInfo in subStreamDictArray) {
SuperPlayerUrl *url = [[SuperPlayerUrl alloc] init];
url.title = J2Str(resInfo[@"resolutionName"]);
// SPSubStreamInfo *info = [SPSubStreamInfo infoWithDictionary:resInfo];
[subStreamInfoArray addObject:url];
}
ret.multiVideoURLs = subStreamInfoArray;
//解析视频播放url
NSString *url = streamInfo[@"url"];
if ([url isKindOfClass:[NSString class]] && url.length > 0) {
//未加密直接解析出视频url
ret.url = url;
} else {
//有加密,url为空,则解析drm加密的url信息
NSArray *urlArray = streamInfo[@"drmUrls"];
if ([urlArray isKindOfClass:[NSArray class]] &&
urlArray.count > 0) {
NSMutableArray *drmURLArray = [NSMutableArray arrayWithCapacity:urlArray.count];
for (NSDictionary *dict in urlArray) {
if ([dict isKindOfClass:[NSDictionary class]]) {
continue;
}
AdaptiveStream *stream = [[AdaptiveStream alloc] init];
stream.url = dict[@"url"];
stream.drmType = dict[@"type"];
[drmURLArray addObject:stream];
}
ret.adaptiveStreamArray = drmURLArray;
}
}
//解析略缩图信息
NSDictionary *imageSpriteInfo = media[@"imageSpriteInfo"];
if ([imageSpriteInfo isKindOfClass:[NSDictionary class]]) {
NSString *vttURLString = J2Str(imageSpriteInfo[@"webVttUrl"]);
NSURL *vttURL = [NSURL URLWithString:vttURLString];
NSArray *imageURLStrings = J2Array(imageSpriteInfo[@"imageUrls"]);
NSMutableArray<NSURL *> *imageURLs = [NSMutableArray arrayWithCapacity:imageURLStrings.count];
for (NSString *urlString in imageURLStrings) {
NSURL *url = [NSURL URLWithString:urlString];
if (url) {
[imageURLs addObject:url];
}
}
TXImageSprite *sprite = [[TXImageSprite alloc] init];
[sprite setVTTUrl:vttURL imageUrls:imageURLs];
ret.imageSprite = sprite;
}
//解析关键帧信息
NSDictionary *keyFrameDescInfo = media[@"keyFrameDescInfo"];
if ([keyFrameDescInfo isKindOfClass:[NSDictionary class]]) {
NSArray *keyFrameDescList = keyFrameDescInfo[@"keyFrameDescList"];
if ([keyFrameDescList isKindOfClass:[NSArray class]] &&
keyFrameDescList.count > 0) {
NSMutableArray<SPVideoFrameDescription *> *videoPoints = [NSMutableArray array];
for (NSDictionary *jsonObject in keyFrameDescList) {
SPVideoFrameDescription *point = [SPVideoFrameDescription instanceFromDictionary:jsonObject];
if (point) {
[videoPoints addObject:point];
}
}
ret.keyFrameDescList = videoPoints;
}
}
} while (0);
}
return ret;
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,79 @@
//
// SPDefaultControlView.h
// SuperPlayer
//
// Created by annidyfeng on 2018/9/30.
//
#import "SuperPlayerControlView.h"
@interface SPDefaultControlView : SuperPlayerControlView
/** 标题 */
@property (nonatomic, strong) UILabel *titleLabel;
/** 开始播放按钮 */
@property (nonatomic, strong) UIButton *startBtn;
/** 当前播放时长label */
@property (nonatomic, strong) UILabel *currentTimeLabel;
/** 视频总时长label */
@property (nonatomic, strong) UILabel *totalTimeLabel;
/** 全屏按钮 */
@property (nonatomic, strong) UIButton *fullScreenBtn;
/** 锁定屏幕方向按钮 */
@property (nonatomic, strong) UIButton *lockBtn;
/** 返回按钮*/
@property (nonatomic, strong) UIButton *backBtn;
/// 是否禁用返回
@property (nonatomic) BOOL disableBackBtn;
/** bottomView*/
@property (nonatomic, strong) UIImageView *bottomImageView;
/** topView */
@property (nonatomic, strong) UIImageView *topImageView;
/** 弹幕按钮 */
@property (nonatomic, strong) UIButton *danmakuBtn;
/// 是否禁用弹幕
@property (nonatomic) BOOL disableDanmakuBtn;
/** 截图按钮 */
@property (nonatomic, strong) UIButton *captureBtn;
/// 是否禁用截图
@property (nonatomic) BOOL disableCaptureBtn;
/** 更多按钮 */
@property (nonatomic, strong) UIButton *moreBtn;
/// 是否禁用更多
@property (nonatomic) BOOL disableMoreBtn;
/** 切换分辨率按钮 */
@property (nonatomic, strong) UIButton *resolutionBtn;
/** 分辨率的View */
@property (nonatomic, strong) UIView *resolutionView;
/** 播放按钮 */
@property (nonatomic, strong) UIButton *playeBtn;
/** 加载失败按钮 */
@property (nonatomic, strong) UIButton *middleBtn;
/** 当前选中的分辨率btn按钮 */
@property (nonatomic, weak ) UIButton *resoultionCurrentBtn;
/** 分辨率的名称 */
@property (nonatomic, strong) NSArray<NSString *> *resolutionArray;
/** 更多设置View */
@property (nonatomic, strong) SuperPlayerSettingsView *moreContentView;
/** 返回直播 */
@property (nonatomic, strong) UIButton *backLiveBtn;
/// 画面比例
@property CGFloat videoRatio;
/** 滑杆 */
@property (nonatomic, strong) PlayerSlider *videoSlider;
/** 重播按钮 */
@property (nonatomic, strong) UIButton *repeatBtn;
/** 是否全屏播放 */
@property (nonatomic, assign,getter=isFullScreen)BOOL fullScreen;
@property (nonatomic, assign,getter=isLockScreen)BOOL isLockScreen;
@property (nonatomic, strong) UIButton *pointJumpBtn;
@end
@@ -0,0 +1,774 @@
#import "SuperPlayerControlView.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import "SuperPlayerSettingsView.h"
#import "DataReport.h"
#import "SuperPlayerFastView.h"
#import "PlayerSlider.h"
#import "UIView+MMLayout.h"
#import "SuperPlayerView+Private.h"
#import "StrUtils.h"
#import "SPDefaultControlView.h"
#import "UIView+Fade.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
#define MODEL_TAG_BEGIN 20
#define BOTTOM_IMAGE_VIEW_HEIGHT 50
@interface SPDefaultControlView () <UIGestureRecognizerDelegate, PlayerSliderDelegate>
@property BOOL isLive;
@end
@implementation SPDefaultControlView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.topImageView];
[self addSubview:self.bottomImageView];
[self.bottomImageView addSubview:self.startBtn];
[self.bottomImageView addSubview:self.currentTimeLabel];
[self.bottomImageView addSubview:self.videoSlider];
[self.bottomImageView addSubview:self.resolutionBtn];
[self.bottomImageView addSubview:self.fullScreenBtn];
[self.bottomImageView addSubview:self.totalTimeLabel];
[self.topImageView addSubview:self.captureBtn];
[self.topImageView addSubview:self.danmakuBtn];
[self.topImageView addSubview:self.moreBtn];
[self addSubview:self.lockBtn];
[self.topImageView addSubview:self.backBtn];
[self addSubview:self.playeBtn];
[self.topImageView addSubview:self.titleLabel];
[self addSubview:self.backLiveBtn];
// 添加子控件的约束
[self makeSubViewsConstraints];
self.captureBtn.hidden = YES;
self.danmakuBtn.hidden = YES;
self.moreBtn.hidden = YES;
self.resolutionBtn.hidden = YES;
self.moreContentView.hidden = YES;
// 初始化时重置controlView
[self playerResetControlView];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)makeSubViewsConstraints {
[self.topImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.equalTo(self);
make.top.equalTo(self.mas_top).offset(0);
make.height.mas_equalTo(50);
}];
[self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.topImageView.mas_leading).offset(5);
make.top.equalTo(self.topImageView.mas_top).offset(3);
make.width.height.mas_equalTo(40);
}];
[self.moreBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(40);
make.height.mas_equalTo(49);
make.trailing.equalTo(self.topImageView.mas_trailing).offset(-10);
make.centerY.equalTo(self.backBtn.mas_centerY);
}];
[self.captureBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(40);
make.height.mas_equalTo(49);
make.trailing.equalTo(self.moreBtn.mas_leading).offset(-10);
make.centerY.equalTo(self.backBtn.mas_centerY);
}];
[self.danmakuBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(40);
make.height.mas_equalTo(49);
make.trailing.equalTo(self.captureBtn.mas_leading).offset(-10);
make.centerY.equalTo(self.backBtn.mas_centerY);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.backBtn.mas_trailing).offset(5);
make.centerY.equalTo(self.backBtn.mas_centerY);
make.trailing.equalTo(self.captureBtn.mas_leading).offset(-10);
}];
[self.bottomImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.bottom.mas_equalTo(0);
make.height.mas_equalTo(BOTTOM_IMAGE_VIEW_HEIGHT);
}];
[self.startBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.bottomImageView.mas_leading).offset(5);
make.top.equalTo(self.bottomImageView.mas_top).offset(10);
make.width.height.mas_equalTo(30);
}];
[self.currentTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.startBtn.mas_trailing);
make.centerY.equalTo(self.startBtn.mas_centerY);
make.width.mas_equalTo(60);
}];
[self.fullScreenBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(30);
make.trailing.equalTo(self.bottomImageView.mas_trailing).offset(-8);
make.centerY.equalTo(self.startBtn.mas_centerY);
}];
[self.resolutionBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(30);
make.width.mas_greaterThanOrEqualTo(45);
make.trailing.equalTo(self.bottomImageView.mas_trailing).offset(-8);
make.centerY.equalTo(self.startBtn.mas_centerY);
}];
[self.totalTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.equalTo(self.fullScreenBtn.mas_leading);
make.centerY.equalTo(self.startBtn.mas_centerY);
make.width.mas_equalTo(60);
}];
[self.videoSlider mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.currentTimeLabel.mas_trailing);
make.trailing.equalTo(self.totalTimeLabel.mas_leading);
make.centerY.equalTo(self.currentTimeLabel.mas_centerY).offset(-1);
}];
[self.lockBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self.mas_leading).offset(15);
make.centerY.equalTo(self.mas_centerY);
make.width.height.mas_equalTo(32);
}];
[self.playeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(50);
make.center.equalTo(self);
}];
[self.backLiveBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(self.startBtn.mas_top).mas_offset(-15);
make.width.mas_equalTo(70);
make.centerX.equalTo(self);
}];
}
#pragma mark - Action
/**
* 点击切换分别率按钮
*/
- (void)changeResolution:(UIButton *)sender {
self.resoultionCurrentBtn.selected = NO;
self.resoultionCurrentBtn.backgroundColor = [UIColor clearColor];
self.resoultionCurrentBtn = sender;
self.resoultionCurrentBtn.selected = YES;
self.resoultionCurrentBtn.backgroundColor = RGBA(34, 30, 24, 1);
// topImageView上的按钮的文字
[self.resolutionBtn setTitle:sender.titleLabel.text forState:UIControlStateNormal];
[self.delegate controlViewSwitch:self withDefinition:sender.titleLabel.text];
}
- (void)backBtnClick:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(controlViewBack:)]) {
[self.delegate controlViewBack:self];
}
}
- (void)exitFullScreen:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(controlViewChangeScreen:withFullScreen:)]) {
[self.delegate controlViewChangeScreen:self withFullScreen:NO];
}
}
- (void)lockScrrenBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
self.isLockScreen = sender.selected;
self.topImageView.hidden = self.isLockScreen;
self.bottomImageView.hidden = self.isLockScreen;
if (self.isLive) {
self.backLiveBtn.hidden = self.isLockScreen;
}
[self.delegate controlViewLockScreen:self withLock:self.isLockScreen];
[self fadeOut:3];
}
- (void)playBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) {
[self.delegate controlViewPlay:self];
} else {
[self.delegate controlViewPause:self];
}
[self cancelFadeOut];
}
- (void)fullScreenBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
self.fullScreen = !self.fullScreen;
[self.delegate controlViewChangeScreen:self withFullScreen:YES];
[self fadeOut:3];
}
- (void)captureBtnClick:(UIButton *)sender {
[self.delegate controlViewSnapshot:self];
[self fadeOut:3];
}
- (void)danmakuBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
[self fadeOut:3];
}
- (void)moreBtnClick:(UIButton *)sender {
self.topImageView.hidden = YES;
self.bottomImageView.hidden = YES;
self.lockBtn.hidden = YES;
self.moreContentView.playerConfig = self.playerConfig;
[self.moreContentView update];
self.moreContentView.hidden = NO;
[self cancelFadeOut];
self.isShowSecondView = YES;
}
- (UIView *)resolutionView {
if (!_resolutionView) {
// 添加分辨率按钮和分辨率下拉列表
_resolutionView = [[UIView alloc] initWithFrame:CGRectZero];
_resolutionView.hidden = YES;
[self addSubview:_resolutionView];
[_resolutionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(330);
make.height.mas_equalTo(self.mas_height);
make.trailing.equalTo(self.mas_trailing).offset(0);
make.top.equalTo(self.mas_top).offset(0);
}];
_resolutionView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
}
return _resolutionView;
}
- (void)resolutionBtnClick:(UIButton *)sender {
self.topImageView.hidden = YES;
self.bottomImageView.hidden = YES;
self.lockBtn.hidden = YES;
// 显示隐藏分辨率View
self.resolutionView.hidden = NO;
[DataReport report:@"change_resolution" param:nil];
[self cancelFadeOut];
self.isShowSecondView = YES;
}
- (void)progressSliderTouchBegan:(UISlider *)sender {
self.isDragging = YES;
[self cancelFadeOut];
}
- (void)progressSliderValueChanged:(UISlider *)sender {
if (self.maxPlayableRatio > 0 && sender.value > self.maxPlayableRatio) {
sender.value = self.maxPlayableRatio;
}
[self.delegate controlViewPreview:self where:sender.value];
}
- (void)progressSliderTouchEnded:(UISlider *)sender {
[self.delegate controlViewSeek:self where:sender.value];
self.isDragging = NO;
[self fadeOut:5];
}
- (void)backLiveClick:(UIButton *)sender {
[self.delegate controlViewReload:self];
}
- (void)pointJumpClick:(UIButton *)sender {
self.pointJumpBtn.hidden = YES;
PlayerPoint *point = [self.videoSlider.pointArray objectAtIndex:self.pointJumpBtn.tag];
[self.delegate controlViewSeek:self where:point.where];
[self fadeOut:0.1];
}
- (void)setDisableBackBtn:(BOOL)disableBackBtn {
_disableBackBtn = disableBackBtn;
self.backBtn.hidden = disableBackBtn;
}
- (void)setDisableMoreBtn:(BOOL)disableMoreBtn {
_disableMoreBtn = disableMoreBtn;
if (self.fullScreen) {
self.moreBtn.hidden = disableMoreBtn;
}
}
- (void)setDisableCaptureBtn:(BOOL)disableCaptureBtn {
_disableCaptureBtn = disableCaptureBtn;
if (self.fullScreen) {
self.captureBtn.hidden = disableCaptureBtn;
}
}
- (void)setDisableDanmakuBtn:(BOOL)disableDanmakuBtn {
_disableDanmakuBtn = disableDanmakuBtn;
if (self.fullScreen) {
self.danmakuBtn.hidden = disableDanmakuBtn;
}
}
/**
* 屏幕方向发生变化会调用这里
*/
- (void)setOrientationLandscapeConstraint {
self.fullScreen = YES;
self.lockBtn.hidden = NO;
self.fullScreenBtn.selected = self.isLockScreen;
self.fullScreenBtn.hidden = YES;
self.resolutionBtn.hidden = self.resolutionArray.count == 0;
self.moreBtn.hidden = self.disableMoreBtn;
self.captureBtn.hidden = self.disableCaptureBtn;
self.danmakuBtn.hidden = self.disableDanmakuBtn;
[self.backBtn setImage:SuperPlayerImage(@"back_full") forState:UIControlStateNormal];
[self.totalTimeLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
if (self.resolutionArray.count > 0) {
make.trailing.equalTo(self.resolutionBtn.mas_leading);
} else {
make.trailing.equalTo(self.bottomImageView.mas_trailing);
}
make.centerY.equalTo(self.startBtn.mas_centerY);
make.width.mas_equalTo(self.isLive?10:60);
}];
[self.bottomImageView mas_updateConstraints:^(MASConstraintMaker *make) {
CGFloat b = self.superview.mm_safeAreaBottomGap;
make.height.mas_equalTo(BOTTOM_IMAGE_VIEW_HEIGHT+b);
}];
self.videoSlider.hiddenPoints = NO;
}
/**
* 设置竖屏的约束
*/
- (void)setOrientationPortraitConstraint {
self.fullScreen = NO;
self.lockBtn.hidden = YES;
self.fullScreenBtn.selected = NO;
self.fullScreenBtn.hidden = NO;
self.resolutionBtn.hidden = YES;
self.moreBtn.hidden = YES;
self.captureBtn.hidden = YES;
self.danmakuBtn.hidden = YES;
self.moreContentView.hidden = YES;
self.resolutionView.hidden = YES;
[self.totalTimeLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.trailing.equalTo(self.fullScreenBtn.mas_leading);
make.centerY.equalTo(self.startBtn.mas_centerY);
make.width.mas_equalTo(self.isLive?10:60);
}];
[self.bottomImageView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(BOTTOM_IMAGE_VIEW_HEIGHT);
}];
self.videoSlider.hiddenPoints = YES;
self.pointJumpBtn.hidden = YES;
}
#pragma mark - Private Method
#pragma mark - setter
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.font = [UIFont systemFontOfSize:15.0];
}
return _titleLabel;
}
- (UIButton *)backBtn {
if (!_backBtn) {
_backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_backBtn setImage:SuperPlayerImage(@"back_full") forState:UIControlStateNormal];
[_backBtn addTarget:self action:@selector(backBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _backBtn;
}
- (UIImageView *)topImageView {
if (!_topImageView) {
_topImageView = [[UIImageView alloc] init];
_topImageView.userInteractionEnabled = YES;
_topImageView.image = SuperPlayerImage(@"top_shadow");
}
return _topImageView;
}
- (UIImageView *)bottomImageView {
if (!_bottomImageView) {
_bottomImageView = [[UIImageView alloc] init];
_bottomImageView.userInteractionEnabled = YES;
_bottomImageView.image = SuperPlayerImage(@"bottom_shadow");
}
return _bottomImageView;
}
- (UIButton *)lockBtn {
if (!_lockBtn) {
_lockBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_lockBtn.exclusiveTouch = YES;
[_lockBtn setImage:SuperPlayerImage(@"unlock-nor") forState:UIControlStateNormal];
[_lockBtn setImage:SuperPlayerImage(@"lock-nor") forState:UIControlStateSelected];
[_lockBtn addTarget:self action:@selector(lockScrrenBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _lockBtn;
}
- (UIButton *)startBtn {
if (!_startBtn) {
_startBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_startBtn setImage:SuperPlayerImage(@"play") forState:UIControlStateNormal];
[_startBtn setImage:SuperPlayerImage(@"pause") forState:UIControlStateSelected];
[_startBtn addTarget:self action:@selector(playBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _startBtn;
}
- (UILabel *)currentTimeLabel {
if (!_currentTimeLabel) {
_currentTimeLabel = [[UILabel alloc] init];
_currentTimeLabel.textColor = [UIColor whiteColor];
_currentTimeLabel.font = [UIFont systemFontOfSize:12.0f];
_currentTimeLabel.textAlignment = NSTextAlignmentCenter;
}
return _currentTimeLabel;
}
- (PlayerSlider *)videoSlider {
if (!_videoSlider) {
_videoSlider = [[PlayerSlider alloc] init];
[_videoSlider setThumbImage:SuperPlayerImage(@"slider_thumb") forState:UIControlStateNormal];
_videoSlider.minimumTrackTintColor = TintColor;
// slider开始滑动事件
[_videoSlider addTarget:self action:@selector(progressSliderTouchBegan:) forControlEvents:UIControlEventTouchDown];
// slider滑动中事件
[_videoSlider addTarget:self action:@selector(progressSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
// slider结束滑动事件
[_videoSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
_videoSlider.delegate = self;
}
return _videoSlider;
}
- (UILabel *)totalTimeLabel {
if (!_totalTimeLabel) {
_totalTimeLabel = [[UILabel alloc] init];
_totalTimeLabel.textColor = [UIColor whiteColor];
_totalTimeLabel.font = [UIFont systemFontOfSize:12.0f];
_totalTimeLabel.textAlignment = NSTextAlignmentCenter;
}
return _totalTimeLabel;
}
- (UIButton *)fullScreenBtn {
if (!_fullScreenBtn) {
_fullScreenBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_fullScreenBtn setImage:SuperPlayerImage(@"fullscreen") forState:UIControlStateNormal];
[_fullScreenBtn addTarget:self action:@selector(fullScreenBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _fullScreenBtn;
}
- (UIButton *)captureBtn {
if (!_captureBtn) {
_captureBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_captureBtn setImage:SuperPlayerImage(@"capture") forState:UIControlStateNormal];
[_captureBtn setImage:SuperPlayerImage(@"capture_pressed") forState:UIControlStateSelected];
[_captureBtn addTarget:self action:@selector(captureBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _captureBtn;
}
- (UIButton *)danmakuBtn {
if (!_danmakuBtn) {
_danmakuBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_danmakuBtn setImage:SuperPlayerImage(@"danmu") forState:UIControlStateNormal];
[_danmakuBtn setImage:SuperPlayerImage(@"danmu_pressed") forState:UIControlStateSelected];
[_danmakuBtn addTarget:self action:@selector(danmakuBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _danmakuBtn;
}
- (UIButton *)moreBtn {
if (!_moreBtn) {
_moreBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_moreBtn setImage:SuperPlayerImage(@"more") forState:UIControlStateNormal];
[_moreBtn setImage:SuperPlayerImage(@"more_pressed") forState:UIControlStateSelected];
[_moreBtn addTarget:self action:@selector(moreBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _moreBtn;
}
- (UIButton *)resolutionBtn {
if (!_resolutionBtn) {
_resolutionBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_resolutionBtn.titleLabel.font = [UIFont systemFontOfSize:12];
_resolutionBtn.backgroundColor = [UIColor clearColor];
[_resolutionBtn addTarget:self action:@selector(resolutionBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _resolutionBtn;
}
- (UIButton *)backLiveBtn {
if (!_backLiveBtn) {
_backLiveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_backLiveBtn setTitle:@"返回直播" forState:UIControlStateNormal];
_backLiveBtn.titleLabel.font = [UIFont systemFontOfSize:14];
UIImage *image = SuperPlayerImage(@"qg_online_bg");
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(33 * 0.5, 33 * 0.5, 33 * 0.5, 33 * 0.5)];
[_backLiveBtn setBackgroundImage:resizableImage forState:UIControlStateNormal];
[_backLiveBtn addTarget:self action:@selector(backLiveClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _backLiveBtn;
}
- (UIButton *)pointJumpBtn {
if (!_pointJumpBtn) {
_pointJumpBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = SuperPlayerImage(@"copywright_bg");
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20, 0, 20) resizingMode:UIImageResizingModeStretch];
[_pointJumpBtn setBackgroundImage:resizableImage forState:UIControlStateNormal];
_pointJumpBtn.titleLabel.font = [UIFont systemFontOfSize:14];
[_pointJumpBtn addTarget:self action:@selector(pointJumpClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_pointJumpBtn];
}
return _pointJumpBtn;
}
- (SuperPlayerSettingsView *)moreContentView {
if (!_moreContentView) {
_moreContentView = [[SuperPlayerSettingsView alloc] initWithFrame:CGRectZero];
_moreContentView.controlView = self;
_moreContentView.hidden = YES;
[self addSubview:_moreContentView];
[_moreContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(330);
make.height.mas_equalTo(self.mas_height);
make.trailing.equalTo(self.mas_trailing).offset(0);
make.top.equalTo(self.mas_top).offset(0);
}];
_moreContentView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
}
return _moreContentView;
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UISlider class]]) { // 如果在滑块上点击就不响应pan手势
return NO;
}
return YES;
}
#pragma mark - Public method
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
if (hidden) {
self.resolutionView.hidden = YES;
self.moreContentView.hidden = YES;
if (!self.isLockScreen) {
self.topImageView.hidden = NO;
self.bottomImageView.hidden = NO;
}
}
self.lockBtn.hidden = !self.isFullScreen;
self.isShowSecondView = NO;
self.pointJumpBtn.hidden = YES;
}
/** 重置ControlView */
- (void)playerResetControlView {
self.videoSlider.value = 0;
self.videoSlider.progressView.progress = 0;
self.currentTimeLabel.text = @"00:00";
self.totalTimeLabel.text = @"00:00";
self.playeBtn.hidden = YES;
self.resolutionView.hidden = YES;
self.backgroundColor = [UIColor clearColor];
self.moreBtn.enabled = !self.disableMoreBtn;
self.lockBtn.hidden = !self.isFullScreen;
self.danmakuBtn.enabled = YES;
self.captureBtn.enabled = YES;
self.backLiveBtn.hidden = YES;
}
- (void)setPointArray:(NSArray *)pointArray
{
[super setPointArray:pointArray];
for (PlayerPoint *holder in self.videoSlider.pointArray) {
[holder.holder removeFromSuperview];
}
[self.videoSlider.pointArray removeAllObjects];
for (SPVideoFrameDescription *p in pointArray) {
PlayerPoint *point = [self.videoSlider addPoint:p.where];
point.content = p.text;
point.timeOffset = p.time;
}
}
- (void)onPlayerPointSelected:(PlayerPoint *)point {
NSString *text = [NSString stringWithFormat:@" %@ %@ ", [StrUtils timeFormat:point.timeOffset],
point.content];
[self.pointJumpBtn setTitle:text forState:UIControlStateNormal];
[self.pointJumpBtn sizeToFit];
CGFloat x = self.videoSlider.mm_x + self.videoSlider.mm_w * point.where - self.pointJumpBtn.mm_h/2;
if (x < 0)
x = 0;
if (x + self.pointJumpBtn.mm_h/2 > ScreenWidth)
x = ScreenWidth - self.pointJumpBtn.mm_h/2;
self.pointJumpBtn.tag = [self.videoSlider.pointArray indexOfObject:point];
self.pointJumpBtn.m_left(x).m_bottom(60);
self.pointJumpBtn.hidden = NO;
[DataReport report:@"player_point" param:nil];
}
- (void)setProgressTime:(NSInteger)currentTime
totalTime:(NSInteger)totalTime
progressValue:(CGFloat)progress
playableValue:(CGFloat)playable {
if (!self.isDragging) {
// 更新slider
self.videoSlider.value = progress;
}
// 更新当前播放时间
self.currentTimeLabel.text = [StrUtils timeFormat:currentTime];
// 更新总时间
self.totalTimeLabel.text = [StrUtils timeFormat:totalTime];
[self.videoSlider.progressView setProgress:playable animated:NO];
}
- (void)resetWithResolutionNames:(NSArray<NSString *> *)resolutionNames
currentResolutionIndex:(NSUInteger)currentResolutionIndex
isLive:(BOOL)isLive
isTimeShifting:(BOOL)isTimeShifting
isPlaying:(BOOL)isPlaying
{
NSAssert(resolutionNames.count == 0 || currentResolutionIndex < resolutionNames.count,
@"Invalid argument when reseeting %@", NSStringFromClass(self.class));
[self setPlayState:isPlaying];
self.backLiveBtn.hidden = !isTimeShifting;
self.moreContentView.enableSpeedAndMirrorControl = !isLive;
for (UIView *subview in self.resolutionView.subviews)
[subview removeFromSuperview];
_resolutionArray = resolutionNames;
if (_resolutionArray.count > 0) {
[self.resolutionBtn setTitle:resolutionNames[currentResolutionIndex]
forState:UIControlStateNormal];
}
UILabel *lable = [UILabel new];
lable.text = @"清晰度";
lable.textAlignment = NSTextAlignmentCenter;
lable.textColor = [UIColor whiteColor];
[self.resolutionView addSubview:lable];
[lable mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.resolutionView.mas_width);
make.height.mas_equalTo(30);
make.left.equalTo(self.resolutionView.mas_left);
make.top.equalTo(self.resolutionView.mas_top).mas_offset(20);
}];
// 分辨率View上边的Btn
for (NSInteger i = 0 ; i < _resolutionArray.count; i++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:_resolutionArray[i] forState:UIControlStateNormal];
[btn setTitleColor:RGBA(252, 89, 81, 1) forState:UIControlStateSelected];
[self.resolutionView addSubview:btn];
[btn addTarget:self action:@selector(changeResolution:) forControlEvents:UIControlEventTouchUpInside];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.resolutionView.mas_width);
make.height.mas_equalTo(45);
make.left.equalTo(self.resolutionView.mas_left);
make.centerY.equalTo(self.resolutionView.mas_centerY).offset((i-self.resolutionArray.count/2.0+0.5)*45);
}];
btn.tag = MODEL_TAG_BEGIN+i;
if (i == currentResolutionIndex) {
btn.selected = YES;
btn.backgroundColor = RGBA(34, 30, 24, 1);
self.resoultionCurrentBtn = btn;
}
}
if (self.isLive != isLive) {
self.isLive = isLive;
[self setNeedsLayout];
}
// 时移的时候不能切清晰度
self.resolutionBtn.userInteractionEnabled = !isTimeShifting;
}
/** 播放按钮状态 */
- (void)setPlayState:(BOOL)state {
self.startBtn.selected = state;
}
- (void)setTitle:(NSString *)title
{
[super setTitle:title];
self.titleLabel.text = title;
}
- (void)hideDanmu {
[self setDisableDanmakuBtn:YES];
}
- (void)hideReplay {
[self.repeatBtn setHidden:YES];
}
#pragma clang diagnostic pop
@end
@@ -0,0 +1,40 @@
//
// SPWeiboControlView.h
// SuperPlayer
//
// Created by annidyfeng on 2018/10/8.
//
#import "SuperPlayerControlView.h"
@interface SPWeiboControlView : SuperPlayerControlView
/** 分辨率的名称 */
@property (nonatomic, strong) NSArray<NSString *> *resolutionArray;
/** 开始播放按钮 */
@property (nonatomic, strong) UIButton *startBtn;
/** 当前播放时长label */
@property (nonatomic, strong) UILabel *currentTimeLabel;
/** 视频总时长label */
@property (nonatomic, strong) UILabel *totalTimeLabel;
/** 全屏按钮 */
@property (nonatomic, strong) UIButton *fullScreenBtn;
/** 滑杆 */
@property (nonatomic, strong) PlayerSlider *videoSlider;
@property (nonatomic, strong) UIButton *moreBtn;
@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UIButton *muteBtn;
@property (nonatomic, assign,getter=isFullScreen)BOOL fullScreen;
/** 切换分辨率按钮 */
@property (nonatomic, strong) UIButton *resolutionBtn;
@property (nonatomic, strong) UIButton *resoultionCurrentBtn;
/** 分辨率的View */
@property (nonatomic, strong) UIView *resolutionView;
/** 更多设置View */
@property (nonatomic, strong) SuperPlayerSettingsView *moreContentView;
@property (nonatomic, strong) UIButton *pointJumpBtn;
@end
@@ -0,0 +1,487 @@
//
// SPWeiboControlView.m
// SuperPlayer
//
// Created by annidyfeng on 2018/10/8.
//
#import "SPWeiboControlView.h"
#import <Masonry/Masonry.h>
#import "UIView+Fade.h"
#import "UIView+MMLayout.h"
#import "StrUtils.h"
#import "DataReport.h"
#import "SuperPlayer.h"
@interface SPWeiboControlView() <PlayerSliderDelegate>
@property BOOL isLive;
@end
@implementation SPWeiboControlView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.startBtn];
[self addSubview:self.currentTimeLabel];
[self addSubview:self.totalTimeLabel];
[self addSubview:self.videoSlider];
[self addSubview:self.fullScreenBtn];
[self addSubview:self.resolutionBtn];
[self addSubview:self.muteBtn];
[self addSubview:self.moreBtn];
[self addSubview:self.backBtn];
// 添加子控件的约束
[self makeSubViewsConstraints];
[self resetControlView];
}
return self;
}
- (void)makeSubViewsConstraints {
[self.startBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
}];
[self.currentTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self).offset(-8);
make.left.mas_equalTo(@0);
make.width.mas_equalTo(@60);
}];
[self.fullScreenBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.currentTimeLabel);
make.right.equalTo(self).offset(-12);
}];
[self.resolutionBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.currentTimeLabel);
make.right.equalTo(self.fullScreenBtn.mas_left);
make.width.mas_equalTo(0);
}];
[self.totalTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.currentTimeLabel);
make.right.equalTo(self.resolutionBtn.mas_left);
make.width.mas_equalTo(@60);
}];
[self.videoSlider mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.currentTimeLabel);
make.left.equalTo(self.currentTimeLabel.mas_right);
make.right.equalTo(self.totalTimeLabel.mas_left);
}];
[self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self).offset(5);
make.top.equalTo(self).offset(3);
make.width.mas_equalTo(@60);
}];
[self.moreBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.equalTo(self).offset(-10);
make.centerY.equalTo(self.backBtn);
make.width.mas_equalTo(@40);
}];
[self.muteBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.equalTo(self.moreBtn.mas_leading).offset(-10);
make.centerY.equalTo(self.backBtn);
make.width.mas_equalTo(@40);
}];
}
- (UIButton *)startBtn {
if (!_startBtn) {
_startBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_startBtn setImage:SuperPlayerImage(@"wb_play") forState:UIControlStateNormal];
[_startBtn setImage:SuperPlayerImage(@"wb_pause") forState:UIControlStateSelected];
[_startBtn addTarget:self action:@selector(playBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _startBtn;
}
- (UILabel *)currentTimeLabel {
if (!_currentTimeLabel) {
_currentTimeLabel = [[UILabel alloc] init];
_currentTimeLabel.textColor = [UIColor whiteColor];
_currentTimeLabel.font = [UIFont systemFontOfSize:12.0f];
_currentTimeLabel.textAlignment = NSTextAlignmentCenter;
}
return _currentTimeLabel;
}
- (UIButton *)resolutionBtn {
if (!_resolutionBtn) {
_resolutionBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_resolutionBtn.titleLabel.font = [UIFont systemFontOfSize:12];
_resolutionBtn.backgroundColor = [UIColor clearColor];
[_resolutionBtn addTarget:self action:@selector(resolutionBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _resolutionBtn;
}
- (PlayerSlider *)videoSlider {
if (!_videoSlider) {
_videoSlider = [[PlayerSlider alloc] init];
[_videoSlider setThumbImage:SuperPlayerImage(@"wb_thumb") forState:UIControlStateNormal];
_videoSlider.minimumTrackTintColor = RGBA(223, 223, 223, 1);
// slider开始滑动事件
[_videoSlider addTarget:self action:@selector(progressSliderTouchBegan:) forControlEvents:UIControlEventTouchDown];
// slider滑动中事件
[_videoSlider addTarget:self action:@selector(progressSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
// slider结束滑动事件
[_videoSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside|UIControlEventTouchCancel];
_videoSlider.delegate = self;
}
return _videoSlider;
}
- (UILabel *)totalTimeLabel {
if (!_totalTimeLabel) {
_totalTimeLabel = [[UILabel alloc] init];
_totalTimeLabel.textColor = [UIColor whiteColor];
_totalTimeLabel.font = [UIFont systemFontOfSize:12.0f];
_totalTimeLabel.textAlignment = NSTextAlignmentCenter;
}
return _totalTimeLabel;
}
- (UIButton *)fullScreenBtn {
if (!_fullScreenBtn) {
_fullScreenBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_fullScreenBtn setImage:SuperPlayerImage(@"wb_fullscreen") forState:UIControlStateNormal];
[_fullScreenBtn setImage:SuperPlayerImage(@"wb_fullscreen_back") forState:UIControlStateSelected];
[_fullScreenBtn addTarget:self action:@selector(fullScreenBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _fullScreenBtn;
}
- (UIButton *)backBtn {
if (!_backBtn) {
_backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_backBtn setImage:SuperPlayerImage(@"wb_back") forState:UIControlStateNormal];
[_backBtn addTarget:self action:@selector(fullScreenBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _backBtn;
}
- (UIButton *)moreBtn {
if (!_moreBtn) {
_moreBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_moreBtn setImage:SuperPlayerImage(@"wb_more") forState:UIControlStateNormal];
[_moreBtn addTarget:self action:@selector(moreBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _moreBtn;
}
- (UIButton *)muteBtn {
if (!_muteBtn) {
_muteBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_muteBtn setImage:SuperPlayerImage(@"wb_volume_on") forState:UIControlStateNormal];
[_muteBtn setImage:SuperPlayerImage(@"wb_volume_off") forState:UIControlStateSelected];
[_muteBtn addTarget:self action:@selector(muteBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _muteBtn;
}
- (UIView *)resolutionView {
if (!_resolutionView) {
// 添加分辨率按钮和分辨率下拉列表
_resolutionView = [[UIView alloc] initWithFrame:CGRectZero];
_resolutionView.hidden = YES;
[self addSubview:_resolutionView];
[_resolutionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(330);
make.height.mas_equalTo(self.mas_height);
make.trailing.equalTo(self.mas_trailing).offset(0);
make.top.equalTo(self.mas_top).offset(0);
}];
_resolutionView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
}
return _resolutionView;
}
- (SuperPlayerSettingsView *)moreContentView {
if (!_moreContentView) {
_moreContentView = [[SuperPlayerSettingsView alloc] initWithFrame:CGRectZero];
_moreContentView.controlView = self;
[self addSubview:_moreContentView];
[_moreContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(330);
make.height.mas_equalTo(self.mas_height);
make.trailing.equalTo(self.mas_trailing).offset(0);
make.top.equalTo(self.mas_top).offset(0);
}];
_moreContentView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
}
return _moreContentView;
}
- (void)playBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) {
[self.delegate controlViewPlay:self];
} else {
[self.delegate controlViewPause:self];
}
[self cancelFadeOut];
}
- (void)fullScreenBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
[self.delegate controlViewChangeScreen:self withFullScreen:sender.selected];
}
- (void)progressSliderTouchBegan:(UISlider *)sender {
self.isDragging = YES;
self.startBtn.hidden = YES; // 播放按钮挡住了fastView
[self cancelFadeOut];
}
- (void)progressSliderValueChanged:(UISlider *)sender {
if (self.maxPlayableRatio > 0 && sender.value * self.maxPlayableRatio) {
sender.value = self.maxPlayableRatio;
}
[self.delegate controlViewPreview:self where:sender.value];
}
- (void)progressSliderTouchEnded:(UISlider *)sender {
[self.delegate controlViewSeek:self where:sender.value];
self.isDragging = NO;
self.startBtn.hidden = NO;
[self cancelFadeOut];
}
- (void)setProgressTime:(NSInteger)currentTime totalTime:(NSInteger)totalTime
progressValue:(CGFloat)progress playableValue:(CGFloat)playable;
{
if (!self.isDragging) {
// 更新slider
self.videoSlider.value = progress;
// 更新当前播放时间
self.currentTimeLabel.text = [StrUtils timeFormat:currentTime];
}
// 更新总时间
self.totalTimeLabel.text = [StrUtils timeFormat:totalTime];
[self.videoSlider.progressView setProgress:playable animated:NO];
}
- (void)muteBtnClick:(UIButton *)sender
{
sender.selected = self.playerConfig.mute = !self.playerConfig.mute;
[self.delegate controlViewConfigUpdate:self withReload:NO];
[self fadeOut:3];
}
/** 重置ControlView */
- (void)resetControlView {
self.videoSlider.value = 0;
self.videoSlider.progressView.progress = 0;
self.currentTimeLabel.text = @"00:00";
self.totalTimeLabel.text = @"00:00";
self.moreContentView.hidden = YES;
}
- (void)setHidden:(BOOL)hidden
{
[super setHidden:hidden];
for (UIView *view in self.subviews) {
if (view != self.resolutionView && view != self.moreContentView) {
if (!self.isFullScreen && (view == self.backBtn || view == self.moreBtn || view == self.muteBtn))
view.hidden = YES;
else
view.hidden = NO;
} else {
view.hidden = YES;
}
}
self.isShowSecondView = NO;
self.pointJumpBtn.hidden = YES;
}
/** 播放按钮状态 */
- (void)setPlayState:(BOOL)isPlay {
self.startBtn.selected = isPlay;
}
- (void)resolutionBtnClick:(UIButton *)sender {
for (UIView *view in self.subviews) {
view.hidden = YES;
}
// 显示分辨率View
self.resolutionView.hidden = NO;
[DataReport report:@"change_resolution" param:nil];
[self cancelFadeOut];
self.isShowSecondView = YES;
}
- (void)moreBtnClick:(UIButton *)sender {
for (UIView *view in self.subviews) {
view.hidden = YES;
}
self.moreContentView.playerConfig = self.playerConfig;
self.moreContentView.enableSpeedAndMirrorControl = !self.isLive;
[self.moreContentView update];
self.moreContentView.hidden = NO;
[self cancelFadeOut];
self.isShowSecondView = YES;
}
- (void)resetWithResolutionNames:(NSArray<NSString *> *)resolutionNames
currentResolutionIndex:(NSUInteger)currentResolutionIndex
isLive:(BOOL)isLive
isTimeShifting:(BOOL)isTimeShifting
isPlaying:(BOOL)isPlaying
{
[self setPlayState:isPlaying];
_resolutionArray = resolutionNames;
NSAssert(currentResolutionIndex < resolutionNames.count,
@"Invalid argument when reseeting %@", NSStringFromClass(self.class));
if (resolutionNames.count > 0) {
[self.resolutionBtn setTitle:resolutionNames[currentResolutionIndex]
forState:UIControlStateNormal];
}
for (UIView *subview in self.resolutionView.subviews)
[subview removeFromSuperview];
UILabel *lable = [UILabel new];
lable.text = @"清晰度";
lable.textAlignment = NSTextAlignmentCenter;
lable.textColor = [UIColor whiteColor];
[self.resolutionView addSubview:lable];
[lable mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.resolutionView.mas_width);
make.height.mas_equalTo(30);
make.left.equalTo(self.resolutionView.mas_left);
make.top.equalTo(self.resolutionView.mas_top).mas_offset(20);
}];
// 分辨率View上边的Btn
for (NSInteger i = 0 ; i < _resolutionArray.count; i++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:_resolutionArray[i] forState:UIControlStateNormal];
[btn setTitleColor:RGBA(252, 89, 81, 1) forState:UIControlStateSelected];
[self.resolutionView addSubview:btn];
[btn addTarget:self action:@selector(changeResolution:) forControlEvents:UIControlEventTouchUpInside];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.resolutionView.mas_width);
make.height.mas_equalTo(45);
make.left.equalTo(self.resolutionView.mas_left);
make.centerY.equalTo(self.resolutionView.mas_centerY).offset((i-self.resolutionArray.count/2.0+0.5)*45);
}];
if (i == currentResolutionIndex) {
btn.selected = YES;
btn.backgroundColor = RGBA(34, 30, 24, 1);
self.resoultionCurrentBtn = btn;
}
}
if (self.isLive != isLive) {
self.isLive = isLive;
[self setNeedsLayout];
}
// 时移的时候不能切清晰度
self.resolutionBtn.userInteractionEnabled = !isTimeShifting;
}
/**
* 点击切换分别率按钮
*/
- (void)changeResolution:(UIButton *)sender {
self.resoultionCurrentBtn.selected = NO;
self.resoultionCurrentBtn.backgroundColor = [UIColor clearColor];
self.resoultionCurrentBtn = sender;
self.resoultionCurrentBtn.selected = YES;
self.resoultionCurrentBtn.backgroundColor = RGBA(34, 30, 24, 1);
// topImageView上的按钮的文字
[self.resolutionBtn setTitle:sender.titleLabel.text forState:UIControlStateNormal];
[self.delegate controlViewSwitch:self withDefinition:sender.titleLabel.text];
}
- (void)setOrientationLandscapeConstraint {
self.fullScreen = YES;
self.fullScreenBtn.selected = YES;
self.moreBtn.hidden = NO;
self.backBtn.hidden = NO;
self.muteBtn.hidden = NO;
[self.resolutionBtn mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(@60);
}];
self.videoSlider.hiddenPoints = NO;
}
- (void)setOrientationPortraitConstraint {
self.fullScreen = NO;
self.fullScreenBtn.selected = NO;
self.moreBtn.hidden = YES;
self.backBtn.hidden = YES;
self.muteBtn.hidden = YES;
[self.resolutionBtn mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(@0);
}];
self.videoSlider.hiddenPoints = YES;
self.pointJumpBtn.hidden = YES;
}
- (void)setPointArray:(NSArray *)pointArray
{
[super setPointArray:pointArray];
for (PlayerPoint *holder in self.videoSlider.pointArray) {
[holder.holder removeFromSuperview];
}
[self.videoSlider.pointArray removeAllObjects];
for (SPVideoFrameDescription *p in pointArray) {
PlayerPoint *point = [self.videoSlider addPoint:p.where];
point.content = p.text;
point.timeOffset = p.time;
}
}
- (UIButton *)pointJumpBtn {
if (!_pointJumpBtn) {
_pointJumpBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = SuperPlayerImage(@"copywright_bg");
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, 20, 0, 20) resizingMode:UIImageResizingModeStretch];
[_pointJumpBtn setBackgroundImage:resizableImage forState:UIControlStateNormal];
_pointJumpBtn.titleLabel.font = [UIFont systemFontOfSize:14];
[_pointJumpBtn addTarget:self action:@selector(pointJumpClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_pointJumpBtn];
}
return _pointJumpBtn;
}
- (void)pointJumpClick:(UIButton *)sender {
PlayerPoint *point = [self.videoSlider.pointArray objectAtIndex:self.pointJumpBtn.tag];
[self.delegate controlViewSeek:self where:point.where];
[self fadeOut:0.1];
}
- (void)onPlayerPointSelected:(PlayerPoint *)point {
NSString *text = [NSString stringWithFormat:@" %@ %@ ", [StrUtils timeFormat:point.timeOffset],
point.content];
[self.pointJumpBtn setTitle:text forState:UIControlStateNormal];
[self.pointJumpBtn sizeToFit];
CGFloat x = self.videoSlider.mm_x + self.videoSlider.mm_w * point.where - self.pointJumpBtn.mm_w/2;
if (x < 0)
x = 0;
if (x + self.pointJumpBtn.mm_w/2 > ScreenWidth)
x = ScreenWidth - self.pointJumpBtn.mm_w/2;
self.pointJumpBtn.tag = [self.videoSlider.pointArray indexOfObject:point];
self.pointJumpBtn.m_left(x).m_bottom(60);
self.pointJumpBtn.hidden = NO;
[DataReport report:@"player_point" param:nil];
}
@end
@@ -0,0 +1,12 @@
//
// SPWithoutControlView.h
// SuperPlayer
//
// Created by annidyfeng on 2021/4/15.
//
#import "SuperPlayerControlView.h"
@interface SPWithoutControlView : SuperPlayerControlView
@end
@@ -0,0 +1,39 @@
#import "SuperPlayerControlView.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import "SuperPlayerSettingsView.h"
#import "DataReport.h"
#import "SuperPlayerFastView.h"
#import "PlayerSlider.h"
#import "UIView+MMLayout.h"
#import "SuperPlayerView+Private.h"
#import "StrUtils.h"
#import "SPWithoutControlView.h"
#import "UIView+Fade.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
#define MODEL_TAG_BEGIN 20
#define BOTTOM_IMAGE_VIEW_HEIGHT 50
@interface SPWithoutControlView () <UIGestureRecognizerDelegate, PlayerSliderDelegate>
@property BOOL isLive;
@end
@implementation SPWithoutControlView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// skip
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

Some files were not shown because too many files have changed in this diff Show More