This commit is contained in:
2024-06-11 10:51:38 +08:00
parent 4326de86e5
commit 1989abab7f
66 changed files with 6450 additions and 29 deletions

View File

@ -111,6 +111,35 @@
91C871412C13111B0093790D /* HBHomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871402C13111B0093790D /* HBHomeViewController.m */; };
91C871442C13112F0093790D /* HBDiscoverViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871432C13112F0093790D /* HBDiscoverViewController.m */; };
91C871472C1311450093790D /* HBMineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871462C1311450093790D /* HBMineViewController.m */; };
91C8718E2C1314770093790D /* UIButton+GKEnlarge.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871492C1314770093790D /* UIButton+GKEnlarge.m */; };
91C8718F2C1314770093790D /* GKDoubleLikeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8714C2C1314770093790D /* GKDoubleLikeView.m */; };
91C871902C1314770093790D /* GKLikeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8714E2C1314770093790D /* GKLikeView.m */; };
91C871912C1314770093790D /* GKBallLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871512C1314770093790D /* GKBallLoadingView.m */; };
91C871922C1314770093790D /* GKLandscapeNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871542C1314770093790D /* GKLandscapeNavigationController.m */; };
91C871932C1314770093790D /* GKLandscapeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871562C1314770093790D /* GKLandscapeViewController.m */; };
91C871942C1314770093790D /* GKLandscapeWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871582C1314770093790D /* GKLandscapeWindow.m */; };
91C871952C1314770093790D /* GKRotationManager_iOS_9_15.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8715A2C1314770093790D /* GKRotationManager_iOS_9_15.m */; };
91C871962C1314770093790D /* GKRotationManager_iOS_16_Later.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8715C2C1314770093790D /* GKRotationManager_iOS_16_Later.m */; };
91C871972C1314770093790D /* GKRotationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8715E2C1314770093790D /* GKRotationManager.m */; };
91C871992C1314770093790D /* GKDYPlayerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871652C1314770093790D /* GKDYPlayerManager.m */; };
91C8719A2C1314770093790D /* GKDUVideoInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871682C1314770093790D /* GKDUVideoInfoModel.m */; };
91C8719B2C1314770093790D /* GKDYVideoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8716A2C1314770093790D /* GKDYVideoModel.m */; };
91C8719C2C1314770093790D /* GKDYPanGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8716D2C1314770093790D /* GKDYPanGestureRecognizer.m */; };
91C8719D2C1314770093790D /* GKDYScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8716F2C1314770093790D /* GKDYScrollView.m */; };
91C8719E2C1314770093790D /* GKDYTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871712C1314770093790D /* GKDYTitleView.m */; };
91C8719F2C1314770093790D /* GKDYVideoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871732C1314770093790D /* GKDYVideoCell.m */; };
91C871A02C1314770093790D /* GKDYVideoControlView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871752C1314770093790D /* GKDYVideoControlView.m */; };
91C871A12C1314770093790D /* GKDYVideoFullscreenView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871772C1314770093790D /* GKDYVideoFullscreenView.m */; };
91C871A22C1314770093790D /* GKDYVideoItemButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871792C1314770093790D /* GKDYVideoItemButton.m */; };
91C871A32C1314770093790D /* GKDYVideoLandscapeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8717B2C1314770093790D /* GKDYVideoLandscapeCell.m */; };
91C871A42C1314770093790D /* GKDYVideoLandscapeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8717D2C1314770093790D /* GKDYVideoLandscapeView.m */; };
91C871A52C1314770093790D /* GKDYVideoMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8717F2C1314770093790D /* GKDYVideoMaskView.m */; };
91C871A62C1314770093790D /* GKDYVideoPortraitCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871812C1314770093790D /* GKDYVideoPortraitCell.m */; };
91C871A72C1314770093790D /* GKDYVideoPortraitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871832C1314770093790D /* GKDYVideoPortraitView.m */; };
91C871A82C1314770093790D /* GKDYVideoPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871852C1314770093790D /* GKDYVideoPreviewView.m */; };
91C871A92C1314770093790D /* GKDYVideoScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871872C1314770093790D /* GKDYVideoScrollView.m */; };
91C871AA2C1314770093790D /* GKDYVideoSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C871892C1314770093790D /* GKDYVideoSlider.m */; };
91C871AB2C1314770093790D /* GKDYVideoStatusBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C8718B2C1314770093790D /* GKDYVideoStatusBar.m */; };
C8AC2283D47E2B99FF559E75 /* libPods-HiBit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 141F02EF5C0783797594009A /* libPods-HiBit.a */; };
/* End PBXBuildFile section */
@ -327,6 +356,64 @@
91C871432C13112F0093790D /* HBDiscoverViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBDiscoverViewController.m; sourceTree = "<group>"; };
91C871452C1311450093790D /* HBMineViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBMineViewController.h; sourceTree = "<group>"; };
91C871462C1311450093790D /* HBMineViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBMineViewController.m; sourceTree = "<group>"; };
91C871482C1314770093790D /* UIButton+GKEnlarge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+GKEnlarge.h"; sourceTree = "<group>"; };
91C871492C1314770093790D /* UIButton+GKEnlarge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+GKEnlarge.m"; sourceTree = "<group>"; };
91C8714B2C1314770093790D /* GKDoubleLikeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDoubleLikeView.h; sourceTree = "<group>"; };
91C8714C2C1314770093790D /* GKDoubleLikeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDoubleLikeView.m; sourceTree = "<group>"; };
91C8714D2C1314770093790D /* GKLikeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKLikeView.h; sourceTree = "<group>"; };
91C8714E2C1314770093790D /* GKLikeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKLikeView.m; sourceTree = "<group>"; };
91C871502C1314770093790D /* GKBallLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKBallLoadingView.h; sourceTree = "<group>"; };
91C871512C1314770093790D /* GKBallLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKBallLoadingView.m; sourceTree = "<group>"; };
91C871532C1314770093790D /* GKLandscapeNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKLandscapeNavigationController.h; sourceTree = "<group>"; };
91C871542C1314770093790D /* GKLandscapeNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKLandscapeNavigationController.m; sourceTree = "<group>"; };
91C871552C1314770093790D /* GKLandscapeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKLandscapeViewController.h; sourceTree = "<group>"; };
91C871562C1314770093790D /* GKLandscapeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKLandscapeViewController.m; sourceTree = "<group>"; };
91C871572C1314770093790D /* GKLandscapeWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKLandscapeWindow.h; sourceTree = "<group>"; };
91C871582C1314770093790D /* GKLandscapeWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKLandscapeWindow.m; sourceTree = "<group>"; };
91C871592C1314770093790D /* GKRotationManager_iOS_9_15.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKRotationManager_iOS_9_15.h; sourceTree = "<group>"; };
91C8715A2C1314770093790D /* GKRotationManager_iOS_9_15.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKRotationManager_iOS_9_15.m; sourceTree = "<group>"; };
91C8715B2C1314770093790D /* GKRotationManager_iOS_16_Later.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKRotationManager_iOS_16_Later.h; sourceTree = "<group>"; };
91C8715C2C1314770093790D /* GKRotationManager_iOS_16_Later.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKRotationManager_iOS_16_Later.m; sourceTree = "<group>"; };
91C8715D2C1314770093790D /* GKRotationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKRotationManager.h; sourceTree = "<group>"; };
91C8715E2C1314770093790D /* GKRotationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKRotationManager.m; sourceTree = "<group>"; };
91C871642C1314770093790D /* GKDYPlayerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYPlayerManager.h; sourceTree = "<group>"; };
91C871652C1314770093790D /* GKDYPlayerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYPlayerManager.m; sourceTree = "<group>"; };
91C871672C1314770093790D /* GKDUVideoInfoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDUVideoInfoModel.h; sourceTree = "<group>"; };
91C871682C1314770093790D /* GKDUVideoInfoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDUVideoInfoModel.m; sourceTree = "<group>"; };
91C871692C1314770093790D /* GKDYVideoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoModel.h; sourceTree = "<group>"; };
91C8716A2C1314770093790D /* GKDYVideoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoModel.m; sourceTree = "<group>"; };
91C8716C2C1314770093790D /* GKDYPanGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYPanGestureRecognizer.h; sourceTree = "<group>"; };
91C8716D2C1314770093790D /* GKDYPanGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYPanGestureRecognizer.m; sourceTree = "<group>"; };
91C8716E2C1314770093790D /* GKDYScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYScrollView.h; sourceTree = "<group>"; };
91C8716F2C1314770093790D /* GKDYScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYScrollView.m; sourceTree = "<group>"; };
91C871702C1314770093790D /* GKDYTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYTitleView.h; sourceTree = "<group>"; };
91C871712C1314770093790D /* GKDYTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYTitleView.m; sourceTree = "<group>"; };
91C871722C1314770093790D /* GKDYVideoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoCell.h; sourceTree = "<group>"; };
91C871732C1314770093790D /* GKDYVideoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoCell.m; sourceTree = "<group>"; };
91C871742C1314770093790D /* GKDYVideoControlView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoControlView.h; sourceTree = "<group>"; };
91C871752C1314770093790D /* GKDYVideoControlView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoControlView.m; sourceTree = "<group>"; };
91C871762C1314770093790D /* GKDYVideoFullscreenView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoFullscreenView.h; sourceTree = "<group>"; };
91C871772C1314770093790D /* GKDYVideoFullscreenView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoFullscreenView.m; sourceTree = "<group>"; };
91C871782C1314770093790D /* GKDYVideoItemButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoItemButton.h; sourceTree = "<group>"; };
91C871792C1314770093790D /* GKDYVideoItemButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoItemButton.m; sourceTree = "<group>"; };
91C8717A2C1314770093790D /* GKDYVideoLandscapeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoLandscapeCell.h; sourceTree = "<group>"; };
91C8717B2C1314770093790D /* GKDYVideoLandscapeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoLandscapeCell.m; sourceTree = "<group>"; };
91C8717C2C1314770093790D /* GKDYVideoLandscapeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoLandscapeView.h; sourceTree = "<group>"; };
91C8717D2C1314770093790D /* GKDYVideoLandscapeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoLandscapeView.m; sourceTree = "<group>"; };
91C8717E2C1314770093790D /* GKDYVideoMaskView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoMaskView.h; sourceTree = "<group>"; };
91C8717F2C1314770093790D /* GKDYVideoMaskView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoMaskView.m; sourceTree = "<group>"; };
91C871802C1314770093790D /* GKDYVideoPortraitCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoPortraitCell.h; sourceTree = "<group>"; };
91C871812C1314770093790D /* GKDYVideoPortraitCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoPortraitCell.m; sourceTree = "<group>"; };
91C871822C1314770093790D /* GKDYVideoPortraitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoPortraitView.h; sourceTree = "<group>"; };
91C871832C1314770093790D /* GKDYVideoPortraitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoPortraitView.m; sourceTree = "<group>"; };
91C871842C1314770093790D /* GKDYVideoPreviewView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoPreviewView.h; sourceTree = "<group>"; };
91C871852C1314770093790D /* GKDYVideoPreviewView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoPreviewView.m; sourceTree = "<group>"; };
91C871862C1314770093790D /* GKDYVideoScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoScrollView.h; sourceTree = "<group>"; };
91C871872C1314770093790D /* GKDYVideoScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoScrollView.m; sourceTree = "<group>"; };
91C871882C1314770093790D /* GKDYVideoSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoSlider.h; sourceTree = "<group>"; };
91C871892C1314770093790D /* GKDYVideoSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoSlider.m; sourceTree = "<group>"; };
91C8718A2C1314770093790D /* GKDYVideoStatusBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKDYVideoStatusBar.h; sourceTree = "<group>"; };
91C8718B2C1314770093790D /* GKDYVideoStatusBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GKDYVideoStatusBar.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -782,6 +869,7 @@
916353402C12C10100593047 /* Project */ = {
isa = PBXGroup;
children = (
91C8718D2C1314770093790D /* Player */,
916353852C12C20B00593047 /* Publics */,
9163533F2C12C01E00593047 /* Services */,
91C871362C13108E0093790D /* Login */,
@ -1039,6 +1127,135 @@
path = Views;
sourceTree = "<group>";
};
91C8714A2C1314770093790D /* Category */ = {
isa = PBXGroup;
children = (
91C871482C1314770093790D /* UIButton+GKEnlarge.h */,
91C871492C1314770093790D /* UIButton+GKEnlarge.m */,
);
path = Category;
sourceTree = "<group>";
};
91C8714F2C1314770093790D /* GKLikeView */ = {
isa = PBXGroup;
children = (
91C8714B2C1314770093790D /* GKDoubleLikeView.h */,
91C8714C2C1314770093790D /* GKDoubleLikeView.m */,
91C8714D2C1314770093790D /* GKLikeView.h */,
91C8714E2C1314770093790D /* GKLikeView.m */,
);
path = GKLikeView;
sourceTree = "<group>";
};
91C871522C1314770093790D /* GKLoadingView */ = {
isa = PBXGroup;
children = (
91C871502C1314770093790D /* GKBallLoadingView.h */,
91C871512C1314770093790D /* GKBallLoadingView.m */,
);
path = GKLoadingView;
sourceTree = "<group>";
};
91C8715F2C1314770093790D /* GKRotationManager */ = {
isa = PBXGroup;
children = (
91C871532C1314770093790D /* GKLandscapeNavigationController.h */,
91C871542C1314770093790D /* GKLandscapeNavigationController.m */,
91C871552C1314770093790D /* GKLandscapeViewController.h */,
91C871562C1314770093790D /* GKLandscapeViewController.m */,
91C871572C1314770093790D /* GKLandscapeWindow.h */,
91C871582C1314770093790D /* GKLandscapeWindow.m */,
91C871592C1314770093790D /* GKRotationManager_iOS_9_15.h */,
91C8715A2C1314770093790D /* GKRotationManager_iOS_9_15.m */,
91C8715B2C1314770093790D /* GKRotationManager_iOS_16_Later.h */,
91C8715C2C1314770093790D /* GKRotationManager_iOS_16_Later.m */,
91C8715D2C1314770093790D /* GKRotationManager.h */,
91C8715E2C1314770093790D /* GKRotationManager.m */,
);
path = GKRotationManager;
sourceTree = "<group>";
};
91C871602C1314770093790D /* Common */ = {
isa = PBXGroup;
children = (
91C8714A2C1314770093790D /* Category */,
91C8714F2C1314770093790D /* GKLikeView */,
91C871522C1314770093790D /* GKLoadingView */,
91C8715F2C1314770093790D /* GKRotationManager */,
);
path = Common;
sourceTree = "<group>";
};
91C871662C1314770093790D /* Manager */ = {
isa = PBXGroup;
children = (
91C871642C1314770093790D /* GKDYPlayerManager.h */,
91C871652C1314770093790D /* GKDYPlayerManager.m */,
);
path = Manager;
sourceTree = "<group>";
};
91C8716B2C1314770093790D /* Model */ = {
isa = PBXGroup;
children = (
91C871672C1314770093790D /* GKDUVideoInfoModel.h */,
91C871682C1314770093790D /* GKDUVideoInfoModel.m */,
91C871692C1314770093790D /* GKDYVideoModel.h */,
91C8716A2C1314770093790D /* GKDYVideoModel.m */,
);
path = Model;
sourceTree = "<group>";
};
91C8718C2C1314770093790D /* View */ = {
isa = PBXGroup;
children = (
91C8716C2C1314770093790D /* GKDYPanGestureRecognizer.h */,
91C8716D2C1314770093790D /* GKDYPanGestureRecognizer.m */,
91C8716E2C1314770093790D /* GKDYScrollView.h */,
91C8716F2C1314770093790D /* GKDYScrollView.m */,
91C871702C1314770093790D /* GKDYTitleView.h */,
91C871712C1314770093790D /* GKDYTitleView.m */,
91C871722C1314770093790D /* GKDYVideoCell.h */,
91C871732C1314770093790D /* GKDYVideoCell.m */,
91C871742C1314770093790D /* GKDYVideoControlView.h */,
91C871752C1314770093790D /* GKDYVideoControlView.m */,
91C871762C1314770093790D /* GKDYVideoFullscreenView.h */,
91C871772C1314770093790D /* GKDYVideoFullscreenView.m */,
91C871782C1314770093790D /* GKDYVideoItemButton.h */,
91C871792C1314770093790D /* GKDYVideoItemButton.m */,
91C8717A2C1314770093790D /* GKDYVideoLandscapeCell.h */,
91C8717B2C1314770093790D /* GKDYVideoLandscapeCell.m */,
91C8717C2C1314770093790D /* GKDYVideoLandscapeView.h */,
91C8717D2C1314770093790D /* GKDYVideoLandscapeView.m */,
91C8717E2C1314770093790D /* GKDYVideoMaskView.h */,
91C8717F2C1314770093790D /* GKDYVideoMaskView.m */,
91C871802C1314770093790D /* GKDYVideoPortraitCell.h */,
91C871812C1314770093790D /* GKDYVideoPortraitCell.m */,
91C871822C1314770093790D /* GKDYVideoPortraitView.h */,
91C871832C1314770093790D /* GKDYVideoPortraitView.m */,
91C871842C1314770093790D /* GKDYVideoPreviewView.h */,
91C871852C1314770093790D /* GKDYVideoPreviewView.m */,
91C871862C1314770093790D /* GKDYVideoScrollView.h */,
91C871872C1314770093790D /* GKDYVideoScrollView.m */,
91C871882C1314770093790D /* GKDYVideoSlider.h */,
91C871892C1314770093790D /* GKDYVideoSlider.m */,
91C8718A2C1314770093790D /* GKDYVideoStatusBar.h */,
91C8718B2C1314770093790D /* GKDYVideoStatusBar.m */,
);
path = View;
sourceTree = "<group>";
};
91C8718D2C1314770093790D /* Player */ = {
isa = PBXGroup;
children = (
91C871602C1314770093790D /* Common */,
91C871662C1314770093790D /* Manager */,
91C8716B2C1314770093790D /* Model */,
91C8718C2C1314770093790D /* View */,
);
path = Player;
sourceTree = "<group>";
};
B36329ED094310C499FEBA2F /* Frameworks */ = {
isa = PBXGroup;
children = (
@ -1184,28 +1401,43 @@
files = (
916353892C12C20B00593047 /* HBNavigationController.m in Sources */,
916353002C12B6D400593047 /* NSUserDefaults+Extesion.m in Sources */,
91C871A12C1314770093790D /* GKDYVideoFullscreenView.m in Sources */,
91C871A92C1314770093790D /* GKDYVideoScrollView.m in Sources */,
916351402C12B12F00593047 /* AppDelegate.m in Sources */,
91C871A72C1314770093790D /* GKDYVideoPortraitView.m in Sources */,
9163530D2C12B6D400593047 /* UINavigationController+Transparent.m in Sources */,
916352FA2C12B6D400593047 /* NSNumber+Extension.m in Sources */,
9163534D2C12C15300593047 /* HBNetWorkingUtilityResult.m in Sources */,
916353292C12B6D400593047 /* DGActivityIndicatorLineScalePulseOutRapidAnimation.m in Sources */,
916353A22C12C3DC00593047 /* HtyoNetWorking.m in Sources */,
91C871992C1314770093790D /* GKDYPlayerManager.m in Sources */,
916353232C12B6D400593047 /* DGActivityIndicatorCookieTerminatorAnimation.m in Sources */,
91C871A42C1314770093790D /* GKDYVideoLandscapeView.m in Sources */,
91C871412C13111B0093790D /* HBHomeViewController.m in Sources */,
91C871A62C1314770093790D /* GKDYVideoPortraitCell.m in Sources */,
91C8718F2C1314770093790D /* GKDoubleLikeView.m in Sources */,
9163530A2C12B6D400593047 /* NSLayoutConstraint+BSIBDesignable.m in Sources */,
9163534C2C12C15300593047 /* HBNetWorkingUtility.m in Sources */,
91C8719A2C1314770093790D /* GKDUVideoInfoModel.m in Sources */,
916353352C12B6D400593047 /* SVIndefiniteAnimatedView.m in Sources */,
916353332C12B6D400593047 /* DGActivityIndicatorView.m in Sources */,
916353152C12B6D400593047 /* DGActivityIndicatorBallClipRotatePulseAnimation.m in Sources */,
91C8719E2C1314770093790D /* GKDYTitleView.m in Sources */,
916353132C12B6D400593047 /* DGActivityIndicatorBallClipRotateAnimation.m in Sources */,
91C871952C1314770093790D /* GKRotationManager_iOS_9_15.m in Sources */,
916353322C12B6D400593047 /* DGActivityIndicatorTwoDotsAnimation.m in Sources */,
916353862C12C20B00593047 /* HBColor.m in Sources */,
9163532B2C12B6D400593047 /* DGActivityIndicatorRotatingSandglassAnimation.m in Sources */,
91C871912C1314770093790D /* GKBallLoadingView.m in Sources */,
9163530E2C12B6D400593047 /* UIViewController+present.m in Sources */,
916353212C12B6D400593047 /* DGActivityIndicatorBallZigZagAnimation.m in Sources */,
91C871942C1314770093790D /* GKLandscapeWindow.m in Sources */,
91C871922C1314770093790D /* GKLandscapeNavigationController.m in Sources */,
916353262C12B6D400593047 /* DGActivityIndicatorLineScaleAnimation.m in Sources */,
916353272C12B6D400593047 /* DGActivityIndicatorLineScalePartyAnimation.m in Sources */,
91C871A52C1314770093790D /* GKDYVideoMaskView.m in Sources */,
916353102C12B6D400593047 /* NSString+AES.m in Sources */,
91C871A22C1314770093790D /* GKDYVideoItemButton.m in Sources */,
9163538B2C12C20B00593047 /* HBViewController.m in Sources */,
9163531A2C12B6D400593047 /* DGActivityIndicatorBallRotateAnimation.m in Sources */,
916352F82C12B6D400593047 /* NSDate+Extension.m in Sources */,
@ -1214,9 +1446,13 @@
9163531D2C12B6D400593047 /* DGActivityIndicatorBallScaleRippleAnimation.m in Sources */,
9163533A2C12B6D400593047 /* HUDManager.m in Sources */,
916353072C12B6D400593047 /* UIScreen+Extension.m in Sources */,
91C8719D2C1314770093790D /* GKDYScrollView.m in Sources */,
916353282C12B6D400593047 /* DGActivityIndicatorLineScalePulseOutAnimation.m in Sources */,
91C871972C1314770093790D /* GKRotationManager.m in Sources */,
9163534B2C12C15300593047 /* HBApiParams.m in Sources */,
9163531C2C12B6D400593047 /* DGActivityIndicatorBallScaleMultipleAnimation.m in Sources */,
91C871A32C1314770093790D /* GKDYVideoLandscapeCell.m in Sources */,
91C871AA2C1314770093790D /* GKDYVideoSlider.m in Sources */,
916353042C12B6D400593047 /* UIFont+Category.m in Sources */,
916353092C12B6D400593047 /* UITextField+Category.m in Sources */,
916353972C12C20B00593047 /* HBTableView.m in Sources */,
@ -1230,10 +1466,14 @@
9163538D2C12C20B00593047 /* HBMultiLanguageManager.m in Sources */,
9163531F2C12B6D400593047 /* DGActivityIndicatorBallSpinFadeLoader.m in Sources */,
9163539A2C12C20B00593047 /* RSButton.m in Sources */,
91C8719F2C1314770093790D /* GKDYVideoCell.m in Sources */,
91C8718E2C1314770093790D /* UIButton+GKEnlarge.m in Sources */,
916353302C12B6D400593047 /* DGActivityIndicatorTriplePulseAnimation.m in Sources */,
916353022C12B6D400593047 /* UIControl+Extension.m in Sources */,
9163532D2C12B6D400593047 /* DGActivityIndicatorRotatingTrigonAnimation.m in Sources */,
91C871902C1314770093790D /* GKLikeView.m in Sources */,
916353342C12B6D400593047 /* MBProgressHUD.m in Sources */,
91C871A82C1314770093790D /* GKDYVideoPreviewView.m in Sources */,
916353242C12B6D400593047 /* DGActivityIndicatorDoubleBounceAnimation.m in Sources */,
9163538C2C12C20B00593047 /* HBMultiLanguageController.m in Sources */,
916353192C12B6D400593047 /* DGActivityIndicatorBallPulseSyncAnimation.m in Sources */,
@ -1241,6 +1481,7 @@
9163533D2C12B6D400593047 /* KxMenu.m in Sources */,
916353A82C12C6AF00593047 /* NSNotificationCenter+Extension.m in Sources */,
91C8711E2C12ECF50093790D /* HBFirstStartController.m in Sources */,
91C8719B2C1314770093790D /* GKDYVideoModel.m in Sources */,
9163531E2C12B6D400593047 /* DGActivityIndicatorBallScaleRippleMultipleAnimation.m in Sources */,
916353362C12B6D400593047 /* SVProgressAnimatedView.m in Sources */,
916353112C12B6D400593047 /* DGActivityIndicatorAnimation.m in Sources */,
@ -1248,6 +1489,7 @@
9163531B2C12B6D400593047 /* DGActivityIndicatorBallScaleAnimation.m in Sources */,
916353182C12B6D400593047 /* DGActivityIndicatorBallPulseAnimation.m in Sources */,
916353872C12C20B00593047 /* HBCommonKeys.m in Sources */,
91C871AB2C1314770093790D /* GKDYVideoStatusBar.m in Sources */,
916353052C12B6D400593047 /* UIImage+Category.m in Sources */,
916353962C12C20B00593047 /* HBRefreshNormalHeader.m in Sources */,
916353392C12B6D400593047 /* SVRadialGradientLayer.m in Sources */,
@ -1256,9 +1498,13 @@
916353312C12B6D400593047 /* DGActivityIndicatorTripleRingsAnimation.m in Sources */,
916352FE2C12B6D400593047 /* NSString+Extension.m in Sources */,
916352FD2C12B6D400593047 /* NSObject+Tool.m in Sources */,
91C8719C2C1314770093790D /* GKDYPanGestureRecognizer.m in Sources */,
9163530F2C12B6D400593047 /* GTMBase64.m in Sources */,
91C871962C1314770093790D /* GKRotationManager_iOS_16_Later.m in Sources */,
916353062C12B6D400593047 /* UIImageView+Extension.m in Sources */,
91C871A02C1314770093790D /* GKDYVideoControlView.m in Sources */,
9163530C2C12B6D400593047 /* UIView+Frame.m in Sources */,
91C871932C1314770093790D /* GKLandscapeViewController.m in Sources */,
916353382C12B6D400593047 /* SVProgressHUD.m in Sources */,
9163534E2C12C15300593047 /* HBNetWorkingUtility+Services.m in Sources */,
916353142C12B6D400593047 /* DGActivityIndicatorBallClipRotateMultipleAnimation.m in Sources */,

View File

@ -1,5 +1,16 @@
<?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/>
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -6,11 +6,44 @@
//
#import "HBViewController.h"
#import "GKDYVideoModel.h"
#import <JXCategoryView/JXCategoryView.h>
#import "GKDYVideoScrollView.h"
NS_ASSUME_NONNULL_BEGIN
@interface HBHomeViewController : HBViewController
@class HBHomeViewController;
@protocol HBHomeViewControllerDelegate <NSObject>
@optional;
- (void)playerVCDidClickShoot:(HBHomeViewController *)playerVC;
//- (void)playerVC:(HBHomeViewController *)playerVC controlView:(GKDYVideoControlView *)controlView isCritical:(BOOL)isCritical;
- (void)playerVC:(HBHomeViewController *)playerVC didDragDistance:(CGFloat)distance isEnd:(BOOL)isEnd;
- (void)playerVC:(HBHomeViewController *)playerVC cellZoomBegan:(GKDYVideoModel *)model;
- (void)playerVC:(HBHomeViewController *)playerVC cellZoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen;
- (void)playerVC:(HBHomeViewController *)playerVC commentShowOrHide:(BOOL)show;
@end
@interface HBHomeViewController : HBViewController
@property (nonatomic, weak) id<HBHomeViewControllerDelegate> delegate;
@property (nonatomic, copy) NSString *tab;
@property (nonatomic, strong) GKDYVideoModel * model;
- (void)refreshData:(nullable void(^)(void))completion;
-(instancetype)initWithVideoId:(NSInteger)sid;
@end
NS_ASSUME_NONNULL_END

View File

@ -7,25 +7,247 @@
#import "HBHomeViewController.h"
@interface HBHomeViewController ()
//#import "QJShereModalView.h"
//#import "QJVideoEpisodesModalView.h"
#import "GKBallLoadingView.h"
#import "GKLikeView.h"
#import "GKDYVideoScrollView.h"
#import "GKDYVideoCell.h"
#import "GKDYPlayerManager.h"
#import "GKDYVideoPortraitCell.h"
#import "GKDYVideoLandscapeCell.h"
@interface HBHomeViewController ()<GKDYPlayerManagerDelegate> //,QJVideoEpisodesModalViewDelegate>
@property (nonatomic, strong) GKDYPlayerManager * manager;
@property (assign, nonatomic) BOOL isDetails;
@property (assign, nonatomic) NSInteger sid;
//@property (nonatomic, strong) QJVideoEpisodesModalView * episodesModalView;
@end
@implementation HBHomeViewController
- (instancetype)initWithVideoId:(NSInteger)sid {
self = [super init];
if (self) {
self.isDetails = YES;
self.sid = sid;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.hbd_barAlpha = 0.0;
self.edgesForExtendedLayout = UIRectEdgeNone;
[self initUI];
[self setupRefresh];
[self requestData];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.manager.player.viewControllerDisappear = YES;
}
*/
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.manager.player.viewControllerDisappear = NO;
}
- (void)dealloc {
NSLog(@"playerVC dealloc");
}
- (void)initUI {
[self.view addSubview:self.manager.scrollView];
[self.manager.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
}
- (void)setupRefresh {
if (self.isDetails) return; //
@weakify(self);
self.manager.scrollView.mj_footer = [HBRefreshAutoNormalFooter footerWithRefreshingBlock:^{
@strongify(self);
[self requestMore];
}];
}
- (void)requestData {
GKBallLoadingView *loadingView = [GKBallLoadingView loadingViewInView:self.view];
[loadingView startLoading];
self.manager.page = 1;
@weakify(loadingView);
[self requestData:^{
@strongify(loadingView);
[loadingView stopLoading];
[loadingView removeFromSuperview];
}];
}
- (void)requestMore {
self.manager.page++;
[self requestData:nil];
}
- (void)refreshData:(void (^)(void))completion {
self.manager.page = 1;
[self requestData:completion];
}
- (void)requestData:(nullable void (^)(void))completion {
HBWeakSelf
if (self.isDetails) {
[HBNetWorkingUtility videos_fetchVideoDetailsWithSid:self.sid
complateBlock:^(BOOL success, id _Nonnull data, NSString * _Nonnull message) {
if (completion) completion();
if (success) {
GKDYVideoModel * model = [GKDYVideoModel mj_objectWithKeyValues:data[@"shortVideoInfo"]];
NSArray * videoInfoModels = [GKDUVideoInfoModel mj_objectArrayWithKeyValuesArray:data[@"episode_list"]];
GKDUVideoInfoModel * formModel = [GKDUVideoInfoModel mj_objectWithKeyValues:data[@"video_info"]];
for (GKDUVideoInfoModel * videoInfoModel in videoInfoModels) {
GKDYVideoModel * tempModel = [model copy];
tempModel.videoInfo = videoInfoModel;
[weakSelf.manager.dataSources addObject:tempModel];
}
// weakSelf.episodesModalView.models = weakSelf.manager.dataSources;
// weakSelf.episodesModalView.indexModel = formModel;
[weakSelf.manager.scrollView reloadData];
[weakSelf.manager.scrollView scrollToPageWithIndex:(formModel.episode -1)];
}
}];
} else {
[HBNetWorkingUtility discover_fetchRecommandsWithPage:self.manager.page
size:20
complateBlock:^(BOOL success, id _Nonnull data, NSString * _Nonnull message) {
if (completion) completion();
if (success) {
NSArray * models = [GKDYVideoModel mj_objectArrayWithKeyValuesArray:data[@"list"]];
if (weakSelf.manager.page == 1) {
[weakSelf.manager.dataSources removeAllObjects];
}
[weakSelf.manager.dataSources addObjectsFromArray:models];
[weakSelf.manager.scrollView reloadData];
}
[weakSelf.manager.scrollView.mj_footer endRefreshingWithNoMoreData];
}];
}
}
- (GKDYVideoModel *)model {
return self.manager.currentCell.model;
}
#pragma mark - GKDYPlayerManagerDelegate
- (void)scrollViewShouldLoadMore {
[self requestMore];
}
- (void)scrollViewDidPanDistance:(CGFloat)distance isEnd:(BOOL)isEnd {
if ([self.delegate respondsToSelector:@selector(playerVC:didDragDistance:isEnd:)]) {
[self.delegate playerVC:self didDragDistance:distance isEnd:isEnd];
}
}
- (void)cellZoomBegan:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(playerVC:cellZoomBegan:)]) {
[self.delegate playerVC:self cellZoomBegan:model];
}
}
- (void)cellZoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen {
if ([self.delegate respondsToSelector:@selector(playerVC:cellZoomEnded:isFullscreen:)]) {
[self.delegate playerVC:self cellZoomEnded:model isFullscreen:isFullscreen];
}
}
- (void)celldidClickShare:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell {
// [[QJShereModalView new] presentInView:nil];
}
- (void)celldidClickFavorite:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell {
if (self.isDetails) return;
if (model.is_collect) {
[HBNetWorkingUtility customer_favoriteWithVideoId:model.cid complateBlock:nil];
} else {
[HBNetWorkingUtility customer_unFavoriteWithVideoId:model.cid complateBlock:nil];
}
}
- (void)celldidClickEpiscode:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell {
if (!self.isDetails) {
HBHomeViewController * controller = [[HBHomeViewController alloc]initWithVideoId:model.cid];
[self.navigationController pushViewController:controller animated:YES];
} else {
// self.episodesModalView.indexModel = self.manager.currentCell.model.videoInfo;
// [self.episodesModalView presentInView:nil];
}
}
-(void)videoEpisodesModalViewDidSelectItemWithModel:(GKDUVideoInfoModel *)model {
if (self.isDetails) {
NSInteger row = 0;
for (int index = 0; index < self.manager.dataSources.count; index ++ ) {
GKDYVideoModel * tempModel = self.manager.dataSources[index];
if (model.vid == tempModel.videoInfo.vid) {
row = index;
break;;
}
}
[self.manager.scrollView scrollToPageWithIndex:row];
}
}
- (void)cellSwitchWithModel:(GKDYVideoModel *)model {
if (!self.isDetails) return;
[HBNetWorkingUtility videos_uploadPlayHistoryWithSid:model.cid
vId:model.videoInfo.vid
complateBlock:^(BOOL success, id _Nonnull data, NSString * _Nonnull message) {
}];
}
#pragma mark -
- (GKDYPlayerManager *)manager {
if (!_manager) {
_manager = [[GKDYPlayerManager alloc] init];
_manager.delegate = self;
}
return _manager;
}
//- (QJVideoEpisodesModalView *)episodesModalView{
// if (!_episodesModalView) {
// _episodesModalView = [QJVideoEpisodesModalView new];
// _episodesModalView.delegate = self;
// }
// return _episodesModalView;
//}
@end

View File

@ -0,0 +1,29 @@
//
// UIButton+GKEnlarge.h
// Example
//
// Created by QuintGao on 2023/3/15.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIButton (GKEnlarge)
/*
UIButton响应区域
使
[enlargeButton setEnlargeEdge:20.0];
[enlargeButton setEnlargeEdgeWithTop:20 right:20 bottom:20 left:10];
*/
- (void)setEnlargeEdge:(CGFloat)size;
- (void)setEnlargeEdgeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,64 @@
//
// UIButton+GKEnlarge.m
// Example
//
// Created by QuintGao on 2023/3/15.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "UIButton+GKEnlarge.h"
#import <objc/runtime.h>
@implementation UIButton (GKEnlarge)
static char topNameKey;
static char rightNameKey;
static char bottomNameKey;
static char leftNameKey;
- (void)setEnlargeEdge:(CGFloat)size
{
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:size], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void)setEnlargeEdgeWithTop:(CGFloat)top left:(CGFloat)left bottom:(CGFloat)bottom right:(CGFloat)right
{
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGRect)enlargedRect
{
NSNumber* topEdge = objc_getAssociatedObject(self, &topNameKey);
NSNumber* rightEdge = objc_getAssociatedObject(self, &rightNameKey);
NSNumber* bottomEdge = objc_getAssociatedObject(self, &bottomNameKey);
NSNumber* leftEdge = objc_getAssociatedObject(self, &leftNameKey);
if (topEdge && rightEdge && bottomEdge && leftEdge)
{
return CGRectMake(self.bounds.origin.x - leftEdge.floatValue,
self.bounds.origin.y - topEdge.floatValue,
self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue,
self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue);
}
else
{
return self.bounds;
}
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGRect rect = [self enlargedRect];
if (CGRectEqualToRect(rect, self.bounds))
{
return [super pointInside:point withEvent:event];
}
return CGRectContainsPoint(rect, point) ? YES : NO;
}
@end

View File

@ -0,0 +1,21 @@
//
// GKDoubleLikeView.h
// GKDYVideo
//
// Created by gaokun on 2019/6/19.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDoubleLikeView : NSObject
- (void)createAnimationWithTouch:(UITouch *)touch;
- (void)createAnimationWithPoint:(CGPoint)point view:(UIView *)view completion:(nullable void(^)(void))completion;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,73 @@
//
// GKDoubleLikeView.m
// GKDYVideo
//
// Created by gaokun on 2019/6/19.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import "GKDoubleLikeView.h"
@interface GKDoubleLikeView()
@property (nonatomic, copy) void(^completion)(void);
@end
@implementation GKDoubleLikeView
- (void)createAnimationWithTouch:(UITouch *)touch {
if (touch.tapCount <= 1.0f) return;
[self createAnimationWithPoint:[touch locationInView:touch.view] view:touch.view completion:nil];
}
- (void)createAnimationWithPoint:(CGPoint)point view:(UIView *)view completion:(nullable void (^)(void))completion {
self.completion = completion;
UIImage *image = [UIImage imageNamed:@"player_favorite_selected"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
imgView.image = image;
imgView.contentMode = UIViewContentModeScaleAspectFill;
imgView.center = point;
//
int leftOrRight = arc4random() % 2;
leftOrRight = leftOrRight ? leftOrRight : -1;
imgView.transform = CGAffineTransformRotate(imgView.transform, M_PI / 9.0f * leftOrRight);
[view addSubview:imgView];
//
__block UIImageView *blockImgV = imgView;
__block UIImage *blockImage = image;
[UIView animateWithDuration:0.1 animations:^{
blockImgV.transform = CGAffineTransformScale(blockImgV.transform, 1.2f, 1.2f);
} completion:^(BOOL finished) {
blockImgV.transform = CGAffineTransformScale(blockImgV.transform, 0.8f, 0.8f);
//
[self performSelector:@selector(animationToTop:) withObject:@[blockImgV, blockImage] afterDelay:0.3f];
}];
}
- (void)animationToTop:(NSArray *)imgObjects {
if (imgObjects && imgObjects.count > 0) {
__block UIImageView *imgView = (UIImageView *)imgObjects.firstObject;
__block UIImage *image = (UIImage *)imgObjects.lastObject;
[UIView animateWithDuration:1.0f animations:^{
CGRect imgViewFrame = imgView.frame;
imgViewFrame.origin.y -= 100.0f;
imgView.frame = imgViewFrame;
imgView.transform = CGAffineTransformScale(imgView.transform, 1.8f, 1.8f);
imgView.alpha = 0.0f;
} completion:^(BOOL finished) {
[imgView removeFromSuperview];
imgView = nil;
image = nil;
!self.completion ?: self.completion();
}];
}
}
@end

View File

@ -0,0 +1,27 @@
//
// GKLikeView.h
// GKDYVideo
//
// Created by gaokun on 2019/5/27.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKLikeView : UIView
@property (nonatomic, assign) BOOL isLike;
@property (nonatomic, copy) void(^likeBlock)(void);
- (void)startAnimationWithIsLike:(BOOL)isLike;
- (void)setupLikeState:(BOOL)isLike;
- (void)setupLikeCount:(NSString *)count;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,189 @@
//
// GKLikeView.m
// GKDYVideo
//
// Created by gaokun on 2019/5/27.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import "GKLikeView.h"
@interface GKLikeView()
@property (nonatomic, strong) UIImageView *likeBeforeImgView;
@property (nonatomic, strong) UIImageView *likeAfterImgView;
@property (nonatomic, strong) UILabel *countLabel;
@end
@implementation GKLikeView
- (instancetype)init {
if (self = [super init]) {
[self addSubview:self.likeBeforeImgView];
[self addSubview:self.likeAfterImgView];
[self addSubview:self.countLabel];
// CGFloat imgWH = HBAdapt(40.0f);
// self.likeBeforeImgView.frame = CGRectMake(0, 0, imgWH, imgWH);
// self.likeAfterImgView.frame = CGRectMake(0, 0, imgWH, imgWH);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[self addGestureRecognizer:tapGesture];
[self.likeBeforeImgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self);
}];
[self.likeAfterImgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.likeBeforeImgView);
}];
[self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self);
make.top.equalTo(self.likeBeforeImgView.mas_bottom).offset(4.0);
}];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
//
// CGPoint imgCenter = self.likeBeforeImgView.center;
// imgCenter.x = self.frame.size.width / 2;
// self.likeBeforeImgView.center = imgCenter;
// self.likeAfterImgView.center = imgCenter;
//
// [self.countLabel sizeToFit];
//
// CGFloat countX = (self.frame.size.width - self.countLabel.frame.size.width) / 2;
// CGFloat countY = self.frame.size.height - self.countLabel.frame.size.height;
// self.countLabel.frame = CGRectMake(countX, countY, self.countLabel.frame.size.width, self.countLabel.frame.size.height);
}
- (void)setupLikeState:(BOOL)isLike {
self.isLike = isLike;
if (isLike) {
self.likeAfterImgView.hidden = NO;
}else {
self.likeAfterImgView.hidden = YES;
}
}
- (void)setupLikeCount:(NSString *)count {
self.countLabel.text = count;
[self layoutSubviews];
}
- (void)startAnimationWithIsLike:(BOOL)isLike {
if (self.isLike == isLike) return;
self.isLike = isLike;
if (isLike) {
CGFloat length = 30;
CGFloat duration = 0.5f;
for (NSInteger i = 0; i < 6; i++) {
CAShapeLayer *layer = [CAShapeLayer layer];
layer.position = self.likeBeforeImgView.center;
layer.fillColor = [UIColor colorWithRed:232.0/255.0 green:50.0/255.0 blue:85.0/255.0 alpha:1.0].CGColor;
UIBezierPath *startPath = [UIBezierPath bezierPath];
[startPath moveToPoint:CGPointMake(-2, -length)];
[startPath addLineToPoint:CGPointMake(2, -length)];
[startPath addLineToPoint:CGPointMake(0, 0)];
layer.path = startPath.CGPath;
layer.transform = CATransform3DMakeRotation(M_PI / 3.0f * i, 0, 0, 1.0);
[self.layer addSublayer:layer];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.removedOnCompletion = NO;
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
group.fillMode = kCAFillModeForwards;
group.duration = duration;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnim.fromValue = @(0.0f);
scaleAnim.toValue = @(1.0f);
scaleAnim.duration = duration * 0.2f;
UIBezierPath *endPath = [UIBezierPath bezierPath];
[endPath moveToPoint:CGPointMake(-2, -length)];
[endPath addLineToPoint:CGPointMake(2, -length)];
[endPath addLineToPoint:CGPointMake(0, -length)];
CABasicAnimation *pathAnim = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnim.fromValue = (__bridge id)layer.path;
pathAnim.toValue = (__bridge id)endPath.CGPath;
pathAnim.beginTime = duration * 0.2f;
pathAnim.duration = duration * 0.8f;
[group setAnimations:@[scaleAnim, pathAnim]];
[layer addAnimation:group forKey:nil];
}
self.likeAfterImgView.hidden = NO;
self.likeAfterImgView.alpha = 0.0f;
self.likeAfterImgView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
[UIView animateWithDuration:0.15 animations:^{
self.likeAfterImgView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
self.likeAfterImgView.alpha = 1.0f;
self.likeBeforeImgView.alpha = 0.0f;
} completion:^(BOOL finished) {
self.likeAfterImgView.transform = CGAffineTransformIdentity;
self.likeBeforeImgView.alpha = 1.0f;
}];
}else {
self.likeAfterImgView.alpha = 1.0f;
self.likeAfterImgView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
[UIView animateWithDuration:0.15 animations:^{
self.likeAfterImgView.transform = CGAffineTransformMakeScale(0.3f, 0.3f);
} completion:^(BOOL finished) {
self.likeAfterImgView.transform = CGAffineTransformIdentity;
self.likeAfterImgView.hidden = YES;
}];
}
}
#pragma mark - UITapGestureRecognizer
- (void)tapAction:(UITapGestureRecognizer *)tap {
[self startAnimationWithIsLike:!self.isLike];
!self.likeBlock ?: self.likeBlock();
}
#pragma mark -
- (UIImageView *)likeBeforeImgView {
if (!_likeBeforeImgView) {
_likeBeforeImgView = [UIImageView new];
_likeBeforeImgView.image = [UIImage imageNamed:@"player_favorite_normal"];
}
return _likeBeforeImgView;
}
- (UIImageView *)likeAfterImgView {
if (!_likeAfterImgView) {
_likeAfterImgView = [UIImageView new];
_likeAfterImgView.image = [UIImage imageNamed:@"player_favorite_selected"];
}
return _likeAfterImgView;
}
- (UILabel *)countLabel {
if (!_countLabel) {
_countLabel = [UILabel new];
_countLabel.textColor = [UIColor whiteColor];
_countLabel.font = [UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular];
_countLabel.textAlignment = NSTextAlignmentCenter;
}
return _countLabel;
}
@end

View File

@ -0,0 +1,24 @@
//
// GKBallLoadingView.h
// GKDYVideo
//
// Created by gaokun on 2019/5/7.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKBallLoadingView : UIView
+ (instancetype)loadingViewInView:(UIView *)view;
- (void)startLoadingWithProgress:(CGFloat)progress;
- (void)startLoading;
- (void)stopLoading;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,261 @@
//
// GKBallLoadingView.m
// GKDYVideo
//
// Created by gaokun on 2019/5/7.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import "GKBallLoadingView.h"
#define kBallWidth 12.0f
#define kBallSpeed 0.7f
#define kBallZoomScale 0.25
#define kBallPauseTime 0.18
#define GKColorRGBA(r, g, b, a) [UIColor colorWithRed:(r / 255.0) green:(g / 255.0) blue:(b / 255.0) alpha:a]
#define GKColorRGB(r, g, b) GKColorRGBA(r, g, b, 1.0)
// 绿
typedef NS_ENUM(NSUInteger, GKBallMoveDirection) {
GKBallMoveDirectionPositive = 1, //
GKBallMoveDirectionNegative = -1 //
};
@interface GKBallLoadingView()
//
@property (nonatomic, strong) UIView *containerView;
// 绿
@property (nonatomic, strong) UIView *greenBall;
//
@property (nonatomic, strong) UIView *redBall;
//
@property (nonatomic, strong) UIView *blackBall;
@property (nonatomic, assign) GKBallMoveDirection moveDirection;
//
@property (nonatomic, strong) CADisplayLink *displayLink;
@end
@implementation GKBallLoadingView
+ (instancetype)loadingViewInView:(UIView *)view {
GKBallLoadingView *loadingView = [[GKBallLoadingView alloc] initWithFrame:view.bounds];
[view addSubview:loadingView];
return loadingView;
}
- (void)startLoadingWithProgress:(CGFloat)progress {
[self updateBallPositionWithProgress:progress];
}
- (void)startLoading {
[self startAnimation];
}
- (void)stopLoading {
[self stopAnimation];
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
- (void)setupUI {
self.containerView = [[UIView alloc] init];
self.containerView.center = self.center;
self.containerView.bounds = CGRectMake(0, 0, 2.1f * kBallWidth, 2.0f * kBallWidth);
[self addSubview:self.containerView];
// 绿
self.greenBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
self.greenBall.center = CGPointMake(kBallWidth * 0.5f, self.containerView.bounds.size.height * 0.5f);
self.greenBall.layer.cornerRadius = kBallWidth * 0.5f;
self.greenBall.layer.masksToBounds = YES;
self.greenBall.backgroundColor = GKColorRGB(35, 246, 235);
[self.containerView addSubview:self.greenBall];
//
self.redBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
self.redBall.center = CGPointMake(self.containerView.bounds.size.width - kBallWidth * 0.5f, self.containerView.bounds.size.height * 0.5f);
self.redBall.layer.cornerRadius = kBallWidth * 0.5f;
self.redBall.layer.masksToBounds = YES;
self.redBall.backgroundColor = GKColorRGB(255, 46, 86);
[self.containerView addSubview:self.redBall];
//
// 绿绿
self.blackBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
self.blackBall.backgroundColor = GKColorRGB(12, 11, 17);
self.blackBall.layer.cornerRadius = kBallWidth * 0.5f;
self.blackBall.layer.masksToBounds = YES;
[self.greenBall addSubview:self.blackBall];
//
self.moveDirection = GKBallMoveDirectionPositive;
[self.containerView bringSubviewToFront:self.greenBall];
[self updateBallPositionWithProgress:0];
}
- (void)startAnimation {
[self pauseAnimation];
//
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateBallAnimations)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)pauseAnimation {
if (self.displayLink) {
[self.displayLink invalidate];
self.displayLink = nil;
}
}
- (void)stopAnimation {
if (self.displayLink) {
[self.displayLink invalidate];
self.displayLink = nil;
}
//
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startAnimation) object:nil];
//
[self.greenBall addSubview:self.blackBall];
[self.containerView bringSubviewToFront:self.greenBall];
self.moveDirection = GKBallMoveDirectionPositive;
[self updateBallPositionWithProgress:0];
}
- (void)resetAnimation {
[self pauseAnimation];
//
[self performSelector:@selector(startAnimation) withObject:nil afterDelay:kBallPauseTime];
}
- (void)updateBallPositionWithProgress:(CGFloat)progress {
CGPoint center = self.greenBall.center;
center.x = kBallWidth * 0.5 + 1.1 * kBallWidth * progress;
self.greenBall.center = center;
center = self.redBall.center;
center.x = kBallWidth * 1.6 - 1.1 * kBallWidth * progress;
self.redBall.center = center;
// 绿
if (progress != 0 && progress != 1) {
self.greenBall.transform = [self ballLargerTransformOfCenterX:center.x];
self.redBall.transform = [self ballSmallerTransformOfCenterX:center.x];
}else {
self.greenBall.transform = CGAffineTransformIdentity;
self.redBall.transform = CGAffineTransformIdentity;
}
//
CGRect blackBallFrame = [self.redBall convertRect:self.redBall.bounds toCoordinateSpace:self.greenBall];
self.blackBall.frame = blackBallFrame;
self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width * 0.5f;
}
- (void)updateBallAnimations {
if (self.moveDirection == GKBallMoveDirectionPositive) { //
CGPoint center = self.greenBall.center;
center.x += kBallSpeed;
self.greenBall.center = center;
center = self.redBall.center;
center.x -= kBallSpeed;
self.redBall.center = center;
// 绿
self.greenBall.transform = [self ballLargerTransformOfCenterX:center.x];
self.redBall.transform = [self ballSmallerTransformOfCenterX:center.x];
//
CGRect blackBallFrame = [self.redBall convertRect:self.redBall.bounds toCoordinateSpace:self.greenBall];
self.blackBall.frame = blackBallFrame;
self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width * 0.5f;
//
if (CGRectGetMaxX(self.greenBall.frame) >= self.containerView.bounds.size.width || CGRectGetMinX(self.redBall.frame) <= 0) {
//
self.moveDirection = GKBallMoveDirectionNegative;
// 绿
[self.containerView bringSubviewToFront:self.redBall];
//
[self.redBall addSubview:self.blackBall];
//
[self resetAnimation];
}
}else if (self.moveDirection == GKBallMoveDirectionNegative) { //
// 绿
CGPoint center = self.greenBall.center;
center.x -= kBallSpeed;
self.greenBall.center = center;
//
center = self.redBall.center;
center.x += kBallSpeed;
self.redBall.center = center;
// 绿
self.redBall.transform = [self ballLargerTransformOfCenterX:center.x];
self.greenBall.transform = [self ballSmallerTransformOfCenterX:center.x];
//
CGRect blackBallFrame = [self.greenBall convertRect:self.greenBall.bounds toCoordinateSpace:self.redBall];
self.blackBall.frame = blackBallFrame;
self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width * 0.5f;
//
if (CGRectGetMinX(self.greenBall.frame) <= 0 || CGRectGetMaxX(self.redBall.frame) >= self.containerView.bounds.size.width) {
//
self.moveDirection = GKBallMoveDirectionPositive;
// 绿
[self.containerView bringSubviewToFront:self.greenBall];
// 绿
[self.greenBall addSubview:self.blackBall];
//
[self resetAnimation];
}
}
}
//
- (CGAffineTransform)ballLargerTransformOfCenterX:(CGFloat)centerX {
CGFloat cosValue = [self cosValueOfCenterX:centerX];
return CGAffineTransformMakeScale(1 + cosValue * kBallZoomScale, 1 + cosValue * kBallZoomScale);
}
//
- (CGAffineTransform)ballSmallerTransformOfCenterX:(CGFloat)centerX {
CGFloat cosValue = [self cosValueOfCenterX:centerX];
return CGAffineTransformMakeScale(1 - cosValue * kBallZoomScale, 1 - cosValue * kBallZoomScale);
}
// 0~1~0
- (CGFloat)cosValueOfCenterX:(CGFloat)centerX {
//
CGFloat apart = centerX - self.containerView.bounds.size.width * 0.5f;
// (Container)
CGFloat maxAppart = (self.containerView.bounds.size.width - kBallWidth) * 0.5f;
//
CGFloat angle = apart / maxAppart * M_PI_2;
// 线Y
return cos(angle);
}
@end

View File

@ -0,0 +1,25 @@
//
// GKLandscapeNavigationController.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol GKLandscapeNavigationControllerDelegate;
@interface GKLandscapeNavigationController : UINavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController delegate:(nullable id<GKLandscapeNavigationControllerDelegate>)delegate;
@end
@protocol GKLandscapeNavigationControllerDelegate <NSObject>
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,62 @@
//
// GKLandscapeNavigationController.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKLandscapeNavigationController.h"
@implementation GKLandscapeNavigationController {
__weak id<GKLandscapeNavigationControllerDelegate> _delegate;
}
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController delegate:(id<GKLandscapeNavigationControllerDelegate>)delegate {
if (self = [super initWithRootViewController:rootViewController]) {
_delegate = delegate;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[super setNavigationBarHidden:YES animated:NO];
}
- (void)setNavigationBarHidden:(BOOL)navigationBarHidden {}
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {}
- (BOOL)shouldAutorotate {
return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.topViewController.supportedInterfaceOrientations;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.topViewController.preferredInterfaceOrientationForPresentation;
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
- (BOOL)prefersHomeIndicatorAutoHidden {
return YES;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.viewControllers.count < 1) {
[super pushViewController:viewController animated:animated];
}else if ([_delegate respondsToSelector:@selector(pushViewController:animated:)]) {
[_delegate pushViewController:viewController animated:animated];
}
}
@end

View File

@ -0,0 +1,37 @@
//
// GKLandscapeViewController.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol GKLandscapeViewControllerDelegate;
@interface GKLandscapeViewController : UIViewController
@property (nonatomic, weak, nullable) id<GKLandscapeViewControllerDelegate> delegate;
@property (nonatomic, assign) BOOL disableAnimations;
@property (nonatomic, assign) BOOL statusBarHidden;
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;
@property (nonatomic, assign) UIStatusBarAnimation statusBarAnimation;
@end
@protocol GKLandscapeViewControllerDelegate <NSObject>
@optional
- (BOOL)viewControllerShouldAutorotate:(GKLandscapeViewController *)viewController;
- (void)viewController:(GKLandscapeViewController *)viewController viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,47 @@
//
// GKLandscapeViewController.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKLandscapeViewController.h"
@implementation GKLandscapeViewController
- (instancetype)init {
if (self = [super init]) {
_statusBarStyle = UIStatusBarStyleLightContent;
_statusBarAnimation = UIStatusBarAnimationSlide;
}
return self;
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
if ([self.delegate respondsToSelector:@selector(viewController:viewWillTransitionToSize:withTransitionCoordinator:)]) {
[self.delegate viewController:self viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (BOOL)prefersHomeIndicatorAutoHidden {
return YES;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return self.statusBarHidden;
}
- (BOOL)prefersStatusBarHidden {
return self.statusBarStyle;
}
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return self.statusBarAnimation;
}
@end

View File

@ -0,0 +1,21 @@
//
// GKLandscapeWindow.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class GKRotationManager;
@interface GKLandscapeWindow : UIWindow
@property (nonatomic, weak, nullable) GKRotationManager *rotationManager;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,76 @@
//
// GKLandscapeWindow.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKLandscapeWindow.h"
@implementation GKLandscapeWindow {
CGRect _old_bounds;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.frame = UIScreen.mainScreen.bounds;
self.windowLevel = UIWindowLevelStatusBar - 1;
if (@available(iOS 13.0, *)) {
if (self.windowScene == nil) {
self.windowScene = UIApplication.sharedApplication.keyWindow.windowScene;
}
if (self.windowScene == nil) {
self.windowScene = (UIWindowScene *) UIApplication.sharedApplication.connectedScenes.anyObject;
}
}
self.hidden = YES;
}
return self;
}
#ifdef DEBUG
- (void)dealloc {
NSLog(@"%d \t %s", (int)__LINE__, __func__);
}
#endif
- (void)setRootViewController:(UIViewController *)rootViewController {
[super setRootViewController:rootViewController];
rootViewController.view.frame = self.bounds;
rootViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
- (void)setBackgroundColor:(UIColor *)backgroundColor {}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return YES;
}
- (void)layoutSubviews {
[super layoutSubviews];
//
if (!CGRectEqualToRect(_old_bounds, self.bounds)) {
_old_bounds = self.bounds;
UIView *superview = self;
if (@available(iOS 13.0, *)) {
superview = self.subviews.firstObject;
}
[UIView performWithoutAnimation:^{
for (UIView *view in superview.subviews) {
if (view != self.rootViewController.view && [view isMemberOfClass:UIView.class]) {
view.backgroundColor = UIColor.clearColor;
for (UIView *subview in view.subviews) {
subview.backgroundColor = UIColor.clearColor;
}
}
}
}];
}
self.rootViewController.view.frame = self.bounds;
}
@end

View File

@ -0,0 +1,118 @@
//
// GKRotationManager.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKLandscapeWindow.h"
#import "GKLandscapeViewController.h"
typedef NS_OPTIONS(NSUInteger, GKInterfaceOrientationMask) {
GKInterfaceOrientationMaskUnknow = 0,
GKInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
GKInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
GKInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
GKInterfaceOrientationMaskPortraitUpsideDown = ( 1 << UIInterfaceOrientationPortraitUpsideDown),
GKInterfaceOrientationMaskLandscape = (GKInterfaceOrientationMaskLandscapeLeft | GKInterfaceOrientationMaskLandscapeRight),
GKInterfaceOrientationMaskAll = (GKInterfaceOrientationMaskPortrait | GKInterfaceOrientationMaskLandscapeLeft | GKInterfaceOrientationMaskLandscapeRight | GKInterfaceOrientationMaskPortraitUpsideDown),
GKInterfaceOrientationMaskAllButUpsideDown = (GKInterfaceOrientationMaskPortrait | GKInterfaceOrientationMaskLandscapeLeft | GKInterfaceOrientationMaskLandscapeRight)
};
NS_ASSUME_NONNULL_BEGIN
@interface GKRotationManager : NSObject
+ (GKInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window;
+ (instancetype)rotationManager;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
/// 横屏时的window
@property (nonatomic, strong, nullable) GKLandscapeWindow *window;
/// 需要旋转的内容视图
@property (nonatomic, weak) UIView *contentView;
/// 旋转内容原来的父视图
@property (nonatomic, weak) UIView *containerView;
/// 是否允许自动旋转
@property (nonatomic, assign) BOOL allowOrientationRotation;
/// 自动旋转支持的方向
@property (nonatomic, assign) GKInterfaceOrientationMask supportInterfaceOrientation;
/// 当前的方向
@property (nonatomic, assign) UIInterfaceOrientation currentOrientation;
/// 是否全屏
@property (nonatomic, assign, readonly) BOOL isFullscreen;
/// 即将旋转回调
@property (nonatomic, copy, nullable) void(^orientationWillChange)(BOOL isFullscreen);
/// 结束旋转回调
@property (nonatomic, copy, nullable) void(^orientationDidChanged)(BOOL isFullscreen);
/// 旋转
- (void)rotate;
/// 旋转到指定方向
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
/// 旋转到指定方向
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated completion:(void(^ __nullable)(void))completion;
@end
@interface GKRotationManager (Internal)
/// 当前设备方向
@property (nonatomic, assign, readonly) UIInterfaceOrientation currentDeviceOrientation;
/// 旋转时是否禁止动画
@property (nonatomic, assign) BOOL disableAnimations;
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window;
- (UIInterfaceOrientation)getCurrentOrientation;
- (__kindof GKLandscapeViewController *)landscapeViewController;
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation completion:(void (^ __nullable)(void))completion;
- (void)handleDeviceOrientationChange;
- (BOOL)isSupportInterfaceOrientation:(UIInterfaceOrientation)orientation;
- (void)willChangeOrientation:(UIInterfaceOrientation)orientation;
- (void)didChangeOrientation:(UIInterfaceOrientation)orientation;
@end
NS_ASSUME_NONNULL_END
#pragma mark - fix safe area
NS_ASSUME_NONNULL_BEGIN
typedef NS_OPTIONS(NSUInteger, GKSafeAreaInsetsMask) {
GKSafeAreaInsetsMaskNone = 0,
GKSafeAreaInsetsMaskTop = 1 << 0,
GKSafeAreaInsetsMaskLeft = 1 << 1,
GKSafeAreaInsetsMaskBottom = 1 << 2,
GKSafeAreaInsetsMaskRight = 1 << 3,
GKSafeAreaInsetsMaskHorizontal = GKSafeAreaInsetsMaskLeft | GKSafeAreaInsetsMaskRight,
GKSafeAreaInsetsMaskVertical = GKSafeAreaInsetsMaskTop | GKSafeAreaInsetsMaskBottom,
GKSafeAreaInsetsMaskAll = GKSafeAreaInsetsMaskHorizontal | GKSafeAreaInsetsMaskVertical
}API_DEPRECATED("deprecated!", ios(13.0, 16.0));
API_DEPRECATED("deprecated!", ios(13.0, 16.0)) @interface UIViewController (GKRotationSafeAreaFixing)
/// 禁止调整哪些方向的安全区域
@property (nonatomic) GKSafeAreaInsetsMask disabledAdjustSafeAreaInsetsMask;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,275 @@
//
// GKRotationManager.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKRotationManager.h"
#import "GKLandscapeWindow.h"
#import "GKLandscapeViewController.h"
#import "GKRotationManager_iOS_9_15.h"
#import "GKRotationManager_iOS_16_Later.h"
#import <objc/message.h>
@interface GKRotationManager()<GKLandscapeViewControllerDelegate>
@property (nonatomic, assign) BOOL isGeneratingDeviceOrientation;
@end
@implementation GKRotationManager
+ (GKInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if ([window isKindOfClass:GKLandscapeWindow.class]) {
GKRotationManager *manager = [(GKLandscapeWindow *)window rotationManager];
if (manager != nil) {
return (GKInterfaceOrientationMask)[manager supportedInterfaceOrientationsForWindow:window];
}
}
return GKInterfaceOrientationMaskUnknow;
}
+ (instancetype)rotationManager {
if (@available(iOS 16.0, *)) {
return [[GKRotationManager_iOS_16_Later alloc] _init];
}else {
return [[GKRotationManager_iOS_9_15 alloc] _init];
}
}
- (instancetype)_init {
if (self = [super init]) {
self.currentOrientation = UIInterfaceOrientationPortrait;
self.supportInterfaceOrientation = GKInterfaceOrientationMaskAll;
}
return self;
}
- (void)addDeviceOrientationObserver {
self.isGeneratingDeviceOrientation = UIDevice.currentDevice.isGeneratingDeviceOrientationNotifications;
if (!self.isGeneratingDeviceOrientation) {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeviceOrientationChange) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)removeDeviceOrientationObserver {
if (!self.isGeneratingDeviceOrientation) {
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)dealloc {
#ifdef DEBUG
NSLog(@"%d -- [%@ %s]", (int)__LINE__, NSStringFromClass(self.class), sel_getName(_cmd));
#endif
[_window setHidden:YES];
[self removeDeviceOrientationObserver];
}
- (void)setAllowOrientationRotation:(BOOL)allowOrientationRotation {
_allowOrientationRotation = allowOrientationRotation;
if (allowOrientationRotation) {
[self addDeviceOrientationObserver];
}else {
[self removeDeviceOrientationObserver];
}
}
- (UIInterfaceOrientation)currentDeviceOrientation {
return (UIInterfaceOrientation)UIDevice.currentDevice.orientation;
}
- (void)rotate {
UIInterfaceOrientation orientation = self.currentOrientation == UIInterfaceOrientationPortrait ? UIInterfaceOrientationLandscapeRight : UIInterfaceOrientationPortrait;
[self rotateToOrientation:orientation animated:YES];
}
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated {
[self rotateToOrientation:orientation animated:animated completion:nil];
}
- (void)rotateToOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated completion:(void (^)(void))completion {
self.currentOrientation = orientation;
if (UIInterfaceOrientationIsLandscape(orientation)) {
if (!self.window) {
self.window = [[GKLandscapeWindow alloc] init];
self.window.rootViewController = self.landscapeViewController;
self.window.rotationManager = self;
}
}
self.disableAnimations = !animated;
if (UIDevice.currentDevice.systemVersion.doubleValue < 16.0) {
[self interfaceOrientation:UIInterfaceOrientationUnknown completion:nil];
}
[self interfaceOrientation:orientation completion:completion];
}
@end
@implementation GKRotationManager (Internal)
@dynamic disableAnimations;
- (void)setDisableAnimations:(BOOL)disableAnimations {
objc_setAssociatedObject(self, @selector(disableAnimations), @(disableAnimations), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)disableAnimations {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)]
userInfo:nil];
}
- (UIInterfaceOrientation)getCurrentOrientation {
if (@available(iOS 16.0, *)) {
NSArray *array = UIApplication.sharedApplication.connectedScenes.allObjects;
UIWindowScene *scene = array.firstObject;
return scene.interfaceOrientation;
}else {
return self.currentDeviceOrientation;
}
}
- (GKLandscapeViewController *)landscapeViewController {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)]
userInfo:nil];
}
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation completion:(void (^)(void))completion {
// subclass implementation
}
- (void)handleDeviceOrientationChange {
if (!self.allowOrientationRotation) return;
if (!UIDeviceOrientationIsValidInterfaceOrientation([UIDevice currentDevice].orientation)) return;
UIInterfaceOrientation currentOrientation = self.currentDeviceOrientation;
if (currentOrientation == self.currentOrientation) return;
self.currentOrientation = currentOrientation;
if (currentOrientation == UIInterfaceOrientationPortraitUpsideDown) return;
switch (currentOrientation) {
case UIInterfaceOrientationPortrait: {
if ([self _isSupportedPortrait]) {
[self rotateToOrientation:UIInterfaceOrientationPortrait animated:YES];
}
}
break;
case UIInterfaceOrientationLandscapeLeft: {
if ([self _isSupportedLandscapeLeft]) {
[self rotateToOrientation:UIInterfaceOrientationLandscapeLeft animated:YES];
}
}
break;
case UIInterfaceOrientationLandscapeRight: {
if ([self _isSupportedLandscapeRight]) {
[self rotateToOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
}
}
break;
default: break;
}
}
- (BOOL)isSupportInterfaceOrientation:(UIInterfaceOrientation)orientation {
if (orientation == UIInterfaceOrientationPortrait) {
return [self _isSupportedPortrait];
}else if (orientation == UIInterfaceOrientationLandscapeLeft) {
return [self _isSupportedLandscapeLeft];
}else if (orientation == UIInterfaceOrientationLandscapeRight) {
return [self _isSupportedLandscapeRight];
}else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
return [self _isSupportedPortraitUpsideDown];
}
return NO;
}
- (void)willChangeOrientation:(UIInterfaceOrientation)orientation {
_isFullscreen = UIInterfaceOrientationIsLandscape(orientation);
!self.orientationWillChange ?: self.orientationWillChange(_isFullscreen);
}
- (void)didChangeOrientation:(UIInterfaceOrientation)orientation {
_isFullscreen = UIInterfaceOrientationIsLandscape(orientation);
!self.orientationDidChanged ?: self.orientationDidChanged(_isFullscreen);
}
- (BOOL)_isSupportedPortrait {
return self.supportInterfaceOrientation & GKInterfaceOrientationMaskPortrait;
}
- (BOOL)_isSupportedPortraitUpsideDown {
return self.supportInterfaceOrientation & GKInterfaceOrientationMaskPortraitUpsideDown;
}
- (BOOL)_isSupportedLandscapeLeft {
return self.supportInterfaceOrientation & GKInterfaceOrientationMaskLandscapeLeft;
}
- (BOOL)_isSupportedLandscapeRight {
return self.supportInterfaceOrientation & GKInterfaceOrientationMaskLandscapeRight;
}
@end
#pragma mark - fix safe area
API_DEPRECATED("deprecated!", ios(13.0, 16.0)) @implementation GKRotationManager (GKRotationSafeAreaFixing)
+ (void)initialize {
if (@available(iOS 16.0, *)) return;
if (@available(iOS 13.0, *)) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = UIViewController.class;
NSData *data = [NSData.alloc initWithBase64EncodedString:@"X3NldENvbnRlbnRPdmVybGF5SW5zZXRzOmFuZExlZnRNYXJnaW46cmlnaHRNYXJnaW46" options:kNilOptions];
NSString *method = [NSString.alloc initWithData:data encoding:NSUTF8StringEncoding];
SEL originalSelector = NSSelectorFromString(method);
SEL swizzledSelector = NSSelectorFromString([@"gk" stringByAppendingString:method]);
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
if ( originalMethod != NULL ) method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
}
@end
API_DEPRECATED("deprecated!", ios(13.0, 16.0)) @implementation UIViewController (GKRotationSafeAreaFixing)
- (void)gk_setContentOverlayInsets:(UIEdgeInsets)insets andLeftMargin:(CGFloat)leftMargin rightMargin:(CGFloat)rightMargin {
GKSafeAreaInsetsMask mask = self.disabledAdjustSafeAreaInsetsMask;
if (mask & GKSafeAreaInsetsMaskTop) insets.top = 0;
if (mask & GKSafeAreaInsetsMaskLeft) insets.left = 0;
if (mask & GKSafeAreaInsetsMaskBottom) insets.bottom = 0;
if (mask & GKSafeAreaInsetsMaskRight) insets.right = 0;
UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
UIWindow *otherWindow = self.view.window;
if ([keyWindow isKindOfClass:GKLandscapeWindow.class] && otherWindow != nil) {
GKRotationManager *manager = ((GKLandscapeWindow *)keyWindow).rotationManager;
UIWindow *superviewWindow = manager.containerView.window;
if (superviewWindow != otherWindow) {
[self gk_setContentOverlayInsets:insets andLeftMargin:leftMargin rightMargin:rightMargin];
}
}else {
[self gk_setContentOverlayInsets:insets andLeftMargin:leftMargin rightMargin:rightMargin];
}
}
- (void)setDisabledAdjustSafeAreaInsetsMask:(GKSafeAreaInsetsMask)disabledAdjustSafeAreaInsetsMask {
objc_setAssociatedObject(self, @selector(disabledAdjustSafeAreaInsetsMask), @(disabledAdjustSafeAreaInsetsMask), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (GKSafeAreaInsetsMask)disabledAdjustSafeAreaInsetsMask {
return [objc_getAssociatedObject(self, _cmd) integerValue];
}
@end

View File

@ -0,0 +1,17 @@
//
// GKRotationManager_iOS_16_Later.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKRotationManager.h"
API_AVAILABLE(ios(16.0)) NS_ASSUME_NONNULL_BEGIN
@interface GKRotationManager_iOS_16_Later : GKRotationManager
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,139 @@
//
// GKRotationManager_iOS_16_Later.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKRotationManager_iOS_16_Later.h"
#import "GKLandscapeViewController.h"
@interface GKRotationManager_iOS_16_Later()
@property (nonatomic, strong, readonly) GKLandscapeViewController *landscapeViewController;
@end
@implementation GKRotationManager_iOS_16_Later
@synthesize landscapeViewController = _landscapeViewController;
- (__kindof GKLandscapeViewController *)landscapeViewController {
if (!_landscapeViewController) {
_landscapeViewController = [[GKLandscapeViewController alloc] init];
}
return _landscapeViewController;
}
- (void)setNeedsUpdateOfSupportedInterfaceOrientations {
if (@available(iOS 16.0, *)) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000
[UIApplication.sharedApplication.keyWindow.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
[self.window.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
#else
[(id)UIApplication.sharedApplication.keyWindow.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
[(id)self.window.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
#endif
}
}
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation completion:(void (^)(void))completion {
[super interfaceOrientation:orientation completion:completion];
UIInterfaceOrientation fromOrientation = [self getCurrentOrientation];
UIInterfaceOrientation toOrientation = orientation;
[self willChangeOrientation:toOrientation];
self.currentOrientation = toOrientation;
UIWindow *sourceWindow = self.containerView.window;
CGRect sourceFrame = [self.containerView convertRect:self.containerView.bounds toView:sourceWindow];
CGRect screenBounds = UIScreen.mainScreen.bounds;
CGFloat maxSize = MAX(screenBounds.size.width, screenBounds.size.height);
CGFloat minSize = MIN(screenBounds.size.width, screenBounds.size.height);
self.contentView.autoresizingMask = UIViewAutoresizingNone;
if (fromOrientation == UIInterfaceOrientationPortrait || self.contentView.superview != self.landscapeViewController.view) {
self.contentView.frame = sourceFrame;
[sourceWindow addSubview:self.contentView];
[self.contentView layoutIfNeeded];
if (!self.window.isKeyWindow) {
self.window.hidden = NO;
[self.window makeKeyAndVisible];
}
}else if (toOrientation == UIInterfaceOrientationPortrait) {
[self.contentView removeFromSuperview];
self.contentView.bounds = CGRectMake(0, 0, maxSize, minSize);
self.contentView.center = CGPointMake(minSize * 0.5, maxSize * 0.5);
self.contentView.transform = [self getRotationTransform:fromOrientation];
[sourceWindow addSubview:self.contentView];
[self.contentView layoutIfNeeded];
[self.contentView snapshotViewAfterScreenUpdates:YES];
[UIView performWithoutAnimation:^{
[sourceWindow makeKeyAndVisible];
self.window.hidden = YES;
}];
}
[self setNeedsUpdateOfSupportedInterfaceOrientations];
CGRect rotationBounds = CGRectZero;
CGPoint rotationCenter = CGPointZero;
if (UIInterfaceOrientationIsLandscape(toOrientation)) {
rotationBounds = CGRectMake(0, 0, maxSize, minSize);
rotationCenter = (fromOrientation == UIInterfaceOrientationPortrait || self.contentView.superview != self.landscapeViewController.view) ? CGPointMake(minSize * 0.5, maxSize * 0.5) : CGPointMake(maxSize * 0.5, minSize * 0.5);
}
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
if (fromOrientation == UIInterfaceOrientationPortrait) {
rotationTransform = [self getRotationTransform:toOrientation];
}
if (self.disableAnimations) {
[CATransaction begin];
[CATransaction setDisableActions:YES];
}
[UIView animateWithDuration:0.3 animations:^{
if (toOrientation == UIInterfaceOrientationPortrait) {
self.contentView.transform = rotationTransform;
self.contentView.frame = sourceFrame;
}else {
self.contentView.transform = rotationTransform;
self.contentView.bounds = rotationBounds;
self.contentView.center = rotationCenter;
}
[self.contentView layoutIfNeeded];
} completion:^(BOOL finished) {
if (self.disableAnimations) {
[CATransaction commit];
}
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if (toOrientation == UIInterfaceOrientationPortrait) {
[self.containerView addSubview:self.contentView];
self.contentView.frame = self.containerView.bounds;
}else {
[self setNeedsUpdateOfSupportedInterfaceOrientations];
self.contentView.transform = CGAffineTransformIdentity;
[self.landscapeViewController.view addSubview:self.contentView];
self.contentView.frame = self.window.bounds;
[self.contentView layoutIfNeeded];
}
!completion ?: completion();
[self didChangeOrientation:toOrientation];
}];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window {
if (window == self.window) {
return 1 << self.currentOrientation;
}
return UIInterfaceOrientationMaskPortrait;
}
- (CGAffineTransform)getRotationTransform:(UIInterfaceOrientation)orientation {
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
if (orientation == UIInterfaceOrientationLandscapeLeft) {
rotationTransform = CGAffineTransformMakeRotation(-M_PI_2);
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
rotationTransform = CGAffineTransformMakeRotation(M_PI_2);
}
return rotationTransform;
}
@end

View File

@ -0,0 +1,17 @@
//
// GKRotationManager_iOS_9_15.h
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKRotationManager.h"
NS_ASSUME_NONNULL_BEGIN
API_DEPRECATED("deprecated!", ios(9.0, 16.0)) @interface GKRotationManager_iOS_9_15 : GKRotationManager
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,177 @@
//
// GKRotationManager_iOS_9_15.m
// Example
//
// Created by QuintGao on 2023/3/31.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKRotationManager_iOS_9_15.h"
#import "GKLandscapeViewController.h"
API_DEPRECATED("deprecated!", ios(9.0, 16.0)) @interface GKLandscapeViewController_iOS_9_15 : GKLandscapeViewController
@property (nonatomic, strong, readonly) UIView *playerSuperview;
@end
@implementation GKLandscapeViewController_iOS_9_15
- (void)viewDidLoad {
[super viewDidLoad];
_playerSuperview = [[UIView alloc] initWithFrame:CGRectZero];
_playerSuperview.backgroundColor = UIColor.clearColor;
[self.view addSubview:_playerSuperview];
}
- (BOOL)shouldAutorotate {
if ([self.delegate respondsToSelector:@selector(viewControllerShouldAutorotate:)]) {
return [self.delegate viewControllerShouldAutorotate:self];
}
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
@end
@interface GKRotationManager_iOS_9_15()<GKLandscapeViewControllerDelegate> {
void(^_rotateCompleted)(void);
}
@property (nonatomic, strong, readonly) GKLandscapeViewController_iOS_9_15 *landscapeViewController;
@property (nonatomic, assign) BOOL forceRotation;
@end
@implementation GKRotationManager_iOS_9_15
@synthesize landscapeViewController = _landscapeViewController;
- (GKLandscapeViewController *)landscapeViewController {
if (!_landscapeViewController) {
_landscapeViewController = [[GKLandscapeViewController_iOS_9_15 alloc] init];
_landscapeViewController.delegate = self;
}
return _landscapeViewController;
}
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation completion:(void (^)(void))completion {
[super interfaceOrientation:orientation completion:completion];
_rotateCompleted = completion;
self.forceRotation = YES;
[UIDevice.currentDevice setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
[UIDevice.currentDevice setValue:@(orientation) forKey:@"orientation"];
}
- (void)rotationBegin {
if (self.window.isHidden) {
self.window.hidden = NO;
[self.window makeKeyAndVisible];
}
[UIView animateWithDuration:0.0 animations:^{} completion:^(BOOL finished) {
[self.window.rootViewController setNeedsStatusBarAppearanceUpdate];
}];
}
- (void)rotationEnd {
if (!self.window.isHidden && !UIInterfaceOrientationIsLandscape(self.currentOrientation)) {
self.window.hidden = YES;
[self.containerView.window makeKeyAndVisible];
}
self.disableAnimations = NO;
if (_rotateCompleted) {
_rotateCompleted();
_rotateCompleted = nil;
}
}
- (BOOL)allowsRotation {
if (UIDeviceOrientationIsValidInterfaceOrientation(UIDevice.currentDevice.orientation)) {
UIInterfaceOrientation toOrientation = self.currentDeviceOrientation;
if (![self isSupportInterfaceOrientation:toOrientation]) {
return NO;
}
}
if (self.forceRotation) return YES;
if (self.allowOrientationRotation) return YES;
return NO;
}
#pragma mark - GKLandscapeViewControllerDelegate
- (BOOL)viewControllerShouldAutorotate:(GKLandscapeViewController *)viewController {
if ([self allowsRotation]) {
[self rotationBegin];
return YES;
}
return NO;
}
- (void)viewController:(GKLandscapeViewController *)viewController viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
UIInterfaceOrientation toOrientation = self.currentDeviceOrientation;
if (![self isSupportInterfaceOrientation:toOrientation]) return;
[self willChangeOrientation:toOrientation];
self.currentOrientation = toOrientation;
if (self.currentOrientation != UIInterfaceOrientationPortrait) {
if (self.contentView.superview != self.landscapeViewController.playerSuperview) {
CGRect frame = [self.contentView convertRect:self.contentView.bounds toView:self.contentView.window];
self.landscapeViewController.playerSuperview.frame = frame;
self.contentView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.landscapeViewController.playerSuperview addSubview:self.contentView];
[self.contentView layoutIfNeeded];
}
if (self.disableAnimations) {
[CATransaction begin];
[CATransaction setDisableActions:YES];
}
[UIView animateWithDuration:0.0 animations:^{ /** preparing */} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.landscapeViewController.playerSuperview.frame = (CGRect){CGPointZero, size};
[self.contentView layoutIfNeeded];
} completion:^(BOOL finished) {
if (self.disableAnimations) {
[CATransaction commit];
}
self.forceRotation = NO;
[self rotationEnd];
[self didChangeOrientation:toOrientation];
}];
}];
}else {
if (self.disableAnimations) {
[CATransaction begin];
[CATransaction setDisableActions:YES];
}
[UIView animateWithDuration:0.0 animations:^{ /** preparing */ } completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.landscapeViewController.playerSuperview.frame = [self.containerView convertRect:self.containerView.bounds toView:self.containerView.window];
[self.contentView layoutIfNeeded];
} completion:^(BOOL finished) {
if (self.disableAnimations) {
[CATransaction commit];
}
self.forceRotation = NO;
UIView *snapshot = [self.contentView snapshotViewAfterScreenUpdates:NO];
snapshot.frame = self.containerView.bounds;
snapshot.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.containerView addSubview:snapshot];
[UIView animateWithDuration:0.0 animations:^{} completion:^(BOOL finished) {
self.contentView.frame = self.containerView.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.containerView addSubview:self.contentView];
[self.contentView layoutIfNeeded];
[snapshot removeFromSuperview];
[self rotationEnd];
[self didChangeOrientation:toOrientation];
}];
}];
}];
}
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
@end

View File

@ -0,0 +1,84 @@
//
// GKDYPlayerManager.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GKDYVideoScrollView.h"
#import "GKDYVideoPortraitView.h"
#import "GKDYVideoLandscapeView.h"
#import <ZFPlayer/ZFPlayer.h>
NS_ASSUME_NONNULL_BEGIN
@class GKDYVideoCell, GKDYVideoPortraitCell, GKDYVideoLandscapeCell;
@protocol GKDYPlayerManagerDelegate <NSObject>
- (void)scrollViewShouldLoadMore;
- (void)scrollViewDidPanDistance:(CGFloat)distance isEnd:(BOOL)isEnd;
- (void)celldidClickShare:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell;
- (void)celldidClickEpiscode:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell;
- (void)celldidClickFavorite:(GKDYVideoModel *)model cell:(GKDYVideoPortraitCell *)cell;
- (void)cellZoomBegan:(GKDYVideoModel *)model;
- (void)cellZoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen;
- (void)cellSwitchWithModel:(GKDYVideoModel *)model;
@end
@interface GKDYPlayerManager : NSObject
@property (nonatomic, strong, readonly) ZFPlayerController *player;
@property (nonatomic, weak) id<GKDYPlayerManagerDelegate> delegate;
// 竖屏滑动容器
@property (nonatomic, strong) GKDYVideoScrollView *scrollView;
// 横屏滑动容器
@property (nonatomic, strong, nullable) GKDYVideoScrollView *landscapeScrollView;
@property (nonatomic, weak) GKDYVideoPortraitCell *currentCell;
@property (nonatomic, weak) GKDYVideoLandscapeCell *landscapeCell;
// 竖屏控制层
@property (nonatomic, weak) GKDYVideoPortraitView *portraitView;
// 横屏控制层
@property (nonatomic, strong) GKDYVideoLandscapeView *landscapeView;
@property (nonatomic, assign) CGSize videoSize;
/// 页码
@property (nonatomic, assign) NSInteger page;
/// 数据源
@property (nonatomic, strong) NSMutableArray *dataSources;
@property (nonatomic, assign) BOOL isPlaying;
@property (nonatomic, assign) BOOL isAppeared;
/// 请求播放地址
- (void)requestPlayUrlWithModel:(GKDYVideoModel *)model completion:(nullable void(^)(void))completion;
/// 播放视频
- (void)playVideoWithCell:(GKDYVideoCell *)cell index:(NSInteger)index;
/// 停止播放
- (void)stopPlayWithCell:(GKDYVideoCell *)cell index:(NSInteger)index;
/// 旋转
- (void)rotate;
- (void)play;
- (void)pause;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,504 @@
//
// GKDYPlayerManager.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYPlayerManager.h"
#import <AFNetworking/AFNetworking.h>
#import <ZFPlayer/ZFPlayer.h>
#import <ZFPlayer/ZFAVPlayerManager.h>
#import "GKDYVideoCell.h"
#import "GKRotationManager.h"
#import "GKDYVideoPortraitCell.h"
#import "GKDYVideoLandscapeCell.h"
#import "GKDYVideoFullscreenView.h"
@interface GKDYPlayerManager()<GKVideoScrollViewDataSource, GKDYVideoScrollViewDelegate, GKDYVideoPortraitCellDelegate>
@property (nonatomic, strong) ZFPlayerController *player;
@property (nonatomic, strong) GKRotationManager *rotationManager;
@property (nonatomic, assign) BOOL isSeeking;
@property (nonatomic, strong) GKDYVideoFullscreenView *fullscreenView;
@end
@implementation GKDYPlayerManager
- (instancetype)init {
if (self = [super init]) {
[self initPlayer];
}
return self;
}
- (void)dealloc {
NSLog(@"GKDYPlayerManager dealloc");
[self stop];
}
- (void)initPlayer {
//
ZFAVPlayerManager *manager = [[ZFAVPlayerManager alloc] init];
ZFPlayerController *player = [[ZFPlayerController alloc] init];
player.shouldAutoPlay = YES;
player.currentPlayerManager = manager;
player.disableGestureTypes = ZFPlayerDisableGestureTypesPan | ZFPlayerDisableGestureTypesPinch;
player.allowOrentitaionRotation = NO; //
self.player = player;
@weakify(self);
//
player.playerDidToEnd = ^(id<ZFPlayerMediaPlayback> _Nonnull asset) {
@strongify(self);
[self.scrollView scrollToNextPage];
};
//
player.playerPlayFailed = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, id _Nonnull error) {
@strongify(self);
self.portraitView.resumeButton.hidden = NO;
};
//
player.playerLoadStateChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, ZFPlayerLoadState loadState) {
@strongify(self);
if ((loadState == ZFPlayerLoadStatePrepare || loadState == ZFPlayerLoadStateStalled) && self.player.currentPlayerManager.isPlaying) {
[self.portraitView.slider showLoading];
}else {
[self.portraitView.slider hideLoading];
// [self.player.currentPlayerManager play];
}
};
//
player.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) {
@strongify(self);
[self.portraitView.slider updateCurrentTime:currentTime totalTime:duration];
};
//
player.orientationWillChange = ^(ZFPlayerController * _Nonnull player, BOOL isFullScreen) {
@strongify(self);
self.player.controlView.hidden = YES;
if (player.isFullScreen) {
[self.landscapeView startTimer];
}else {
[self.landscapeView destoryTimer];
}
};
//
player.orientationDidChanged = ^(ZFPlayerController * _Nonnull player, BOOL isFullScreen) {
@strongify(self);
if (isFullScreen) {
self.landscapeView.hidden = NO;
self.player.controlView = self.landscapeView;
}else {
self.portraitView.hidden = NO;
self.player.controlView = self.portraitView;
}
};
self.rotationManager = [GKRotationManager rotationManager];
self.rotationManager.contentView = self.player.currentPlayerManager.view;
self.landscapeView.rotationManager = self.rotationManager;
//
self.rotationManager.orientationWillChange = ^(BOOL isFullscreen) {
@strongify(self);
self.player.controlView.hidden = YES;
if (isFullscreen) {
[self.landscapeView startTimer];
}else {
self.player.currentPlayerManager.view.backgroundColor = UIColor.clearColor;
self.portraitView.hidden = NO;
[self.landscapeView destoryTimer];
if (self.landscapeScrollView) {
UIView *superview = self.landscapeScrollView.superview;
[superview addSubview:self.rotationManager.contentView];
[self.landscapeScrollView removeFromSuperview];
self.landscapeScrollView = nil;
self.landscapeCell = nil;
}
}
};
//
self.rotationManager.orientationDidChanged = ^(BOOL isFullscreen) {
@strongify(self);
if (isFullscreen) {
// self.portraitView.hidden = YES;
self.landscapeView.hidden = NO;
[self.landscapeView hideContainerView:NO];
if (!self.landscapeScrollView) {
[self initLandscapeScrollView];
UIView *superview = self.rotationManager.contentView.superview;
self.landscapeScrollView.frame = superview.bounds;
[superview addSubview:self.landscapeScrollView];
self.landscapeScrollView.defaultIndex = self.scrollView.currentIndex;
[self.landscapeScrollView reloadData];
}
self.player.controlView = self.landscapeView;
[self.currentCell resetView];
[self.landscapeCell hideTopView];
}else {
self.portraitView.hidden = NO;
self.landscapeView.hidden = YES;
self.player.controlView = self.portraitView;
if (self.player.containerView != self.currentCell.coverImgView) {
self.player.containerView = self.currentCell.coverImgView;
}
self.player.currentPlayerManager.view.backgroundColor = UIColor.blackColor;
}
};
player.presentationSizeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, CGSize size) {
@strongify(self);
self.videoSize = size;
};
}
- (void)initLandscapeScrollView {
self.landscapeScrollView = [[GKDYVideoScrollView alloc] init];
self.landscapeScrollView.backgroundColor = UIColor.blackColor;
self.landscapeScrollView.dataSource = self;
self.landscapeScrollView.delegate = self;
[self.landscapeScrollView registerClass:GKDYVideoLandscapeCell.class forCellReuseIdentifier:@"GKDYVideoLandscapeCell"];
}
- (BOOL)isPlaying {
return self.player.currentPlayerManager.isPlaying;
}
- (void)requestPlayUrlWithModel:(GKDYVideoModel *)model completion:(nullable void (^)(void))completion {
if (model.videoInfo.video_url.length > 0) return;
// if (model.task) {
// [model.task cancel];
// model.task = nil;
// }
//
// AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//
// NSString *url = [NSString stringWithFormat:@"https://haokan.baidu.com/v?vid=%@&_format=json&", model.video_id];
//
// model.task = [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// if ([responseObject[@"errno"] integerValue] == 0) {
// NSDictionary *videoMeta = responseObject[@"data"][@"apiData"][@"curVideoMeta"];
// model.play_url = videoMeta[@"playurl"];
// model.comment = videoMeta[@"comment"];
// model.like = videoMeta[@"fmlike_num"];
//
// __block NSInteger index = 0;
// __block BOOL exist = NO;
// [self.dataSources enumerateObjectsUsingBlock:^(GKDYVideoModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
// if ([obj.video_id isEqualToString:model.video_id]) {
// index = idx;
// exist = YES;
// *stop = YES;
// }
// }];
// [self.dataSources replaceObjectAtIndex:index withObject:model];
// model.task = nil;
// !completion ?: completion();
// }
// } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// model.task = nil;
// NSLog(@"播放地址请求失败");
// }];
}
- (void)playVideoWithCell:(GKDYVideoCell *)cell index:(NSInteger)index {
if (self.dataSources.count - index < 2) {
if ([self.delegate respondsToSelector:@selector(scrollViewShouldLoadMore)]) {
[self.delegate scrollViewShouldLoadMore];
}
}
GKDYVideoModel *model = self.dataSources[index];
self.landscapeView.model = model;
if ([cell isKindOfClass:GKDYVideoPortraitCell.class]) {
self.currentCell = (GKDYVideoPortraitCell *)cell;
self.portraitView = self.currentCell.portraitView;
self.rotationManager.containerView = cell.coverImgView;
if (self.rotationManager.isFullscreen) return;
}else {
self.landscapeCell = (GKDYVideoLandscapeCell *)cell;
[self.landscapeCell autoHide];
[self.scrollView scrollToPageWithIndex:index];
}
//
if (self.player.containerView != cell.coverImgView) {
self.player.containerView = cell.coverImgView;
}
//
if ([cell isKindOfClass:GKDYVideoPortraitCell.class]) {
GKDYVideoPortraitCell *portraitCell = (GKDYVideoPortraitCell *)cell;
if (self.player.controlView != portraitCell.portraitView) {
self.player.controlView = portraitCell.portraitView;
self.portraitView = portraitCell.portraitView;
}
}
//
id<ZFPlayerMediaPlayback> manager = self.player.currentPlayerManager;
[manager.view.coverImageView sd_setImageWithURL:[NSURL URLWithString:model.image_url]];
if (model.videoInfo.video_url.length > 0) {
//
if ([self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return;
//
self.player.assetURL = [NSURL URLWithString:model.videoInfo.video_url];
self.portraitView.resumeButton.hidden = YES;
if (self.isAppeared) {
[self.player.currentPlayerManager play];
}
}else {
@weakify(self);
[self requestPlayUrlWithModel:model completion:^{
@strongify(self);
//
if ([self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return;
//
self.player.assetURL = [NSURL URLWithString:model.videoInfo.video_url];
self.portraitView.resumeButton.hidden = YES;
if (self.isAppeared) {
[self.player.currentPlayerManager play];
}
}];
}
}
- (void)stopPlayWithCell:(GKDYVideoCell *)cell index:(NSInteger)index {
GKDYVideoModel *model = self.dataSources[index];
if (![self.player.assetURL.absoluteString isEqualToString:model.videoInfo.video_url]) return;
[self.player stop];
if ([self.player.controlView isKindOfClass:GKDYVideoPortraitView.class]) {
[self.player.controlView removeFromSuperview];
self.player.controlView = nil;
}
[cell resetView];
}
- (void)rotate {
[self.rotationManager rotate];
}
- (void)play {
if (self.isPlaying) return;
[self.player.currentPlayerManager play];
// [self.currentCell.portraitView handleSingleTapped];
}
- (void)pause {
if (!self.isPlaying) return;
[self.player.currentPlayerManager pause];
}
- (void)stop {
[self.player.currentPlayerManager stop];
self.player = nil;
}
#pragma mark - Private
- (void)likeVideoWithModel:(GKDYVideoModel *)model {
if (model == nil) {
model = self.currentCell.model;
}
model.is_collect = YES;
[self.scrollView reloadData];
}
#pragma mark - GKVideoScrollViewDataSource
- (NSInteger)numberOfRowsInScrollView:(GKVideoScrollView *)scrollView {
return self.dataSources.count;
}
- (GKVideoViewCell *)scrollView:(GKVideoScrollView *)scrollView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
GKDYVideoModel *model = self.dataSources[indexPath.row];
if (scrollView == self.scrollView) {
GKDYVideoPortraitCell *cell = [scrollView dequeueReusableCellWithIdentifier:@"GKDYVideoPortraitCell" forIndexPath:indexPath];
cell.delegate = self;
cell.manager = self;
cell.portraitView.slider.player = self.player;
[cell loadData:model];
return cell;
}else {
GKDYVideoLandscapeCell *cell = [scrollView dequeueReusableCellWithIdentifier:@"GKDYVideoLandscapeCell" forIndexPath:indexPath];
[cell loadData:model];
@weakify(self);
cell.backClickBlock = ^{
@strongify(self);
[self rotate];
};
[cell showTopView];
return cell;
}
}
#pragma mark - GKDYVideoScrollViewDelegate
- (void)scrollView:(GKVideoScrollView *)scrollView didEndScrollingCell:(GKVideoViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[self playVideoWithCell:(GKDYVideoCell *)cell index:indexPath.row];
if ([self.delegate respondsToSelector:@selector(cellSwitchWithModel:)]) {
[self.delegate cellSwitchWithModel:self.dataSources[indexPath.row]];
}
}
- (void)scrollView:(GKVideoScrollView *)scrollView didEndDisplayingCell:(GKVideoViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[self stopPlayWithCell:(GKDYVideoCell *)cell index:indexPath.row];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView == self.scrollView) {
if (self.scrollView.currentIndex == 0 && scrollView.contentOffset.y < 0) {
self.scrollView.contentOffset = CGPointZero;
}
}
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.portraitView willBeginDragging];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
[self.portraitView didEndDragging];
}
- (void)scrollView:(GKDYVideoScrollView *)scrollView didPanWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd {
if ([self.delegate respondsToSelector:@selector(scrollViewDidPanDistance:isEnd:)]) {
[self.delegate scrollViewDidPanDistance:distance isEnd:isEnd];
}
}
#pragma mark - GKDYVideoPortraitCellDelegate
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFavorite:(GKDYVideoModel *)model {
[self.scrollView reloadData];
if ([self.delegate respondsToSelector:@selector(celldidClickFavorite:cell:)]) {
[self.delegate celldidClickFavorite:model cell:cell];
}
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickEpiscode:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(celldidClickEpiscode:cell:)]) {
[self.delegate celldidClickEpiscode:model cell:cell];
}
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickShare:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(celldidClickShare:cell:)]) {
[self.delegate celldidClickShare:model cell:cell];
}
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickDanmu:(GKDYVideoModel *)model {
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFullscreen:(GKDYVideoModel *)model {
[self rotate];
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell zoomBegan:(GKDYVideoModel *)model {
self.player.controlView.hidden = YES;
if ([self.delegate respondsToSelector:@selector(cellZoomBegan:)]) {
[self.delegate cellZoomBegan:model];
}
}
- (void)videoCell:(GKDYVideoPortraitCell *)cell zoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen {
if (isFullscreen) {
self.fullscreenView.hidden = NO;
if (self.player.controlView != self.fullscreenView) {
self.player.controlView = self.fullscreenView;
self.player.disableGestureTypes = ZFPlayerDisableGestureTypesPinch;
}
}else {
self.currentCell.portraitView.hidden = NO;
if (self.player.controlView != self.currentCell.portraitView) {
self.player.controlView = self.currentCell.portraitView;
self.player.disableGestureTypes = ZFPlayerDisableGestureTypesPan | ZFPlayerDisableGestureTypesPinch;
}
}
if ([self.delegate respondsToSelector:@selector(cellZoomEnded:isFullscreen:)]) {
[self.delegate cellZoomEnded:model isFullscreen:isFullscreen];
}
}
#pragma mark - Lazy
- (GKDYVideoScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[GKDYVideoScrollView alloc] init];
_scrollView.dataSource = self;
_scrollView.delegate = self;
_scrollView.backgroundColor = UIColor.blackColor;
[_scrollView registerClass:GKDYVideoPortraitCell.class forCellReuseIdentifier:@"GKDYVideoPortraitCell"];
[_scrollView addPanGesture];
}
return _scrollView;
}
- (GKDYVideoLandscapeView *)landscapeView {
if (!_landscapeView) {
_landscapeView = [[GKDYVideoLandscapeView alloc] initWithFrame:UIScreen.mainScreen.bounds];
@weakify(self);
_landscapeView.likeBlock = ^(GKDYVideoModel * _Nonnull model) {
@strongify(self);
[self likeVideoWithModel:model];
};
_landscapeView.singleTapBlock = ^{
@strongify(self);
if (self.landscapeCell.isShowTop) {
[self.landscapeCell hideTopView];
[self.landscapeView hideContainerView:NO];
}else {
[self.landscapeView autoHide];
}
};
}
return _landscapeView;
}
- (GKDYVideoFullscreenView *)fullscreenView {
if (!_fullscreenView) {
_fullscreenView = [[GKDYVideoFullscreenView alloc] init];
@weakify(self);
_fullscreenView.closeFullscreenBlock = ^{
@strongify(self);
[self.currentCell closeFullscreen];
};
_fullscreenView.likeBlock = ^{
@strongify(self);
[self likeVideoWithModel:nil];
};
}
return _fullscreenView;
}
- (NSMutableArray *)dataSources {
if (!_dataSources) {
_dataSources = [NSMutableArray array];
}
return _dataSources;
}
@end

View File

@ -0,0 +1,21 @@
//
// GKDUVideoInfoModel.h
// QinJiuTV
//
// Created by HI_LOSER on 2024/5/28.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDUVideoInfoModel : NSObject
@property (assign, nonatomic) NSInteger status;
@property (assign, nonatomic) NSInteger skits_id;
@property (assign, nonatomic) NSInteger vid;
@property (copy, nonatomic) NSString * video_url;
@property (assign, nonatomic) NSInteger episode;
@property (assign, nonatomic) BOOL is_vip;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,14 @@
//
// GKDUVideoInfoModel.m
// QinJiuTV
//
// Created by HI_LOSER on 2024/5/28.
//
#import "GKDUVideoInfoModel.h"
@implementation GKDUVideoInfoModel
+ (NSDictionary *)mj_replacedKeyFromPropertyName{
return @{@"vid" : @"id"};
}
@end

View File

@ -0,0 +1,88 @@
//
// GKDYVideoModel.h
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "GKDUVideoInfoModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoModel : NSObject<NSCopying>
//@property (nonatomic, copy) NSString *video_id;
//@property (nonatomic, copy) NSString *poster_small;
//@property (nonatomic, copy) NSString *poster_big;
//@property (nonatomic, copy) NSString *poster_pc;
//@property (nonatomic, copy) NSString *source_name;
//@property (nonatomic, copy) NSString *play_url;
//@property (nonatomic, copy) NSString *duration;
//@property (nonatomic, copy) NSString *url;
//@property (nonatomic, copy) NSString *show_tag;
//@property (nonatomic, copy) NSString *publish_time;
//@property (nonatomic, copy) NSString *is_pay_column;
//@property (nonatomic, copy) NSString *like;
//@property (nonatomic, copy) NSString *comment;
//@property (nonatomic, copy) NSString *playcnt;
//@property (nonatomic, copy) NSString *fmplaycnt;
//@property (nonatomic, copy) NSString *fmplaycnt_2;
//@property (nonatomic, copy) NSString *outstand_tag;
//@property (nonatomic, copy) NSString *previewUrlHttp;
//@property (nonatomic, copy) NSString *third_id;
//@property (nonatomic, copy) NSString *vip;
//@property (nonatomic, copy) NSString *author_avatar;
//
//@property (nonatomic, assign) BOOL isLike;
@property (nonatomic, strong, nullable) NSURLSessionDataTask *task;
@property (nonatomic, assign) BOOL isRequest;
@property (nonatomic, assign) BOOL requested;
/// 短剧id
@property (assign, nonatomic) NSInteger cid;
/// 收藏数量
@property (assign, nonatomic) NSInteger collect_total;
/// 集数
@property (assign, nonatomic) NSInteger episode_total;
@property (assign, nonatomic) NSInteger episode;
/// 观看数量
@property (assign, nonatomic) NSInteger watch_total;
/// 是否购买
@property (assign, nonatomic) BOOL buy_type;
/// 是否收藏
@property (assign, nonatomic) BOOL is_collect;
@property (assign, nonatomic) NSInteger process;
/// 价格
@property (strong, nonatomic) NSNumber * all_price;
/// 标题 剧名
@property (copy, nonatomic) NSString * title; // name
/// 剧情描述
@property (copy, nonatomic) NSString * detailText;
/// 封面 海报
@property (copy, nonatomic) NSString * image_url;
@property (strong, nonatomic) GKDUVideoInfoModel * videoInfo;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,77 @@
//
// GKDYVideoModel.m
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
//
#import "GKDYVideoModel.h"
@implementation GKDYVideoModel
/*
/// id
@property (assign, nonatomic) NSInteger ;
///
@property (assign, nonatomic) NSInteger ;
///
@property (assign, nonatomic) NSInteger ;
///
@property (assign, nonatomic) BOOL ;
///
@property (assign, nonatomic) BOOL ;
///
@property (assign, nonatomic) BOOL ;
@property (assign, nonatomic) NSInteger ;
///
@property (strong, nonatomic) NSNumber * ;
///
@property (copy, nonatomic) NSString * ; // name
///
@property (copy, nonatomic) NSString * ;
///
@property (copy, nonatomic) NSString * ;
@property (strong, nonatomic) GKDUVideoInfoModel * ;
*/
- (id)copyWithZone:(NSZone *)zone{
GKDYVideoModel * model = [self.class new];
model.cid = self.cid;
model.collect_total = self.collect_total;
model.episode_total = self.episode_total;
model.episode = self.episode;
model.watch_total = self.watch_total;
model.buy_type = self.buy_type;
model.is_collect = self.is_collect;
model.process = self.process;
model.all_price = self.all_price;
model.title = self.title;
model.detailText = self.detailText;
model.image_url = self.image_url;
model.videoInfo = self.videoInfo;
return model;
}
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
return @{@"cid" : @"id",
@"detailText" : @"description",
@"videoInfo" : @"video_info",
@"title" : @"name"};
}
@end

View File

@ -0,0 +1,24 @@
//
// GKDYPanGestureRecognizer.h
// GKDYVideo
//
// Created by gaokun on 2019/7/31.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, GKDYPanGestureRecognizerDirection) {
GKDYPanGestureRecognizerDirectionVertical,
GKDYPanGestureRecognizerDirectionHorizontal
};
@interface GKDYPanGestureRecognizer : UIPanGestureRecognizer
@property (nonatomic, assign) GKDYPanGestureRecognizerDirection direction;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,54 @@
//
// GKDYPanGestureRecognizer.h
// GKDYVideo
//
// Created by gaokun on 2019/7/31.
// Copyright © 2019 QuintGao. All rights reserved.
//
#import "GKDYPanGestureRecognizer.h"
int const static kDirectionPanThreshold = 5;
@interface GKDYPanGestureRecognizer()
@property (nonatomic, assign) BOOL drag;
@property (nonatomic, assign) int moveX;
@property (nonatomic, assign) int moveY;
@end
@implementation GKDYPanGestureRecognizer
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
CGPoint nowPoint = [[touches anyObject] locationInView:self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
_moveX += prevPoint.x - nowPoint.x;
_moveY += prevPoint.y - nowPoint.y;
if (!_drag) {
if (abs(_moveX) > kDirectionPanThreshold) {
if (_direction == GKDYPanGestureRecognizerDirectionVertical) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}else if (abs(_moveY) > kDirectionPanThreshold) {
if (_direction == GKDYPanGestureRecognizerDirectionHorizontal) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}
}
}
- (void)reset {
[super reset];
_drag = NO;
_moveX = 0;
_moveY = 0;
}
@end

View File

@ -0,0 +1,17 @@
//
// GKDYScrollView.h
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYScrollView : UIScrollView
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,58 @@
//
// GKDYScrollView.m
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
//
#import "GKDYScrollView.h"
@implementation GKDYScrollView
#pragma mark - push
// UIScrollView
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([self panBack:gestureRecognizer]) {
return NO;
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([self panBack:gestureRecognizer]) {
return YES;
}
return NO;
}
- (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == self.panGestureRecognizer) {
CGPoint point = [self.panGestureRecognizer translationInView:self];
UIGestureRecognizerState state = gestureRecognizer.state;
//
CGFloat locationDistance = self.bounds.size.width;
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStatePossible) {
CGPoint location = [gestureRecognizer locationInView:self];
if (point.x > 0 && location.x < locationDistance && self.contentOffset.x <= 0) {
return YES;
}
// scrollViewx
CGFloat criticalPoint = self.frame.size.width;
// point.x < 0
// UIScrollviewUIScrollview
if (point.x < 0 && self.contentOffset.x + criticalPoint >= self.contentSize.width) {
return YES;
}
}
}
return NO;
}
@end

View File

@ -0,0 +1,26 @@
//
// GKDYTitleView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/27.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <JXCategoryView/JXCategoryView.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYTitleView : UIView
@property (nonatomic, strong) JXCategoryTitleView *categoryView;
@property (nonatomic, copy) void(^loadingBlock)(void);
- (void)changeAlphaWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd;
- (void)loadingEnd;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,195 @@
//
// GKDYTitleView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/27.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYTitleView.h"
#import "GKBallLoadingView.h"
#define kTransitionCenter 20.0f
@interface GKDYTitleView()
@property (nonatomic, strong) UILabel *refreshLabel;
@property (nonatomic, strong) UIButton *searchBtn;
@property (nonatomic, strong) GKBallLoadingView *loadingView;
@property (nonatomic, assign) BOOL isRefreshing;
@end
@implementation GKDYTitleView
- (instancetype)init {
if (self = [super init]) {
[self initUI];
}
return self;
}
- (void)initUI {
[self addSubview:self.categoryView];
[self addSubview:self.searchBtn];
[self addSubview:self.refreshLabel];
[self addSubview:self.loadingView];
[self.categoryView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self);
make.left.equalTo(self).offset(60);
make.right.equalTo(self).offset(-60);
}];
[self.searchBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self).offset(-15);
make.top.bottom.equalTo(self);
}];
[self.refreshLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self);
make.centerX.equalTo(self);
}];
[self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self).offset(-15);
make.centerY.equalTo(self);
make.width.height.mas_equalTo(44);
}];
}
- (void)changeAlphaWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd {
if (isEnd) {
[UIView animateWithDuration:0.25 animations:^{
[self changeFrameWithDistance:0];
self.categoryView.alpha = 1;
self.refreshLabel.alpha = 0;
self.loadingView.alpha = 1;
}];
if (distance >= 2 * kTransitionCenter) {
self.searchBtn.alpha = 0;
self.isRefreshing = YES;
[self.loadingView startLoading];
!self.loadingBlock ?: self.loadingBlock();
}else {
self.searchBtn.alpha = 1;
self.loadingView.alpha = 0;
}
}else {
if (distance <= 0) {
self.categoryView.alpha = 1;
self.searchBtn.alpha = 1;
self.refreshLabel.alpha = 0;
self.loadingView.alpha = 0;
}else if (distance > 0 && distance < kTransitionCenter) {
CGFloat alpha = distance / kTransitionCenter;
self.categoryView.alpha = 1 - alpha;
self.searchBtn.alpha = 1 - alpha;
self.refreshLabel.alpha = 0;
self.loadingView.alpha = 0;
//
[self changeFrameWithDistance:distance];
}else if (distance >= kTransitionCenter && distance <= 2 * kTransitionCenter) {
CGFloat alpha = (2 * kTransitionCenter - distance) / kTransitionCenter;
self.categoryView.alpha = 0;
self.searchBtn.alpha = 0;
self.refreshLabel.alpha = 1 - alpha;
self.loadingView.alpha = 1 - alpha;
//
[self changeFrameWithDistance:distance];
[self.loadingView startLoadingWithProgress:1 - alpha];
}else {
self.categoryView.alpha = 0;
self.searchBtn.alpha = 0;
self.refreshLabel.alpha = 1;
self.loadingView.alpha = 1;
[self.loadingView startLoadingWithProgress:1];
}
}
}
- (void)changeFrameWithDistance:(CGFloat)distance {
CGRect frame = self.categoryView.frame;
frame.origin.y = distance;
self.categoryView.frame = frame;
frame = self.searchBtn.frame;
frame.origin.y = distance;
self.searchBtn.frame = frame;
frame = self.refreshLabel.frame;
frame.origin.y = distance;
self.refreshLabel.frame = frame;
frame = self.loadingView.frame;
frame.origin.y = distance;
self.loadingView.frame = frame;
}
- (void)loadingEnd {
self.searchBtn.alpha = 1;
self.loadingView.alpha = 0;
[self.loadingView stopLoading];
self.isRefreshing = NO;
}
- (void)searchClick:(id)sender {
}
#pragma mark - Lazy
- (JXCategoryTitleView *)categoryView {
if (!_categoryView) {
_categoryView = [[JXCategoryTitleView alloc] init];
_categoryView.backgroundColor = UIColor.clearColor;
_categoryView.titleColor = UIColor.lightGrayColor;
_categoryView.titleSelectedColor = UIColor.whiteColor;
_categoryView.titleFont = [UIFont systemFontOfSize:16];
_categoryView.titleSelectedFont = [UIFont boldSystemFontOfSize:16];
_categoryView.cellSpacing = 10;
JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init];
lineView.indicatorColor = UIColor.whiteColor;
lineView.indicatorWidthIncrement = -4;
_categoryView.indicators = @[lineView];
}
return _categoryView;
}
- (UIButton *)searchBtn {
if (!_searchBtn) {
_searchBtn = [[UIButton alloc] init];
[_searchBtn setImage:[UIImage imageNamed:@"ich_feed_search_Normal"] forState:UIControlStateNormal];
[_searchBtn addTarget:self action:@selector(searchClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _searchBtn;
}
- (UILabel *)refreshLabel {
if (!_refreshLabel) {
_refreshLabel = [[UILabel alloc] init];
_refreshLabel.font = [UIFont systemFontOfSize:16];
_refreshLabel.textColor = UIColor.whiteColor;
_refreshLabel.text = @"下拉刷新内容";
_refreshLabel.alpha = 0;
}
return _refreshLabel;
}
- (GKBallLoadingView *)loadingView {
if (!_loadingView) {
_loadingView = [[GKBallLoadingView alloc] init];
_loadingView.alpha = 0;
}
return _loadingView;
}
@end

View File

@ -0,0 +1,29 @@
//
// GKDYVideoCell.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <GKVideoScrollView/GKVideoScrollView.h>
#import "GKDYVideoModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoCell : GKVideoViewCell
@property (nonatomic, strong) GKDYVideoModel *model;
@property (nonatomic, strong) UIImageView *coverImgView;
- (void)initUI;
- (void)loadData:(GKDYVideoModel *)model;
- (void)resetView;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,58 @@
//
// GKDYVideoCell.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoCell.h"
@interface GKDYVideoCell()
@end
@implementation GKDYVideoCell
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
[self initUI];
}
return self;
}
- (void)initUI {
[self addSubview:self.coverImgView];
[self.coverImgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
}
- (void)loadData:(GKDYVideoModel *)model {
self.model = model;
[self.coverImgView sd_setImageWithURL:[NSURL URLWithString:model.image_url]];
}
- (void)setModel:(GKDYVideoModel *)model {
_model = model;
[self.coverImgView sd_setImageWithURL:[NSURL URLWithString:model.image_url]];
}
- (void)resetView {
}
#pragma mark - Lazy
- (UIImageView *)coverImgView {
if (!_coverImgView) {
_coverImgView = [[UIImageView alloc] init];
_coverImgView.contentMode = UIViewContentModeScaleAspectFit;
_coverImgView.userInteractionEnabled = YES;
}
return _coverImgView;
}
@end

View File

@ -0,0 +1,55 @@
//
// GKDYVideoControlView.h
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
// 播放器视图控制层
#import <UIKit/UIKit.h>
//#import "GKAWEModel.h"
#import <GKSliderView/GKSliderView.h>
NS_ASSUME_NONNULL_BEGIN
@class GKDYVideoControlView;
@protocol GKDYVideoControlViewDelegate <NSObject>
- (void)controlViewDidClickSelf:(GKDYVideoControlView *)controlView;
- (void)controlViewDidClickPriase:(GKDYVideoControlView *)controlView;
- (void)controlViewdidClickEpiscode:(GKDYVideoControlView *)controlView;
- (void)controlViewDidClickShare:(GKDYVideoControlView *)controlView;
- (void)controlView:(GKDYVideoControlView *)controlView touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
@end
@interface GKDYVideoControlView : UIView
@property (nonatomic, weak) id<GKDYVideoControlViewDelegate> delegate;
// 视频封面图:显示封面并播放视频
@property (nonatomic, strong) UIImageView *coverImgView;
@property (nonatomic, strong) id model;
@property (nonatomic, strong) GKSliderView *sliderView;
- (void)setProgress:(float)progress;
- (void)startLoading;
- (void)stopLoading;
- (void)showPlayBtn;
- (void)hidePlayBtn;
- (void)showLikeAnimation;
- (void)showUnLikeAnimation;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,302 @@
//
// GKDYVideoControlView.m
// GKDYVideo
//
// Created by QuintGao on 2018/9/23.
// Copyright © 2018 QuintGao. All rights reserved.
//
#import "GKDYVideoControlView.h"
#import "GKLikeView.h"
//#import "NSString+GKCategory.h"
#import "GKDYVideoItemButton.h"
@interface GKDYVideoControlView()
@property (nonatomic, strong) UIImageView *iconView;
@property (nonatomic, strong) GKLikeView *likeView;
@property (nonatomic, strong) GKDYVideoItemButton *commentBtn;
@property (nonatomic, strong) GKDYVideoItemButton *shareBtn;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *contentLabel;
@property (nonatomic, strong) UIButton *playBtn;
@property (nonatomic, strong) UILabel *label;
@end
@implementation GKDYVideoControlView
- (instancetype)init {
if (self = [super init]) {
[self addSubview:self.coverImgView];
[self addSubview:self.iconView];
[self addSubview:self.likeView];
[self addSubview:self.commentBtn];
[self addSubview:self.shareBtn];
[self addSubview:self.nameLabel];
[self addSubview:self.contentLabel];
[self addSubview:self.sliderView];
[self addSubview:self.playBtn];
[self addSubview:self.label];
[self.coverImgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
CGFloat bottomM = [UIScreen bottomSafeHeight];
self.sliderView.frame = CGRectMake(0, HBScreenSize.height - [UIScreen bottomSafeHeight] - 0.5, HBScreenSize.width, 1.0f);
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(HBAdapt(30.0f));
make.bottom.equalTo(self).offset(-(HBAdapt(30.0f) + bottomM));
make.width.mas_equalTo(HBAdapt(504.0f));
}];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentLabel);
make.bottom.equalTo(self.contentLabel.mas_top).offset(-HBAdapt(20.0f));
}];
[self.shareBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self).offset(-HBAdapt(30.0f));
make.bottom.equalTo(self.sliderView.mas_top).offset(-HBAdapt(100.0f));
make.width.height.mas_equalTo(HBAdapt(110.0f));
}];
[self.commentBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.shareBtn);
make.bottom.equalTo(self.shareBtn.mas_top).offset(-HBAdapt(45.0f));
make.width.height.mas_equalTo(HBAdapt(110.0f));
}];
[self.likeView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.shareBtn);
make.bottom.equalTo(self.commentBtn.mas_top).offset(-HBAdapt(45.0f));
make.width.height.mas_equalTo(HBAdapt(110.0f));
}];
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.shareBtn);
make.bottom.equalTo(self.likeView.mas_top).offset(-HBAdapt(70.0f));
make.width.height.mas_equalTo(HBAdapt(100.0f));
}];
[self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
}];
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
}];
}
return self;
}
//- (void)setModel:(GKAWEModel *)model {
// _model = model;
//
// self.sliderView.value = 0;
//
// if (model.video.width.floatValue > model.video.height.floatValue) {
// self.coverImgView.contentMode = UIViewContentModeScaleAspectFit;
// }else {
// self.coverImgView.contentMode = UIViewContentModeScaleAspectFill;
// }
// NSString *url = model.video.cover.url_list.firstObject;
// [self.coverImgView sd_setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"img_video_loading"]];
// self.nameLabel.text = [NSString stringWithFormat:@"@%@", model.author.nickname];
// [self.iconView sd_setImageWithURL:[NSURL URLWithString:model.author.avatar_thumb.url_list.firstObject] placeholderImage:[UIImage imageNamed:@"placeholderimg"]];
// self.contentLabel.text = model.desc;
//
// [self.likeView setupLikeState:model.is_like];
// [self.likeView setupLikeCount:[model.statistics.digg_count gk_unitConvert]];
//
// [self.commentBtn setTitle:[model.statistics.comment_count gk_unitConvert] forState:UIControlStateNormal];
// [self.shareBtn setTitle:[model.statistics.share_count gk_unitConvert] forState:UIControlStateNormal];
//
// self.label.text = [NSString stringWithFormat:@"第%zd个", model.index];
//}
#pragma mark - Public Methods
- (void)setProgress:(float)progress {
self.sliderView.value = progress;
}
- (void)startLoading {
[self.sliderView showLineLoading];
}
- (void)stopLoading {
[self.sliderView hideLineLoading];
}
- (void)showPlayBtn {
self.playBtn.hidden = NO;
}
- (void)hidePlayBtn {
self.playBtn.hidden = YES;
}
- (void)showLikeAnimation {
[self.likeView startAnimationWithIsLike:YES];
}
- (void)showUnLikeAnimation {
[self.likeView startAnimationWithIsLike:NO];
}
#pragma mark - Action
- (void)controlViewDidClick {
if ([self.delegate respondsToSelector:@selector(controlViewDidClickSelf:)]) {
[self.delegate controlViewDidClickSelf:self];
}
}
- (void)praiseBtnClick:(id)sender {
if ([self.delegate respondsToSelector:@selector(controlViewDidClickPriase:)]) {
[self.delegate controlViewDidClickPriase:self];
}
}
- (void)commentBtnClick:(id)sender {
if ([self.delegate respondsToSelector:@selector(controlViewdidClickEpiscode:)]) {
[self.delegate controlViewdidClickEpiscode:self];
}
}
- (void)shareBtnClick:(id)sender {
if ([self.delegate respondsToSelector:@selector(controlViewDidClickShare:)]) {
[self.delegate controlViewDidClickShare:self];
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
NSTimeInterval delayTime = 0.3f;
if (touch.tapCount <= 1) {
[self performSelector:@selector(controlViewDidClick) withObject:nil afterDelay:delayTime];
}else {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(controlViewDidClick) object:nil];
if ([self.delegate respondsToSelector:@selector(controlView:touchesBegan:withEvent:)]) {
[self.delegate controlView:self touchesBegan:touches withEvent:event];
}
}
}
#pragma mark -
- (UIImageView *)coverImgView {
if (!_coverImgView) {
_coverImgView = [UIImageView new];
_coverImgView.contentMode = UIViewContentModeScaleAspectFill;
_coverImgView.clipsToBounds = YES;
}
return _coverImgView;
}
- (UIImageView *)iconView {
if (!_iconView) {
_iconView = [UIImageView new];
_iconView.layer.cornerRadius = HBAdapt(50.0f);
_iconView.layer.masksToBounds = YES;
_iconView.layer.borderColor = [UIColor whiteColor].CGColor;
_iconView.layer.borderWidth = 1.0f;
_iconView.userInteractionEnabled = YES;
UITapGestureRecognizer *iconTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(iconDidClick:)];
[_iconView addGestureRecognizer:iconTap];
}
return _iconView;
}
- (GKLikeView *)likeView {
if (!_likeView) {
_likeView = [GKLikeView new];
}
return _likeView;
}
- (GKDYVideoItemButton *)commentBtn {
if (!_commentBtn) {
_commentBtn = [GKDYVideoItemButton new];
[_commentBtn setImage:[UIImage imageNamed:@"icon_home_comment"] forState:UIControlStateNormal];
_commentBtn.titleLabel.font = [UIFont systemFontOfSize:13.0f];
[_commentBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_commentBtn addTarget:self action:@selector(commentBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _commentBtn;
}
- (GKDYVideoItemButton *)shareBtn {
if (!_shareBtn) {
_shareBtn = [GKDYVideoItemButton new];
[_shareBtn setImage:[UIImage imageNamed:@"icon_home_share"] forState:UIControlStateNormal];
_shareBtn.titleLabel.font = [UIFont systemFontOfSize:13.0f];
[_shareBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[_shareBtn addTarget:self action:@selector(shareBtnClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _shareBtn;
}
- (UILabel *)nameLabel {
if (!_nameLabel) {
_nameLabel = [UILabel new];
_nameLabel.textColor = [UIColor whiteColor];
_nameLabel.font = [UIFont boldSystemFontOfSize:15.0f];
_nameLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *nameTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(iconDidClick:)];
[_nameLabel addGestureRecognizer:nameTap];
}
return _nameLabel;
}
- (UILabel *)contentLabel {
if (!_contentLabel) {
_contentLabel = [UILabel new];
_contentLabel.numberOfLines = 0;
_contentLabel.textColor = [UIColor whiteColor];
_contentLabel.font = [UIFont systemFontOfSize:14.0f];
}
return _contentLabel;
}
- (GKSliderView *)sliderView {
if (!_sliderView) {
_sliderView = [GKSliderView new];
_sliderView.isHideSliderBlock = YES;
_sliderView.sliderHeight = 1.0f;
_sliderView.maximumTrackTintColor = [UIColor clearColor];
_sliderView.minimumTrackTintColor = HBColor.color_FF0049;
}
return _sliderView;
}
- (UIButton *)playBtn {
if (!_playBtn) {
_playBtn = [UIButton new];
[_playBtn setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];
_playBtn.hidden = YES;
}
return _playBtn;
}
- (UILabel *)label {
if (!_label) {
_label = [[UILabel alloc] init];
_label.font = [UIFont systemFontOfSize:30];
_label.backgroundColor = UIColor.blackColor;
_label.textColor = UIColor.whiteColor;
}
return _label;
}
@end

View File

@ -0,0 +1,21 @@
//
// GKDYVideoFullscreenView.h
// GKDYVideo
//
// Created by QuintGao on 2023/5/8.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <ZFPlayer/ZFPlayer.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoFullscreenView : UIView<ZFPlayerMediaControl>
@property (nonatomic, copy) void(^closeFullscreenBlock)(void);
@property (nonatomic, copy) void(^likeBlock)(void);
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,211 @@
//
// GKDYVideoFullscreenView.m
// GKDYVideo
//
// Created by QuintGao on 2023/5/8.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoFullscreenView.h"
#import "GKDoubleLikeView.h"
@interface GKDYVideoFullscreenView()
@property (nonatomic, strong) UIView *bottomView;
@property (nonatomic, strong) UIView *leftView;
@property (nonatomic, strong) UIButton *closeBtn;
@property (nonatomic, strong) UIView *rightView;
@property (nonatomic, strong) UIButton *playBtn;
@property (nonatomic, strong) UIButton *speedBtn;
@property (nonatomic, strong) NSArray *speeds;
@property (nonatomic, assign) NSInteger currentSpeed;
@property (nonatomic, strong) GKDoubleLikeView *likeView;
@property (nonatomic, strong) NSDate *lastDoubleTapTime;
@end
@implementation GKDYVideoFullscreenView
- (instancetype)init {
if (self = [super init]) {
[self initUI];
self.speeds = @[@1, @1.5, @2, @0.5];
self.currentSpeed = 0;
}
return self;
}
- (void)initUI {
[self addSubview:self.bottomView];
[self.bottomView addSubview:self.leftView];
[self.leftView addSubview:self.closeBtn];
[self.bottomView addSubview:self.rightView];
[self.rightView addSubview:self.playBtn];
[self.rightView addSubview:self.speedBtn];
[self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.bottom.equalTo(self);
make.height.mas_equalTo(44);
}];
[self.leftView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.bottomView).offset(10);
make.top.bottom.equalTo(self.bottomView);
make.width.mas_equalTo(58);
}];
[self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.leftView);
}];
[self.rightView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.bottomView).offset(-10);
make.top.bottom.equalTo(self.bottomView);
make.width.mas_equalTo(100);
}];
[self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self.rightView);
make.right.equalTo(self.rightView.mas_centerX);
}];
[self.speedBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.top.bottom.equalTo(self.rightView);
make.left.equalTo(self.rightView.mas_centerX);
}];
}
#pragma mark - ZFPlayerMediaControl
@synthesize player = _player;
- (void)setPlayer:(ZFPlayerController *)player {
_player = player;
self.playBtn.selected = player.currentPlayerManager.isPlaying;
}
- (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
CGFloat diff = [NSDate date].timeIntervalSince1970 - self.lastDoubleTapTime.timeIntervalSince1970;
if (diff < 0.6) {
[self handleDoubleTapped:gestureControl.singleTap];
self.lastDoubleTapTime = [NSDate date];
}else {
[self handleSingleTapped];
}
}
- (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
[self handleDoubleTapped:gestureControl.doubleTap];
self.lastDoubleTapTime = [NSDate date];
}
- (void)gestureBeganPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
[self closeAction];
}
- (void)handleSingleTapped {
[self playAction];
}
- (void)handleDoubleTapped:(UITapGestureRecognizer *)gesture {
CGPoint point = [gesture locationInView:gesture.view];
[self.likeView createAnimationWithPoint:point view:gesture.view completion:nil];
!self.likeBlock ?: self.likeBlock();
}
#pragma mark - action
- (void)closeAction {
!self.closeFullscreenBlock ?: self.closeFullscreenBlock();
}
- (void)playAction {
id<ZFPlayerMediaPlayback> manager = self.player.currentPlayerManager;
if (manager.isPlaying) {
[manager pause];
self.playBtn.selected = NO;
}else {
[manager play];
self.playBtn.selected = YES;
}
}
- (void)speedAction {
self.currentSpeed++;
if (self.currentSpeed == self.speeds.count) {
self.currentSpeed = 0;
}
float speed = [self.speeds[self.currentSpeed] floatValue];
self.player.currentPlayerManager.rate = speed;
[self.speedBtn setTitle:[NSString stringWithFormat:@"%@x", self.speeds[self.currentSpeed]] forState:UIControlStateNormal];
}
#pragma mark - lazy
- (UIView *)bottomView {
if (!_bottomView) {
_bottomView = [[UIView alloc] init];
}
return _bottomView;
}
- (UIView *)leftView {
if (!_leftView) {
_leftView = [[UIView alloc] init];
_leftView.backgroundColor = UIColor.darkGrayColor;
_leftView.layer.cornerRadius = 5;
_leftView.layer.masksToBounds = YES;
}
return _leftView;
}
- (UIButton *)closeBtn {
if (!_closeBtn) {
_closeBtn = [[UIButton alloc] init];
[_closeBtn setImage:[UIImage imageNamed:@"icon_feedback_close_Normal"] forState:UIControlStateNormal];
[_closeBtn addTarget:self action:@selector(closeAction) forControlEvents:UIControlEventTouchUpInside];
}
return _closeBtn;
}
- (UIView *)rightView {
if (!_rightView) {
_rightView = [[UIView alloc] init];
_rightView.backgroundColor = UIColor.darkGrayColor;
_rightView.layer.cornerRadius = 5;
_rightView.layer.masksToBounds = YES;
}
return _rightView;
}
- (UIButton *)playBtn {
if (!_playBtn) {
_playBtn = [[UIButton alloc] init];
[_playBtn setImage:[UIImage imageNamed:@"icon_modern_feed_play_Normal"] forState:UIControlStateNormal];
[_playBtn setImage:[UIImage imageNamed:@"icon_music_pause_new_Normal"] forState:UIControlStateSelected];
[_playBtn addTarget:self action:@selector(playAction) forControlEvents:UIControlEventTouchUpInside];
}
return _playBtn;
}
- (UIButton *)speedBtn {
if (!_speedBtn) {
_speedBtn = [[UIButton alloc] init];
[_speedBtn setTitle:@"1x" forState:UIControlStateNormal];
[_speedBtn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
_speedBtn.titleLabel.font = [UIFont systemFontOfSize:14];
[_speedBtn addTarget:self action:@selector(speedAction) forControlEvents:UIControlEventTouchUpInside];
}
return _speedBtn;
}
- (GKDoubleLikeView *)likeView {
if (!_likeView) {
_likeView = [[GKDoubleLikeView alloc] init];
}
return _likeView;
}
@end

View File

@ -0,0 +1,17 @@
//
// GKDYVideoItemButton.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoItemButton : UIButton
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,33 @@
//
// GKDYVideoItemButton.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoItemButton.h"
@implementation GKDYVideoItemButton
- (void)layoutSubviews {
[super layoutSubviews];
[self.imageView sizeToFit];
[self.titleLabel sizeToFit];
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
CGFloat imgW = self.imageView.frame.size.width;
CGFloat imgH = self.imageView.frame.size.height;
self.imageView.frame = CGRectMake((width - imgH) / 2, 0, imgW, imgH);
CGFloat titleW = self.titleLabel.frame.size.width;
CGFloat titleH = self.titleLabel.frame.size.height;
self.titleLabel.frame = CGRectMake((width - titleW) / 2, height - titleH, titleW, titleH);
}
@end

View File

@ -0,0 +1,26 @@
//
// GKDYVideoLandscapeCell.h
// GKDYVideo
//
// Created by QuintGao on 2023/5/5.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoCell.h"
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoLandscapeCell : GKDYVideoCell
@property (nonatomic, assign) BOOL isShowTop;
@property (nonatomic, copy) void(^backClickBlock)(void);
- (void)hideTopView;
- (void)showTopView;
- (void)autoHide;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,110 @@
//
// GKDYVideoLandscapeCell.m
// GKDYVideo
//
// Created by QuintGao on 2023/5/5.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoLandscapeCell.h"
#import "GKDYVideoMaskView.h"
#import "UIButton+GKEnlarge.h"
@interface GKDYVideoLandscapeCell()
@property (nonatomic, strong) GKDYVideoMaskView *topContainerView;
@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation GKDYVideoLandscapeCell
- (void)initUI {
[super initUI];
[self addSubview:self.topContainerView];
[self.topContainerView addSubview:self.backBtn];
[self.topContainerView addSubview:self.titleLabel];
[self.topContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self);
make.height.mas_equalTo(80);
}];
[self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(25);
make.left.equalTo(self.topContainerView.mas_safeAreaLayoutGuideLeft).offset(12);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.backBtn).offset(3);
make.left.equalTo(self.backBtn.mas_right).offset(5);
make.right.equalTo(self.topContainerView.mas_safeAreaLayoutGuideRight).offset(-30);
}];
self.topContainerView.hidden = YES;
self.isShowTop = NO;
}
- (void)loadData:(GKDYVideoModel *)model {
[super loadData:model];
self.titleLabel.text = model.title;
}
- (void)hideTopView {
self.topContainerView.hidden = YES;
self.isShowTop = NO;
}
- (void)showTopView {
self.topContainerView.hidden = NO;
self.isShowTop = YES;
}
- (void)autoHide {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideTopView) object:nil];
[self performSelector:@selector(hideTopView) withObject:nil afterDelay:3.0f];
}
- (void)resetView {
[super resetView];
[self showTopView];
}
- (void)backAction {
!self.backClickBlock ?: self.backClickBlock();
}
#pragma mark - Lazy
- (GKDYVideoMaskView *)topContainerView {
if (!_topContainerView) {
_topContainerView = [[GKDYVideoMaskView alloc] initWithStyle:GKDYVideoMaskViewStyle_Top];
}
return _topContainerView;
}
- (UIButton *)backBtn {
if (!_backBtn) {
_backBtn = [[UIButton alloc] init];
[_backBtn setEnlargeEdge:10];
[_backBtn setImage:[UIImage imageNamed:@"ic_back_white"] forState:UIControlStateNormal];
[_backBtn addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
}
return _backBtn;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [UIFont boldSystemFontOfSize:15];
_titleLabel.textColor = UIColor.whiteColor;
_titleLabel.numberOfLines = 0;
}
return _titleLabel;
}
@end

View File

@ -0,0 +1,37 @@
//
// GKDYVideoLandscapeView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <ZFPlayer/ZFPlayer.h>
#import "GKDYVideoModel.h"
#import "GKRotationManager.h"
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoLandscapeView : UIView<ZFPlayerMediaControl>
@property (nonatomic, strong) GKDYVideoModel *model;
@property (nonatomic, weak) GKRotationManager *rotationManager;
@property (nonatomic, copy) void(^likeBlock)(GKDYVideoModel *model);
@property (nonatomic, copy) void(^singleTapBlock)(void);
- (void)startTimer;
- (void)destoryTimer;
@property (nonatomic, assign) BOOL isContainerShow;
- (void)showContainerView:(BOOL)animated;
- (void)hideContainerView:(BOOL)animated;
- (void)autoHide;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,491 @@
//
// GKDYVideoLandscapeView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoLandscapeView.h"
#import "GKDYVideoStatusBar.h"
#import "GKDYVideoMaskView.h"
#import "GKDoubleLikeView.h"
#import <GKSliderView/GKSliderView.h>
#import "UIButton+GKEnlarge.h"
#import <ZFPlayer/ZFReachabilityManager.h>
#import "GKDYVideoPreviewView.h"
@interface GKDYVideoLandscapeView()<GKSliderViewDelegate, GKSliderViewPreviewDelegate>
//
@property (nonatomic, strong) GKDYVideoMaskView *topContainerView;
@property (nonatomic, strong) GKDYVideoStatusBar *statusBar;
@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *contentLabel;
//
@property (nonatomic, strong) GKDYVideoMaskView *bottomContainerView;
@property (nonatomic, strong) GKSliderView *sliderView;
@property (nonatomic, strong) UIButton *playBtn;
@property (nonatomic, strong) UILabel *timeLabel;
@property (nonatomic, strong) UIButton *likeBtn;
@property (nonatomic, strong) UIButton *exitBtn;
@property (nonatomic, strong) GKDoubleLikeView *likeView;
@property (nonatomic, strong) NSDate *lastDoubleTapTime;
@property (nonatomic, assign) BOOL isDragging;
@property (nonatomic ,assign) BOOL isSeeking;
@end
@implementation GKDYVideoLandscapeView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self initUI];
}
return self;
}
- (void)initUI {
[self addSubview:self.topContainerView];
[self.topContainerView addSubview:self.statusBar];
[self.topContainerView addSubview:self.backBtn];
[self.topContainerView addSubview:self.contentLabel];
[self.topContainerView addSubview:self.nameLabel];
[self addSubview:self.bottomContainerView];
[self.bottomContainerView addSubview:self.sliderView];
[self.bottomContainerView addSubview:self.playBtn];
[self.bottomContainerView addSubview:self.timeLabel];
[self.bottomContainerView addSubview:self.likeBtn];
[self.bottomContainerView addSubview:self.exitBtn];
[self.topContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.right.equalTo(self);
make.height.mas_equalTo(80);
}];
[self.statusBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.topContainerView.mas_safeAreaLayoutGuideTop);
make.left.equalTo(self.topContainerView.mas_safeAreaLayoutGuideLeft).offset(10);
make.right.equalTo(self.topContainerView.mas_safeAreaLayoutGuideRight).offset(-10);
make.height.mas_equalTo(20);
}];
[self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.statusBar.mas_bottom).offset(5);
make.left.equalTo(self.statusBar).offset(2);
}];
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.backBtn).offset(3);
make.left.equalTo(self.backBtn.mas_right).offset(5);
make.right.equalTo(self.statusBar.mas_right).offset(-20);
}];
[self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentLabel);
make.top.equalTo(self.contentLabel.mas_bottom).offset(5);
}];
[self.bottomContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.left.right.equalTo(self);
make.height.mas_equalTo(80);
}];
[self.sliderView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.bottomContainerView.mas_safeAreaLayoutGuideLeft).offset(10);
make.right.equalTo(self.bottomContainerView.mas_safeAreaLayoutGuideRight).offset(-10);
make.bottom.equalTo(self.playBtn.mas_top).offset(-10);
make.height.mas_equalTo(10);
}];
[self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.sliderView);
make.bottom.equalTo(self.bottomContainerView).offset(-10);
}];
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.playBtn);
make.left.equalTo(self.playBtn.mas_right).offset(10);
}];
[self.likeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.playBtn);
make.right.equalTo(self.exitBtn.mas_left).offset(-20);
}];
[self.exitBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.playBtn);
make.right.equalTo(self.sliderView.mas_right);
}];
}
- (void)setModel:(GKDYVideoModel *)model {
_model = model;
self.contentLabel.text = model.detailText;
self.nameLabel.text = model.title;
self.likeBtn.selected = model.is_collect;
}
- (void)startTimer {
[self.statusBar startTimer];
}
- (void)destoryTimer {
[self.statusBar destoryTimer];
}
#pragma mark - ZFPlayerMediaControl
@synthesize player = _player;
- (void)setPlayer:(ZFPlayerController *)player {
_player = player;
GKDYVideoPreviewView *videoPreview = (GKDYVideoPreviewView *)self.sliderView.preview;
videoPreview.player = player;
self.playBtn.selected = player.currentPlayerManager.isPlaying;
[self setNetworkState];
}
- (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationDidChanged:(ZFOrientationObserver *)observer {
if (videoPlayer.isFullScreen) {
[self showContainerView:NO];
[self cancelAutoHidden];
[self performSelector:@selector(hideContainerView:) withObject:@(YES) afterDelay:5.0f];
}
}
- (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
CGFloat diff = [NSDate date].timeIntervalSince1970 - self.lastDoubleTapTime.timeIntervalSince1970;
if (diff < 0.6) {
[self handleDoubleTapped:gestureControl.singleTap];
self.lastDoubleTapTime = [NSDate date];
}else {
[self handleSingleTapped];
}
}
- (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
[self handleDoubleTapped:gestureControl.doubleTap];
self.lastDoubleTapTime = [NSDate date];
}
- (void)videoPlayer:(ZFPlayerController *)videoPlayer reachabilityChanged:(ZFReachabilityStatus)status {
[self setNetworkState];
}
- (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
if (self.isDragging) return;
if (self.isSeeking) return;
self.sliderView.value = self.player.progress;
self.timeLabel.text = [NSString stringWithFormat:@"%@ / %@", [NSString convertTimeSecond:currentTime], [NSString convertTimeSecond:totalTime]];
}
- (void)handleSingleTapped {
!self.singleTapBlock ?: self.singleTapBlock();
}
- (void)handleDoubleTapped:(UITapGestureRecognizer *)gesture {
[self cancelAutoHidden];
CGPoint point = [gesture locationInView:gesture.view];
@weakify(self);
[self.likeView createAnimationWithPoint:point view:gesture.view completion:^{
@strongify(self);
[self performSelector:@selector(hideContainerView) withObject:nil afterDelay:5.0f];
}];
self.model.is_collect = YES;
self.likeBtn.selected = self.model.is_collect;
!self.likeBlock ?: self.likeBlock(self.model);
}
#pragma mark - Public
- (void)showContainerView:(BOOL)animated {
[self.topContainerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self);
}];
[self.bottomContainerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self);
}];
self.topContainerView.hidden = NO;
self.bottomContainerView.hidden = NO;
NSTimeInterval duration = animated ? 0.2 : 0;
[UIView animateWithDuration:duration animations:^{
[self layoutIfNeeded];
} completion:^(BOOL finished) {
self.isContainerShow = YES;
}];
}
- (void)hideContainerView {
[self hideContainerView:YES];
}
- (void)hideContainerView:(BOOL)animated {
[self.topContainerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(-80);
}];
[self.bottomContainerView mas_updateConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self).offset(80);
}];
NSTimeInterval duration = animated ? 0.15 : 0;
[UIView animateWithDuration:duration animations:^{
[self layoutIfNeeded];
} completion:^(BOOL finished) {
self.isContainerShow = NO;
self.topContainerView.hidden = YES;
self.bottomContainerView.hidden = YES;
}];
}
- (void)autoHide {
[self cancelAutoHidden];
if (self.isContainerShow) {
[self hideContainerView:YES];
}else {
[self showContainerView:YES];
[self performSelector:@selector(hideContainerView) withObject:nil afterDelay:5.0];
}
}
- (void)cancelAutoHidden {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideContainerView) object:nil];
}
- (void)setNetworkState {
NSString *net = @"WIFI";
switch (ZFReachabilityManager.sharedManager.networkReachabilityStatus) {
case ZFReachabilityStatusReachableViaWiFi:
net = @"WIFI";
break;
case ZFReachabilityStatusNotReachable:
net = @"无网络";
break;
case ZFReachabilityStatusReachableVia2G:
net = @"2G";
break;
case ZFReachabilityStatusReachableVia3G:
net = @"3G";
break;
case ZFReachabilityStatusReachableVia4G:
net = @"4G";
break;
case ZFReachabilityStatusReachableVia5G:
net = @"5G";
break;
default:
net = @"未知";
break;
}
self.statusBar.network = net;
}
#pragma mark - Action
- (void)backAction {
[self cancelAutoHidden];
[self.rotationManager rotate];
}
- (void)playAction {
[self cancelAutoHidden];
id<ZFPlayerMediaPlayback> manager = self.player.currentPlayerManager;
if (manager.isPlaying) {
[manager pause];
}else {
[manager play];
}
self.playBtn.selected = manager.isPlaying;
[self autoHide];
}
- (void)likeAction {
[self cancelAutoHidden];
self.model.is_collect = !self.model.is_collect;
self.likeBtn.selected = self.model.is_collect;
!self.likeBlock ?: self.likeBlock(self.model);
[self autoHide];
}
- (void)exitAction {
[self backAction];
}
#pragma mark - GKSliderViewDelegate
- (void)sliderView:(GKSliderView *)sliderView touchBegan:(float)value {
self.isDragging = YES;
[self showLargeSlider];
[self cancelAutoHidden];
}
- (void)sliderView:(GKSliderView *)sliderView touchEnded:(float)value {
self.isDragging = NO;
[self showSmallSlider];
[self autoHide];
}
#pragma mark - GKSliderViewPreviewDelegate
- (UIView *)sliderViewSetupPreview:(GKSliderView *)sliderView {
GKDYVideoPreviewView *preview = [[GKDYVideoPreviewView alloc] init];
preview.bounds = CGRectMake(0, 0, 120, 120);
return preview;
}
- (CGFloat)sliderViewPreviewMargin:(GKSliderView *)sliderView {
return 40;
}
- (void)sliderView:(GKSliderView *)sliderView preview:(UIView *)preview valueChanged:(float)value {
GKDYVideoPreviewView *videoPreview = (GKDYVideoPreviewView *)preview;
[videoPreview setPreviewValue:value];
}
- (void)showLargeSlider {
self.sliderView.sliderBtn.transform = CGAffineTransformMakeScale(1.5, 1.5);
self.sliderView.sliderHeight = 5;
}
- (void)showSmallSlider {
self.sliderView.sliderBtn.transform = CGAffineTransformIdentity;
self.sliderView.sliderHeight = 2;
}
#pragma mark - Lazy
- (GKDYVideoMaskView *)topContainerView {
if (!_topContainerView) {
_topContainerView = [[GKDYVideoMaskView alloc] initWithStyle:GKDYVideoMaskViewStyle_Top];
}
return _topContainerView;
}
- (GKDYVideoMaskView *)bottomContainerView {
if (!_bottomContainerView) {
_bottomContainerView = [[GKDYVideoMaskView alloc] initWithStyle:GKDYVideoMaskViewStyle_Bottom];
}
return _bottomContainerView;
}
- (GKDYVideoStatusBar *)statusBar {
if (!_statusBar) {
_statusBar = [[GKDYVideoStatusBar alloc] init];
}
return _statusBar;
}
- (UIButton *)backBtn {
if (!_backBtn) {
_backBtn = [[UIButton alloc] init];
[_backBtn setImage:[UIImage imageNamed:@"ic_back_white"] forState:UIControlStateNormal];
[_backBtn addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[_backBtn setEnlargeEdge:10];
}
return _backBtn;
}
- (UILabel *)contentLabel {
if (!_contentLabel) {
_contentLabel = [[UILabel alloc] init];
_contentLabel.font = [UIFont boldSystemFontOfSize:15];
_contentLabel.textColor = UIColor.whiteColor;
_contentLabel.numberOfLines = 0;
}
return _contentLabel;
}
- (UILabel *)nameLabel {
if (!_nameLabel) {
_nameLabel = [[UILabel alloc] init];
_nameLabel.font = [UIFont systemFontOfSize:14];
_nameLabel.textColor = UIColor.whiteColor;
}
return _nameLabel;
}
- (GKSliderView *)sliderView {
if (!_sliderView) {
_sliderView = [[GKSliderView alloc] init];
// [_sliderView setThumbImage:[UIImage imageNamed:@"icon_slider"] forState:UIControlStateNormal];
// [_sliderView setThumbImage:[UIImage imageNamed:@"icon_slider"] forState:UIControlStateHighlighted];
_sliderView.maximumTrackTintColor = UIColor.grayColor;
_sliderView.minimumTrackTintColor = HBColor.color_FF0049;
_sliderView.sliderHeight = 2;
_sliderView.delegate = self;
_sliderView.previewDelegate = self;
_sliderView.isPreviewChangePosition = NO;
_sliderView.isSliderAllowTapped = YES;
_sliderView.isSliderAllowDragged = YES;
}
return _sliderView;
}
- (UIButton *)playBtn {
if (!_playBtn) {
_playBtn = [[UIButton alloc] init];
[_playBtn setImage:[UIImage imageNamed:@"icon_play"] forState:UIControlStateNormal];
[_playBtn setImage:[UIImage imageNamed:@"icon_pause"] forState:UIControlStateSelected];
[_playBtn addTarget:self action:@selector(playAction) forControlEvents:UIControlEventTouchUpInside];
[_playBtn setEnlargeEdge:10];
}
return _playBtn;
}
- (UILabel *)timeLabel {
if (!_timeLabel) {
_timeLabel = [[UILabel alloc] init];
_timeLabel.font = [UIFont systemFontOfSize:13];
_timeLabel.textColor = UIColor.whiteColor;
}
return _timeLabel;
}
- (UIButton *)likeBtn {
if (!_likeBtn) {
_likeBtn = [[UIButton alloc] init];
[_likeBtn setImage:[UIImage imageNamed:@"ss_icon_star_normal"] forState:UIControlStateNormal];
[_likeBtn setImage:[UIImage imageNamed:@"ss_icon_star_selected"] forState:UIControlStateSelected];
[_likeBtn addTarget:self action:@selector(likeAction) forControlEvents:UIControlEventTouchUpInside];
[_likeBtn setEnlargeEdge:10];
}
return _likeBtn;
}
- (UIButton *)exitBtn {
if (!_exitBtn) {
_exitBtn = [[UIButton alloc] init];
[_exitBtn setImage:[UIImage imageNamed:@"ss_icon_shrinkscreen"] forState:UIControlStateNormal];
[_exitBtn addTarget:self action:@selector(exitAction) forControlEvents:UIControlEventTouchUpInside];
[_exitBtn setEnlargeEdge:10];
}
return _exitBtn;
}
- (GKDoubleLikeView *)likeView {
if (!_likeView) {
_likeView = [[GKDoubleLikeView alloc] init];
}
return _likeView;
}
@end

View File

@ -0,0 +1,26 @@
//
// GKDYVideoMaskView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, GKDYVideoMaskViewStyle) {
GKDYVideoMaskViewStyle_Top, // 顶部,(上->下)从深到浅
GKDYVideoMaskViewStyle_Bottom // 底部,(上->下)从浅到深
};
@interface GKDYVideoMaskView : UIView
- (instancetype)initWithStyle:(GKDYVideoMaskViewStyle)style;
- (void)clearColors;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,48 @@
//
// GKDYVideoMaskView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoMaskView.h"
@interface GKDYVideoMaskView()
@property (nonatomic, assign) GKDYVideoMaskViewStyle style;
@end
@implementation GKDYVideoMaskView
+ (Class)layerClass {
return CAGradientLayer.class;
}
- (instancetype)initWithStyle:(GKDYVideoMaskViewStyle)style {
if (self = [super init]) {
self.style = style;
CAGradientLayer *maskGradientLayer = (id)self.layer;
switch (self.style) {
case GKDYVideoMaskViewStyle_Top: {
maskGradientLayer.colors = @[(__bridge id)[UIColor colorWithWhite:0 alpha:0.8].CGColor,
(__bridge id)[UIColor clearColor].CGColor];
}
break;
case GKDYVideoMaskViewStyle_Bottom: {
maskGradientLayer.colors = @[(__bridge id)[UIColor clearColor].CGColor,
(__bridge id)[UIColor colorWithWhite:0 alpha:0.8].CGColor];
}
break;
}
}
return self;
}
- (void)clearColors {
CAGradientLayer *maskGradientLayer = (id)self.layer;
maskGradientLayer.colors = nil;
}
@end

View File

@ -0,0 +1,49 @@
//
// GKDYVideoPortraitCell.h
// GKDYVideo
//
// Created by QuintGao on 2023/5/5.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoCell.h"
#import "GKDYPlayerManager.h"
#import "GKDYVideoPortraitView.h"
NS_ASSUME_NONNULL_BEGIN
@class GKDYVideoPortraitCell;
@protocol GKDYVideoPortraitCellDelegate <NSObject>
@optional;
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFavorite:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickEpiscode:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickShare:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickDanmu:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell didClickFullscreen:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell zoomBegan:(GKDYVideoModel *)model;
- (void)videoCell:(GKDYVideoPortraitCell *)cell zoomEnded:(GKDYVideoModel *)model isFullscreen:(BOOL)isFullscreen;
@end
@interface GKDYVideoPortraitCell : GKDYVideoCell
@property (nonatomic, weak) id<GKDYVideoPortraitCellDelegate> delegate;
@property (nonatomic, strong) GKDYVideoPortraitView *portraitView;
@property (nonatomic, weak) GKDYPlayerManager *manager;
- (void)closeFullscreen;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,174 @@
//
// GKDYVideoPortraitCell.m
// GKDYVideo
//
// Created by QuintGao on 2023/5/5.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoPortraitCell.h"
@interface GKDYVideoPortraitCell()<GKDYVideoPortraitViewDelegate, UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, assign) BOOL isFullscreen;
@property (nonatomic, assign) BOOL isCodeSet;
@end
@implementation GKDYVideoPortraitCell
- (void)initUI {
[self addSubview:self.scrollView];
[self.scrollView addSubview:self.coverImgView];
// [self addSubview:self.coverImgView];
[self.coverImgView addSubview:self.portraitView];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
// [self.coverImgView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.edges.equalTo(self);
// }];
}
- (void)layoutSubviews {
[super layoutSubviews];
self.coverImgView.frame = self.scrollView.bounds;
self.portraitView.frame = self.coverImgView.bounds;
}
- (void)loadData:(GKDYVideoModel *)model {
[super loadData:model];
self.portraitView.model = model;
if (self.manager) {
[self.manager requestPlayUrlWithModel:model completion:nil];
}
}
- (void)resetView {
[super resetView];
self.portraitView.slider.player = nil;
self.portraitView.slider.sliderView.value = 0;
self.portraitView.hidden = NO;
self.portraitView.frame = self.coverImgView.bounds;
[self.coverImgView addSubview:self.portraitView];
}
#pragma mark - UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.coverImgView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
self.coverImgView.center = [self centerOfScrollViewContent:scrollView];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
if (self.isCodeSet) return;
if ([self.delegate respondsToSelector:@selector(videoCell:zoomBegan:)]) {
[self.delegate videoCell:self zoomBegan:self.model];
}
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale {
if (self.isCodeSet) {
self.isCodeSet = NO;
return;
}
if ([self.delegate respondsToSelector:@selector(videoCell:zoomEnded:isFullscreen:)]) {
BOOL isFullscreen = NO;
if (scale > 1) {
isFullscreen = YES;
self.isFullscreen = isFullscreen;
}else {
self.isFullscreen = !self.isFullscreen;
isFullscreen = self.isFullscreen;
}
[self.delegate videoCell:self zoomEnded:self.model isFullscreen:isFullscreen];
}
if (scale != 1) {
self.isCodeSet = YES;
[scrollView setZoomScale:1.0f animated:YES];
}
}
- (CGPoint)centerOfScrollViewContent:(UIScrollView *)scrollView {
CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width) ? (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0;
CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height) ? (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0;
CGPoint actualCenter = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, scrollView.contentSize.height * 0.5 + offsetY);
return actualCenter;
}
- (void)closeFullscreen {
self.isFullscreen = NO;
if ([self.delegate respondsToSelector:@selector(videoCell:zoomEnded:isFullscreen:)]) {
[self.delegate videoCell:self zoomEnded:self.model isFullscreen:self.isFullscreen];
}
}
#pragma mark - GKDYVideoPortraitViewDelegate
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickFavorite:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(videoCell:didClickFavorite:)]) {
[self.delegate videoCell:self didClickFavorite:model];
}
}
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickEpiscode:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(videoCell:didClickEpiscode:)]) {
[self.delegate videoCell:self didClickEpiscode:model];
}
}
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickShare:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(videoCell:didClickShare:)]) {
[self.delegate videoCell:self didClickShare:model];
}
}
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickDanmu:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(videoCell:didClickDanmu:)]) {
[self.delegate videoCell:self didClickDanmu:model];
}
}
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickFullscreen:(GKDYVideoModel *)model {
if ([self.delegate respondsToSelector:@selector(videoCell:didClickFullscreen:)]) {
[self.delegate videoCell:self didClickFullscreen:model];
}
}
#pragma mark - Lazy
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];
_scrollView.delegate = self;
_scrollView.backgroundColor = UIColor.clearColor;
_scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.minimumZoomScale = 1.0f;
_scrollView.maximumZoomScale = 10.0f;
}
return _scrollView;
}
- (GKDYVideoPortraitView *)portraitView {
if (!_portraitView) {
_portraitView = [[GKDYVideoPortraitView alloc] initWithFrame:UIScreen.mainScreen.bounds];
_portraitView.delegate = self;
}
return _portraitView;
}
@end

View File

@ -0,0 +1,64 @@
//
// GKDYVideoPortraitView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <ZFPlayer/ZFPlayer.h>
#import "GKDYVideoModel.h"
#import "GKDYVideoSlider.h"
#import "GKLikeView.h"
NS_ASSUME_NONNULL_BEGIN
@class GKDYVideoPortraitView;
@protocol GKDYVideoPortraitViewDelegate <NSObject>
/// 收藏点击事件代理
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickFavorite:(GKDYVideoModel *)model;
/// 剧集点击事件代理
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickEpiscode:(GKDYVideoModel *)model;
/// 分享点击事件代理
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickShare:(GKDYVideoModel *)model;
/// 弹幕点击事件代理
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickDanmu:(GKDYVideoModel *)model;
/// 全屏点击事件代理
- (void)videoPortraitView:(GKDYVideoPortraitView *) view didClickFullscreen:(GKDYVideoModel *)model;
@end
@interface GKDYVideoPortraitView : UIView<ZFPlayerMediaControl>
@property (nonatomic, weak) id<GKDYVideoPortraitViewDelegate> delegate;
/// 数据模型
@property (nonatomic, strong) GKDYVideoModel * model;
/// 视频介绍等
@property (nonatomic, strong) UIView * bottomContainerView;
/// 进度条
@property (nonatomic, strong) GKDYVideoSlider * slider;
/// 收藏按钮 带动画
@property (nonatomic, strong) GKLikeView * favoriteButton;
/// 继续播放按钮
@property (nonatomic, strong) UIButton * resumeButton;
- (void)handleSingleTapped;
- (void)willBeginDragging;
- (void)didEndDragging;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,393 @@
//
// GKDYVideoPortraitView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoPortraitView.h"
#import "GKDYVideoItemButton.h"
#import "GKDoubleLikeView.h"
#import "UIButton+GKEnlarge.h"
@interface GKDYVideoPortraitView()
@property (nonatomic, strong) UIView * buttonContainerView;
@property (nonatomic, strong) UILabel * titleLabel;
@property (nonatomic, strong) UILabel * contentLabel;
@property (nonatomic, strong) UILabel * episcodeLabel;
@property (nonatomic, strong) UIButton * shareButton;
@property (nonatomic, strong) RSButton * episcodeButton;
@property (nonatomic, strong) UIButton * danmuButton;
@property (nonatomic, strong) UIButton * fullscreenButton;
@property (nonatomic, strong) GKDoubleLikeView * doubleLikeView;
@property (nonatomic, strong) NSDate * lastDoubleTapTime;
@end
@implementation GKDYVideoPortraitView
@synthesize player = _player;
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self initUI];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)initUI {
[self addSubview:self.bottomContainerView];
[self.bottomContainerView addSubview:self.contentLabel];
[self.bottomContainerView addSubview:self.episcodeLabel];
[self.bottomContainerView addSubview:self.titleLabel];
[self.bottomContainerView addSubview:self.buttonContainerView];
[self.buttonContainerView addSubview:self.shareButton];
[self.buttonContainerView addSubview:self.episcodeButton];
[self.buttonContainerView addSubview:self.favoriteButton];
[self addSubview:self.slider];
[self addSubview:self.danmuButton];
[self addSubview:self.fullscreenButton];
[self addSubview:self.resumeButton];
[self.bottomContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.bottom.equalTo(self.mas_safeAreaLayoutGuideBottom);
}];
[self.slider mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(16.0);
make.right.equalTo(self).offset(-16.0);
make.bottom.equalTo(self.mas_safeAreaLayoutGuideBottom);
make.height.mas_equalTo(20.0);
}];
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.slider);
make.bottom.equalTo(self.slider.mas_top).offset(-10.0);
}];
[self.buttonContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.bottomContainerView);
make.right.equalTo(self.contentLabel);
make.bottom.equalTo(self.contentLabel.mas_top).offset(-30.0);
}];
[self.episcodeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentLabel);
make.bottom.equalTo(self.contentLabel.mas_top).offset(-12.0);
make.right.equalTo(self.buttonContainerView.mas_left).offset(-8.0);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.episcodeLabel);
make.bottom.equalTo(self.episcodeLabel.mas_top).offset(-8.0);
}];
[self.shareButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.left.right.equalTo(self.buttonContainerView);
}];
[self.episcodeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.buttonContainerView);
make.bottom.equalTo(self.shareButton.mas_top).offset(-26.0);
}];
[self.favoriteButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.buttonContainerView);
make.bottom.equalTo(self.episcodeButton.mas_top).offset(-26.0);
}];
[self.danmuButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.bottomContainerView);
make.right.equalTo(self.mas_centerX).offset(-40);
make.width.height.mas_equalTo(30);
}];
[self.fullscreenButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.danmuButton);
make.left.equalTo(self.danmuButton.mas_right).offset(20);
make.width.mas_equalTo(80);
make.height.mas_equalTo(30);
}];
[self.resumeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
}];
}
#pragma mark - ZFPlayerMediaControl
- (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
CGFloat diff = [NSDate date].timeIntervalSince1970 - self.lastDoubleTapTime.timeIntervalSince1970;
if (diff < 0.6) {
[self handleDoubleTapped:gestureControl.singleTap];
self.lastDoubleTapTime = [NSDate date];
}else {
[self handleSingleTapped];
}
}
- (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
[self handleDoubleTapped:gestureControl.doubleTap];
self.lastDoubleTapTime = [NSDate date];
}
- (void)handleSingleTapped {
id<ZFPlayerMediaPlayback> manager = self.player.currentPlayerManager;
if (manager.isPlaying) {
[manager pause];
[self.slider showLargeSlider];
self.resumeButton.hidden = NO;
self.resumeButton.transform = CGAffineTransformMakeScale(3, 3);
[UIView animateWithDuration:0.15 animations:^{
self.resumeButton.alpha = 1;
self.resumeButton.transform = CGAffineTransformIdentity;
}];
}else {
[manager play];
[self.slider showSmallSlider];
[UIView animateWithDuration:0.15 animations:^{
self.resumeButton.alpha = 0;
} completion:^(BOOL finished) {
self.resumeButton.hidden = YES;
}];
}
}
- (void)handleDoubleTapped:(UITapGestureRecognizer *)gesture {
CGPoint point = [gesture locationInView:gesture.view];
[self.doubleLikeView createAnimationWithPoint:point view:gesture.view completion:nil];
[self.favoriteButton startAnimationWithIsLike:YES];
self.model.is_collect = YES;
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickFavorite:)]) {
[self.delegate videoPortraitView:self didClickFavorite:self.model];
}
}
- (void)setModel:(GKDYVideoModel *)model {
_model = model;
self.titleLabel.text = model.title;
self.contentLabel.text = model.detailText;
self.episcodeLabel.text = [NSString stringWithFormat:[@"player_text_episcode" language],model.videoInfo.episode,model.episode];
[self.favoriteButton setupLikeCount:[NSString stringWithFormat:@"%ld", model.collect_total]];
[self.favoriteButton setupLikeState:model.is_collect];
}
#pragma mark - Action
- (void)favoriteAction {
self.model.is_collect = !self.model.is_collect;
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickFavorite:)]) {
[self.delegate videoPortraitView:self didClickFavorite:self.model];
}
}
- (void)episcodeAction {
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickEpiscode:)]) {
[self.delegate videoPortraitView:self didClickEpiscode:self.model];
}
}
- (void)shareAction {
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickShare:)]) {
[self.delegate videoPortraitView:self didClickShare:self.model];
}
}
- (void)danmuAction {
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickDanmu:)]) {
[self.delegate videoPortraitView:self didClickDanmu:self.model];
}
}
- (void)fullscreenAction {
if ([self.delegate respondsToSelector:@selector(videoPortraitView:didClickFullscreen:)]) {
[self.delegate videoPortraitView:self didClickFullscreen:self.model];
}
}
- (void)sliderDragging:(BOOL)isDragging {
self.bottomContainerView.alpha = !isDragging;
}
- (void)willBeginDragging {
self.bottomContainerView.alpha = 0.4;
self.danmuButton.alpha = 0.4;
self.fullscreenButton.alpha = 0.4;
}
- (void)didEndDragging {
self.bottomContainerView.alpha = 1;
self.danmuButton.alpha = 1;
self.fullscreenButton.alpha = 1;
}
#pragma mark - Lazy
- (UIView *)bottomContainerView {
if (!_bottomContainerView) {
_bottomContainerView = [[UIView alloc] init];
}
return _bottomContainerView;
}
- (UIView *)buttonContainerView{
if (!_buttonContainerView) {
_buttonContainerView = [[UIView alloc] init];
}
return _buttonContainerView ;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.font = [UIFont boldSystemFontOfSize:16];
_titleLabel.textColor = UIColor.whiteColor;
_titleLabel.userInteractionEnabled = YES;
}
return _titleLabel;
}
- (UILabel *)episcodeLabel {
if (!_episcodeLabel) {
_episcodeLabel = [[UILabel alloc] init];
_episcodeLabel.font = [UIFont systemFontOfSize:12.0 weight:UIFontWeightMedium];
_episcodeLabel.textColor = UIColor.whiteColor;
_episcodeLabel.text = @"Episode 1 Complete set : 999";
}
return _episcodeLabel;
}
- (UILabel *)contentLabel {
if (!_contentLabel) {
_contentLabel = [[UILabel alloc] init];
_contentLabel.font = [UIFont systemFontOfSize:12.0 weight:UIFontWeightLight];
_contentLabel.textColor = UIColor.whiteColor;
_contentLabel.numberOfLines = 4;
}
return _contentLabel;
}
- (GKDYVideoSlider *)slider {
if (!_slider) {
_slider = [[GKDYVideoSlider alloc] init];
@weakify(self);
_slider.slideBlock = ^(BOOL isDragging) {
@strongify(self);
[self sliderDragging:isDragging];
};
}
return _slider;
}
- (GKLikeView *)favoriteButton {
if (!_favoriteButton) {
_favoriteButton = [[GKLikeView alloc] init];
@weakify(self);
_favoriteButton.likeBlock = ^{
@strongify(self);
[self favoriteAction];
};
}
return _favoriteButton;
}
- (RSButton *)episcodeButton {
if (!_episcodeButton) {
_episcodeButton = [[RSButton alloc] initWithType:RSButtonTypeAbove];
_episcodeButton.margin = 4.0;
[_episcodeButton setTitleFont:[UIFont systemFontOfSize:12.0f weight:UIFontWeightRegular]];
[_episcodeButton setImage:[UIImage imageNamed:@"player_episode"] forState:UIControlStateNormal];
[_episcodeButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
[_episcodeButton setTitle:[@"player_text_series" language] forState:UIControlStateNormal];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(episcodeAction)];
[_episcodeButton addGestureRecognizer:tapGesture];
}
return _episcodeButton;
}
- (UIButton *)shareButton {
if (!_shareButton) {
_shareButton = [[UIButton alloc] init];
[_shareButton setImage:[UIImage imageNamed:@"player_shared"] forState:UIControlStateNormal];
[_shareButton addTarget:self action:@selector(shareAction) forControlEvents:UIControlEventTouchUpInside];
}
return _shareButton;
}
- (UIButton *)danmuButton {
if (!_danmuButton) {
_danmuButton = [[UIButton alloc] init];
_danmuButton.hidden = YES;
[_danmuButton setTitle:@"弹" forState:UIControlStateNormal];
[_danmuButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
_danmuButton.titleLabel.font = [UIFont systemFontOfSize:15];
_danmuButton.layer.cornerRadius = 15;
_danmuButton.layer.masksToBounds = YES;
_danmuButton.layer.borderColor = UIColor.whiteColor.CGColor;
_danmuButton.layer.borderWidth = 0.5;
[_danmuButton addTarget:self action:@selector(danmuAction) forControlEvents:UIControlEventTouchUpInside];
}
return _danmuButton;
}
- (UIButton *)fullscreenButton {
if (!_fullscreenButton) {
_fullscreenButton = [[UIButton alloc] init];
_fullscreenButton.hidden = YES;
[_fullscreenButton setTitle:@"全屏观看" forState:UIControlStateNormal];
[_fullscreenButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
_fullscreenButton.titleLabel.font = [UIFont systemFontOfSize:15];
_fullscreenButton.layer.cornerRadius = 15;
_fullscreenButton.layer.masksToBounds = YES;
_fullscreenButton.layer.borderColor = UIColor.whiteColor.CGColor;
_fullscreenButton.layer.borderWidth = 0.5;
[_fullscreenButton addTarget:self action:@selector(fullscreenAction) forControlEvents:UIControlEventTouchUpInside];
}
return _fullscreenButton;
}
- (UIButton *)resumeButton {
if (!_resumeButton) {
_resumeButton = [[UIButton alloc] init];
[_resumeButton setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];
_resumeButton.hidden = YES;
}
return _resumeButton;
}
- (GKDoubleLikeView *)doubleLikeView {
if (!_doubleLikeView) {
_doubleLikeView = [[GKDoubleLikeView alloc] init];
}
return _doubleLikeView;
}
@end

View File

@ -0,0 +1,22 @@
//
// GKDYVideoPreviewView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <ZFPlayer/ZFPlayer.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoPreviewView : UIView
@property (nonatomic, weak) ZFPlayerController *player;
- (void)setPreviewValue:(float)value;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,108 @@
//
// GKDYVideoPreviewView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoPreviewView.h"
#import <ZFPlayer/ZFAVPlayerManager.h>
@interface ZFAVPlayerManager (GKCategory)
- (void)thumbnailImageAtTime:(NSTimeInterval)time completion:(void(^)(UIImage *_Nullable image))completion;
@end
@implementation ZFAVPlayerManager (GKCategory)
- (void)thumbnailImageAtTime:(NSTimeInterval)time completion:(void (^)(UIImage * _Nullable))completion {
CMTime expectedTime = CMTimeMakeWithSeconds(time, NSEC_PER_SEC);
AVAssetImageGenerator *imageGenerator = [self valueForKey:@"imageGenerator"];
[imageGenerator generateCGImagesAsynchronouslyForTimes:@[[NSValue valueWithCMTime:expectedTime]] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {
if (image) {
UIImage *finalImage = [UIImage imageWithCGImage:image];
!completion ?: completion(finalImage);
}else {
!completion ?: completion(nil);
}
}];
}
@end
@interface GKDYVideoPreviewView()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *timeLabel;
@end
@implementation GKDYVideoPreviewView
- (instancetype)init {
if (self = [super init]) {
[self initUI];
}
return self;
}
- (void)initUI {
[self addSubview:self.imageView];
[self addSubview:self.timeLabel];
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self);
make.height.mas_equalTo(120*9/16);
}];
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.imageView.mas_bottom).offset(20);
make.centerX.equalTo(self);
}];
}
- (void)setPreviewValue:(float)value {
NSString *currentTime = [NSString convertTimeSecond:self.player.totalTime * value];
NSString *totalTime = [NSString convertTimeSecond:self.player.totalTime];
self.timeLabel.text = [NSString stringWithFormat:@"%@ / %@", currentTime, totalTime];
ZFAVPlayerManager *manager = (ZFAVPlayerManager *)self.player.currentPlayerManager;
@weakify(self);
[manager thumbnailImageAtTime:self.player.totalTime * value completion:^(UIImage * _Nullable image) {
if (image) {
@strongify(self);
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
}];
}
#pragma mark - Lazy
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
_imageView.contentMode = UIViewContentModeScaleAspectFill;
_imageView.layer.cornerRadius = 5;
_imageView.layer.masksToBounds = YES;
}
return _imageView;
}
- (UILabel *)timeLabel {
if (!_timeLabel) {
_timeLabel = [[UILabel alloc] init];
_timeLabel.font = [UIFont systemFontOfSize:15];
_timeLabel.textColor = UIColor.whiteColor;
}
return _timeLabel;
}
@end

View File

@ -0,0 +1,31 @@
//
// GKDYVideoScrollView.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <GKVideoScrollView/GKVideoScrollView.h>
NS_ASSUME_NONNULL_BEGIN
@class GKDYVideoScrollView;
@protocol GKDYVideoScrollViewDelegate <NSObject, GKVideoScrollViewDelegate>
@optional
- (void)scrollView:(GKDYVideoScrollView *)scrollView didPanWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd;
@end
@interface GKDYVideoScrollView : GKVideoScrollView
@property (nonatomic, weak) id<GKDYVideoScrollViewDelegate> delegate;
- (void)addPanGesture;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,126 @@
//
// GKDYVideoScrollView.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/17.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoScrollView.h"
#import "GKDYPanGestureRecognizer.h"
@interface GKDYVideoScrollView()<UIGestureRecognizerDelegate, UIScrollViewDelegate>
@property (nonatomic, strong) GKDYPanGestureRecognizer *panGesture;
//
@property (nonatomic, assign) CGFloat startLocationY;
@property (nonatomic, weak) id<GKDYVideoScrollViewDelegate> userDelegate;
@end
@implementation GKDYVideoScrollView
@dynamic delegate;
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
if (CGRectEqualToRect(frame, CGRectZero)) {
self.frame = CGRectMake(0, 0, HBScreenSize.width, HBScreenSize.height);
}
self.contentSize = CGSizeMake(0, self.frame.size.height);
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
if (self.contentSize.height == 0) {
self.contentSize = CGSizeMake(self.bounds.size.width, self.bounds.size.height);
}
}
- (void)addPanGesture {
[self addGestureRecognizer:self.panGesture];
}
- (void)setDelegate:(id<GKDYVideoScrollViewDelegate>)delegate {
[super setDelegate:delegate];
if (delegate) {
self.userDelegate = delegate;
}else {
self.userDelegate = nil;
}
}
#pragma mark - Gesture
- (void)handlePanGesture:(GKDYPanGestureRecognizer *)panGesture {
if (self.currentIndex == 0) {
CGPoint location = [panGesture locationInView:panGesture.view];
switch (panGesture.state) {
case UIGestureRecognizerStateBegan: {
self.startLocationY = location.y;
}
break;
case UIGestureRecognizerStateChanged: {
if (panGesture.direction == GKDYPanGestureRecognizerDirectionVertical) {
// distance > 0
CGFloat distance = ceil(location.y) - ceil(self.startLocationY);
if (distance > 0) { // distance>0
self.panGestureRecognizer.enabled = NO;
}
if (self.panGestureRecognizer.enabled == NO) {
[self didPanWithDistance:distance isEnd:NO];
}
}
}
break;
case UIGestureRecognizerStateFailed:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded: {
if (self.panGestureRecognizer.enabled == NO) {
CGFloat distance = location.y - self.startLocationY;
[self didPanWithDistance:distance isEnd:YES];
self.panGestureRecognizer.enabled = YES;
}
}
break;
default:
break;
}
[panGesture setTranslation:CGPointZero inView:panGesture.view];
}
}
//
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (otherGestureRecognizer.view == self) {
return YES;
}
return NO;
}
- (void)didPanWithDistance:(CGFloat)distance isEnd:(BOOL)isEnd {
if ([self.userDelegate respondsToSelector:@selector(scrollView:didPanWithDistance:isEnd:)]) {
[self.userDelegate scrollView:self didPanWithDistance:distance isEnd:isEnd];
}
}
#pragma mark - Lazy
- (GKDYPanGestureRecognizer *)panGesture {
if (!_panGesture) {
_panGesture = [[GKDYPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
_panGesture.delegate = self;
_panGesture.direction = GKDYPanGestureRecognizerDirectionVertical;
}
return _panGesture;
}
@end

View File

@ -0,0 +1,33 @@
//
// GKDYVideoSlider.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <GKSliderView/GKSliderView.h>
#import <ZFPlayer/ZFPlayer.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoSlider : UIView
@property (nonatomic, strong) GKSliderView *sliderView;
@property (nonatomic, copy) void(^slideBlock)(BOOL isDragging);
@property (nonatomic, weak) ZFPlayerController *player;
- (void)updateCurrentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime;
- (void)showSmallSlider;
- (void)showLargeSlider;
- (void)showLoading;
- (void)hideLoading;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,212 @@
//
// GKDYVideoSlider.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoSlider.h"
#import <Masonry/Masonry.h>
@interface GKDYVideoSlider()<GKSliderViewPreviewDelegate>
@property (nonatomic, assign) CGFloat startLocationX;
@property (nonatomic, assign) float startValue;
@property (nonatomic, assign) BOOL isDragging;
@property (nonatomic, assign) BOOL isSeeking;
@property (nonatomic, assign) NSTimeInterval currentTime;
@property (nonatomic, assign) NSTimeInterval totalTime;
@end
@implementation GKDYVideoSlider
- (instancetype)init {
if (self = [super init]) {
[self initUI];
}
return self;
}
- (void)initUI {
[self addSubview:self.sliderView];
[self.sliderView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self);
make.height.mas_offset(4);
}];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self addGestureRecognizer:panGesture];
[self showSmallSlider];
}
- (void)updateCurrentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
self.currentTime = currentTime;
self.totalTime = totalTime;
if (self.isDragging) return;
if (self.isSeeking) return;
CGFloat value = totalTime == 0 ? 0 : currentTime / totalTime;
self.sliderView.value = value;
}
- (void)showLoading {
dispatch_async(dispatch_get_main_queue(), ^{
[self.sliderView showLineLoading];
});
}
- (void)hideLoading {
dispatch_async(dispatch_get_main_queue(), ^{
[self.sliderView hideLineLoading];
});
}
- (void)handlePan:(UIPanGestureRecognizer *)gesture {
CGPoint location = [gesture locationInView:gesture.view];
switch (gesture.state) {
case UIGestureRecognizerStateBegan: {
self.startLocationX = location.x;
self.startValue = self.sliderView.value;
if (self.sliderView.preview) {
self.sliderView.preview.hidden = NO;
}
self.isDragging = YES;
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showSmallSlider) object:nil];
[self showLargeSlider];
!self.slideBlock ?: self.slideBlock(self.isDragging);
}
break;
case UIGestureRecognizerStateChanged: {
CGFloat diff = location.x - self.startLocationX;
CGFloat progress = self.startValue + diff / gesture.view.frame.size.width;
if (progress < 0) progress = 0;
if (progress > 1) progress = 1;
self.sliderView.value = progress;
if (self.sliderView.preview && [self.sliderView.previewDelegate respondsToSelector:@selector(sliderView:preview:valueChanged:)]) {
[self.sliderView.previewDelegate sliderView:self.sliderView preview:self.sliderView.preview valueChanged:self.sliderView.value];
}
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showSmallSlider) object:nil];
[self showDragSlider];
}
break;
case UIGestureRecognizerStateFailed:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded: {
self.isDragging = NO;
if (self.sliderView.preview) {
self.sliderView.preview.hidden = YES;
}
[self showLargeSlider];
[self performSelector:@selector(showSmallSlider) withObject:nil afterDelay:3.0f];
!self.slideBlock ?: self.slideBlock(self.isDragging);
[self seekTo:self.sliderView.value];
}
break;
default:
break;
}
}
- (void)seekTo:(float)value {
NSTimeInterval time = self.totalTime * value;
NSLog(@"seekTo: %f",time);
self.isSeeking = YES;
@weakify(self);
[self.player seekToTime:time completionHandler:^(BOOL finished) {
@strongify(self);
weak_self.isSeeking = NO;
}];
}
#pragma mark - Slider
- (void)showSmallSlider {
CGRect frame = self.sliderView.sliderBtn.frame;
frame.size = CGSizeMake(4, 4);
self.sliderView.sliderBtn.frame = frame;
self.sliderView.sliderBtn.layer.cornerRadius = 2;
self.sliderView.sliderHeight = 1;
[self.sliderView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(4);
}];
self.sliderView.bgCornerRadius = 0;
}
- (void)showLargeSlider {
CGRect frame = self.sliderView.sliderBtn.frame;
frame.size = CGSizeMake(8, 8);
self.sliderView.sliderBtn.frame = frame;
self.sliderView.sliderBtn.layer.cornerRadius = 4;
self.sliderView.sliderHeight = 2;
[self.sliderView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(8);
}];
self.sliderView.bgCornerRadius = 1;
}
- (void)showDragSlider {
CGRect frame = self.sliderView.sliderBtn.frame;
frame.size = CGSizeMake(8, 16);
self.sliderView.sliderBtn.frame = frame;
self.sliderView.sliderBtn.layer.cornerRadius = 4;
self.sliderView.sliderHeight = 10;
[self.sliderView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(16);
}];
self.sliderView.bgCornerRadius = 5;
}
#pragma mark - GKSliderViewPreviewDelegate
- (UIView *)sliderViewSetupPreview:(GKSliderView *)sliderView {
GKSliderButton *preview = [[GKSliderButton alloc] init];
NSString *currentTime = [NSString convertTimeSecond:self.currentTime];
NSString *totalTime = [NSString convertTimeSecond:self.totalTime];
[preview setTitle:[NSString stringWithFormat:@"%@ / %@", currentTime, totalTime] forState:UIControlStateNormal];
[preview setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
preview.titleLabel.font = [UIFont systemFontOfSize:15];
[preview sizeToFit];
CGRect frame = preview.frame;
frame.size.width += 10;
preview.frame = frame;
return preview;
}
- (CGFloat)sliderViewPreviewMargin:(GKSliderView *)sliderView {
return 60;
}
- (void)sliderView:(GKSliderView *)sliderView preview:(UIView *)preview valueChanged:(float)value {
GKSliderButton *button = (GKSliderButton *)preview;
NSString *currentTime = [NSString convertTimeSecond:self.totalTime * value];
NSString *totalTime = [NSString convertTimeSecond:self.totalTime];
[button setTitle:[NSString stringWithFormat:@"%@ / %@", currentTime, totalTime] forState:UIControlStateNormal];
}
#pragma mark - Lazy
- (GKSliderView *)sliderView {
if (!_sliderView) {
_sliderView = [[GKSliderView alloc] init];
_sliderView.isSliderAllowTapped = NO;
_sliderView.sliderHeight = 2;
_sliderView.maximumTrackTintColor = [UIColor lightGrayColor];
_sliderView.minimumTrackTintColor = HBColor.color_FF0049;
_sliderView.sliderBtn.layer.masksToBounds = YES;
_sliderView.sliderBtn.backgroundColor = HBColor.color_FF0049;
_sliderView.isPreviewChangePosition = NO;
_sliderView.userInteractionEnabled = NO;
_sliderView.previewDelegate = self;
}
return _sliderView;
}
@end

View File

@ -0,0 +1,27 @@
//
// GKDYVideoStatusBar.h
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GKDYVideoStatusBar : UIView
// 刷新时间默认3s
@property (nonatomic, assign) NSTimeInterval refreshTime;
// 网络状态
@property (nonatomic, copy) NSString *network;
- (void)startTimer;
- (void)destoryTimer;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,345 @@
//
// GKDYVideoStatusBar.m
// GKDYVideo
//
// Created by QuintGao on 2023/3/22.
// Copyright © 2023 QuintGao. All rights reserved.
//
#import "GKDYVideoStatusBar.h"
#define UIColorFromHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
@interface GKDYVideoTimerTarget : NSProxy
@property (nonatomic, weak) id target;
@end
@implementation GKDYVideoTimerTarget
+ (instancetype)proxyWithTarget:(id)target {
GKDYVideoTimerTarget *proxy = [GKDYVideoTimerTarget alloc];
proxy.target = target;
return proxy;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
NSMethodSignature *signature = nil;
if ([self.target respondsToSelector:sel]) {
signature = [self.target methodSignatureForSelector:sel];
}else {
/// void object selector arg
/// signaturecrash
signature = [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
if ([self.target respondsToSelector:invocation.selector]) {
[invocation invokeWithTarget:self.target];
}
}
@end
@interface GKDYVideoStatusBar()
///
@property (nonatomic, strong) UILabel *dateLabel;
///
@property (nonatomic, strong) UIView *batteryView;
///
@property (nonatomic, strong) UIImageView *batteryImageView;
///
@property (nonatomic, strong) CAShapeLayer *batteryLayer;
///
@property (nonatomic, strong) CAShapeLayer *batteryBoundLayer;
///
@property (nonatomic, strong) CAShapeLayer *batteryPositiveLayer;
///
@property (nonatomic, strong) UILabel *batteryLabel;
///
@property (nonatomic, strong) UILabel *networkLabel;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@end
@implementation GKDYVideoStatusBar
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
- (void)dealloc {
[self destoryTimer];
}
- (void)setup {
self.refreshTime = 3.0f;
///
[self addSubview:self.dateLabel];
///
[self addSubview:self.batteryView];
[self.batteryView.layer addSublayer:self.batteryBoundLayer];
[self.batteryView.layer addSublayer:self.batteryPositiveLayer];
[self.batteryView.layer addSublayer:self.batteryLayer];
[self.batteryView addSubview:self.batteryImageView];
[self addSubview:self.batteryLabel];
[self addSubview:self.networkLabel];
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelDidChangeNotification:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryStateDidChangeNotification:) name:UIDeviceBatteryStateDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChangeNotification:) name:NSCurrentLocaleDidChangeNotification object:nil];
}
- (void)layoutSubviews {
[self.dateLabel sizeToFit];
[self.networkLabel sizeToFit];
[self.batteryLabel sizeToFit];
CGRect frame = self.dateLabel.frame;
CGPoint center = self.dateLabel.center;
// dateLabel
frame.size.height = 16;
self.dateLabel.frame = frame;
center = self.center;
self.dateLabel.center = center;
// batteryView
frame = self.batteryView.frame;
frame.origin.x = self.bounds.size.width - 35;
frame.size.width = 22;
frame.size.height = 10;
self.batteryView.frame = frame;
center = self.batteryView.center;
center.y = self.center.y;
self.batteryView.center = center;
// batteryLabel
frame = self.batteryLabel.frame;
frame.origin.x = CGRectGetMinX(self.batteryView.frame) - 5 - frame.size.width;
frame.size.height = 16;
self.batteryLabel.frame = frame;
center = self.batteryLabel.center;
center.y = self.batteryView.center.y;
self.batteryLabel.center = center;
// networkLabel
frame = self.networkLabel.frame;
frame.origin.x = 10;
frame.size.width = frame.size.width + 13;
frame.size.height = 14;
self.networkLabel.frame = frame;
center = self.networkLabel.center;
center.y = self.batteryView.center.y;
self.networkLabel.center = center;
}
- (void)batteryLevelDidChangeNotification:(NSNotification *)noti {
[self updateUI];
}
- (void)batteryStateDidChangeNotification:(NSNotification *)noti {
[self updateUI];
}
- (void)localeDidChangeNotification:(NSNotification *)noti {
[self.dateFormatter setLocale:NSLocale.currentLocale];
[self updateUI];
}
- (void)setNetwork:(NSString *)network {
_network = network;
self.networkLabel.text = network;
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)startTimer {
if (self.timer) return;
self.timer = [NSTimer timerWithTimeInterval:self.refreshTime target:[GKDYVideoTimerTarget proxyWithTarget:self] selector:@selector(updateUI) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
[self.timer fire];
}
- (void)destoryTimer {
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
}
#pragma mark - update UI
- (void)updateUI {
[self updateDate];
[self updateBattery];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)updateDate {
NSMutableString *dateString = [[NSMutableString alloc] initWithString:[self.dateFormatter stringFromDate:[NSDate date]]];
NSRange amRange = [dateString rangeOfString:[self.dateFormatter AMSymbol]];
NSRange pmRange = [dateString rangeOfString:[self.dateFormatter PMSymbol]];
if (amRange.location != NSNotFound) {
[dateString deleteCharactersInRange:amRange];
}else if (pmRange.location != NSNotFound) {
[dateString deleteCharactersInRange:pmRange];
}
self.dateLabel.text = dateString;
}
- (void)updateBattery {
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
CGFloat batteryLevel = [UIDevice currentDevice].batteryLevel;
/// -1
if (batteryLevel < 0) { batteryLevel = 1.0; }
CGRect rect = CGRectMake(1.5, 1.5, (20-3)*batteryLevel, 10-3);
UIBezierPath *batteryPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:2];
UIColor *batteryColor;
UIDeviceBatteryState batteryState = [UIDevice currentDevice].batteryState;
if (batteryState == UIDeviceBatteryStateCharging || batteryState == UIDeviceBatteryStateFull) { ///
self.batteryImageView.hidden = NO;
} else {
self.batteryImageView.hidden = YES;
}
if (@available(iOS 9.0, *)) {
if ([NSProcessInfo processInfo].lowPowerModeEnabled) { ///
batteryColor = UIColorFromHex(0xF9CF0E);
} else {
if (batteryState == UIDeviceBatteryStateCharging || batteryState == UIDeviceBatteryStateFull) { ///
batteryColor = UIColorFromHex(0x37CB46);
} else if (batteryLevel <= 0.2) { ///
batteryColor = UIColorFromHex(0xF02C2D);
} else { ///
batteryColor = [UIColor whiteColor];
}
}
} else {
if (batteryState == UIDeviceBatteryStateCharging || batteryState == UIDeviceBatteryStateFull) { ///
batteryColor = UIColorFromHex(0x37CB46);
} else if (batteryLevel <= 0.2) { ///
batteryColor = UIColorFromHex(0xF02C2D);
} else { ///
batteryColor = [UIColor whiteColor];
}
}
self.batteryLayer.strokeColor = [UIColor clearColor].CGColor;
self.batteryLayer.path = batteryPath.CGPath;
self.batteryLayer.fillColor = batteryColor.CGColor;
self.batteryLabel.text = [NSString stringWithFormat:@"%.0f%%", batteryLevel*100];
}
#pragma mark - getter
- (UILabel *)dateLabel {
if (!_dateLabel) {
_dateLabel = [[UILabel alloc] init];
_dateLabel.bounds = CGRectMake(0, 0, 100, 16);
_dateLabel.textColor = UIColor.whiteColor;
_dateLabel.font = [UIFont systemFontOfSize:12];
}
return _dateLabel;
}
- (NSDateFormatter *)dateFormatter {
if (!_dateFormatter) {
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setLocale:NSLocale.currentLocale];
_dateFormatter.dateStyle = NSDateFormatterNoStyle;
_dateFormatter.timeStyle = NSDateFormatterShortStyle;
}
return _dateFormatter;
}
- (UIView *)batteryView {
if (!_batteryView) {
_batteryView = [[UIView alloc] init];
}
return _batteryView;
}
- (UIImageView *)batteryImageView {
if (!_batteryImageView) {
_batteryImageView = [[UIImageView alloc] init];
_batteryImageView.bounds = CGRectMake(0, 0, 8, 12);
_batteryImageView.center = CGPointMake(10, 5);
_batteryImageView.image = [UIImage imageNamed:@"icon_battery_lightning"];
}
return _batteryImageView;
}
- (CAShapeLayer *)batteryLayer {
if (!_batteryLayer) {
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
CGFloat batteryLevel = [UIDevice currentDevice].batteryLevel;
UIBezierPath *batteryPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(1.5, 1.5, (20-3)*batteryLevel, 10-3) cornerRadius:2];
_batteryLayer = [CAShapeLayer layer];
_batteryLayer.lineWidth = 1;
_batteryLayer.strokeColor = [UIColor clearColor].CGColor;
_batteryLayer.path = batteryPath.CGPath;
_batteryLayer.fillColor = [UIColor whiteColor].CGColor;
}
return _batteryLayer;
}
- (CAShapeLayer *)batteryBoundLayer {
if (!_batteryBoundLayer) {
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 20, 10) cornerRadius:2.5];
_batteryBoundLayer = [CAShapeLayer layer];
_batteryBoundLayer.lineWidth = 1;
_batteryBoundLayer.strokeColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8].CGColor;
_batteryBoundLayer.path = bezierPath.CGPath;
_batteryBoundLayer.fillColor = nil;
}
return _batteryBoundLayer;
}
- (CAShapeLayer *)batteryPositiveLayer {
if (!_batteryPositiveLayer) {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(22, 3, 1, 3) byRoundingCorners:(UIRectCornerTopRight|UIRectCornerBottomRight) cornerRadii:CGSizeMake(2, 2)];
_batteryPositiveLayer = [CAShapeLayer layer];
_batteryPositiveLayer.lineWidth = 0.5;
_batteryPositiveLayer.strokeColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8].CGColor;
_batteryPositiveLayer.path = path.CGPath;
_batteryPositiveLayer.fillColor = [[UIColor whiteColor] colorWithAlphaComponent:0.8].CGColor;
}
return _batteryPositiveLayer;
}
- (UILabel *)batteryLabel {
if (!_batteryLabel) {
_batteryLabel = [[UILabel alloc] init];
_batteryLabel.textColor = [UIColor whiteColor];
_batteryLabel.font = [UIFont systemFontOfSize:11];
_batteryLabel.textAlignment = NSTextAlignmentRight;
}
return _batteryLabel;
}
- (UILabel *)networkLabel {
if (!_networkLabel) {
_networkLabel = [[UILabel alloc] init];
_networkLabel.layer.cornerRadius = 7;
_networkLabel.layer.borderWidth = 1;
_networkLabel.layer.borderColor = [UIColor lightGrayColor].CGColor;
_networkLabel.textColor = [UIColor whiteColor];
_networkLabel.font = [UIFont systemFontOfSize:9];
_networkLabel.textAlignment = NSTextAlignmentCenter;
_networkLabel.text = @"WIFI";
}
return _networkLabel;
}
@end

View File

@ -8,32 +8,32 @@
#import <Foundation/Foundation.h>
/// 网络请求地址
extern NSString *const HBBaseUrlString;
extern NSString * _Nonnull const HBBaseUrlString;
/// 保存设备唯一值key
extern NSString *const HBIdentifierForVendorKey;
extern NSString * _Nonnull const HBIdentifierForVendorKey;
/// 用来保存用户是不是主动登录成功了,可以用来判断是否登录
extern NSString *const HBCustomerLoginSuccessKey;
extern NSString * _Nonnull const HBCustomerLoginSuccessKey;
/// 保存网络请求的Token
extern NSString *const HBNetWorkingTokenKey;
extern NSString * _Nonnull const HBNetWorkingTokenKey;
/// 保存网络请求的Token
extern NSString *const HBCustomerIdKey;
extern NSString * _Nonnull const HBCustomerIdKey;
/// 搜索历史key
extern NSString *const HBSearchHistoryKey;
extern NSString * _Nonnull const HBSearchHistoryKey;
/// 播放界面离开 通知播放器暂停
extern NSString *const HBPlayerPuaseKey;
extern NSString * _Nonnull const HBPlayerPuaseKey;
/// 推送详情使用
extern NSString *const HBNotificationOpenActionIdentifier;
extern NSString *const HBNotificationOpenCategoryIdentifier;
extern NSString * _Nonnull const HBNotificationOpenActionIdentifier;
extern NSString * _Nonnull const HBNotificationOpenCategoryIdentifier;
/// 第一次启动存储
extern NSString *const HBNotFirstStartKey;
extern NSString * _Nonnull const HBNotFirstStartKey;
/// 通知
FOUNDATION_EXPORT NSNotificationName _Nonnull const HBUpdateUserInfoNotification;

View File

@ -8,7 +8,7 @@
#import "HBCommonKeys.h"
///
NSString *const HBBaseUrlString = @"https://hongkongapi.peonytv.com";
NSString *const HBBaseUrlString = @"https://test-api.peonytv.com";
NSString *const HBIdentifierForVendorKey = @"HBIdentifierForVendorKey";

View File

@ -8,13 +8,13 @@
#import <Foundation/Foundation.h>
/// appsflyer dev key
extern NSString *const HBAppsFlyerDevKey;
extern NSString * _Nonnull const HBAppsFlyerDevKey;
/// appsflyer app id
extern NSString *const HBAppsFlyerAppID;
extern NSString * _Nonnull const HBAppsFlyerAppID;
/// applovin key
extern NSString *const HBAppLovinKey;
extern NSString * _Nonnull const HBAppLovinKey;
/// Panlge app id
extern NSString *const HBPangleID;
extern NSString * _Nonnull const HBPangleID;

View File

@ -19,10 +19,10 @@ NS_ASSUME_NONNULL_BEGIN
*/
/// 多语言 userdefine key
extern NSString *const HBMultiLanguageKey;
extern NSString * _Nonnull const HBMultiLanguageKey;
/// 多语言 查询系统首选语言 key
extern NSString *const HBLocaleLanguageKey;
extern NSString * _Nonnull const HBLocaleLanguageKey;
/// 多语言发发现切换使用通知的key
FOUNDATION_EXPORT NSNotificationName _Nonnull const HBMultiLanguageChangeNotification;