Skip to content

Commit

Permalink
优化转场动画,解决转场过程中的闪烁
Browse files Browse the repository at this point in the history
  • Loading branch information
JmoVxia committed May 17, 2024
1 parent 5c55872 commit 3ff1ea8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 82 deletions.
2 changes: 1 addition & 1 deletion CLPlayer.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = 'CLPlayer'
s.version = '2.0.5'
s.version = '2.0.6'
s.summary = 'Swift版自定义AVPlayer'
s.description = <<-DESC
CLPlayer是基于系统AVPlayer封装的视频播放器.
Expand Down
123 changes: 44 additions & 79 deletions CLPlayer/CLFullScreenController/CLAnimationTransitioning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import SnapKit
import UIKit

extension CLAnimationTransitioning {
enum CLAnimationType {
enum AnimationType {
case present
case dismiss
}

enum CLAnimationOrientation {
enum AnimationOrientation {
case left
case right
case fullRight
Expand All @@ -30,24 +30,27 @@ class CLAnimationTransitioning: NSObject {
}
}()

private weak var player: CLPlayerView?
private weak var playerView: CLPlayerView?

private weak var parentView: UIStackView?
private weak var parentStackView: UIStackView?

private var centerInParent: CGPoint = .zero
private var initialCenter: CGPoint = .zero

private var originSize: CGSize = .zero
private var finalCenter: CGPoint = .zero

private var orientation: CLAnimationOrientation = .left
private var initialBounds: CGRect = .zero

var animationType: CLAnimationType = .present
private var animationOrientation: AnimationOrientation = .left

init(playView: CLPlayerView, orientation: CLAnimationOrientation) {
player = playView
self.orientation = orientation
parentView = playView.superview as? UIStackView
centerInParent = playView.center
originSize = playView.frame.size
var animationType: AnimationType = .present

init(playerView: CLPlayerView, animationOrientation: AnimationOrientation) {
self.playerView = playerView
self.animationOrientation = animationOrientation
parentStackView = playerView.superview as? UIStackView
initialBounds = playerView.bounds
initialCenter = playerView.center
finalCenter = playerView.convert(initialCenter, to: nil)
}
}

Expand All @@ -57,97 +60,59 @@ extension CLAnimationTransitioning: UIViewControllerAnimatedTransitioning {
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let playView = player else { return }
guard let playerView = playerView else { return }

if animationType == .present {
guard let toView = transitionContext.view(forKey: .to) else { return }
guard let fromController = transitionContext.viewController(forKey: .from) else { return }

let fromCenter = transitionContext.containerView.convert(playView.center, from: playView.superview)
let fromSize = transitionContext.containerView.convert(playView.frame, from: nil).size
guard let toController = transitionContext.viewController(forKey: .to) as? CLFullScreenController else { return }

let startCenter = transitionContext.containerView.convert(initialCenter, from: playerView)
transitionContext.containerView.addSubview(toView)
toView.addSubview(playView)

if orientation == .left,
!(fromController.shouldAutorotate && fromController.supportedInterfaceOrientations.contains(.landscapeLeft))
{
toView.transform = .init(rotationAngle: -Double.pi * 0.5)
} else if orientation == .right,
!(fromController.shouldAutorotate && fromController.supportedInterfaceOrientations.contains(.landscapeRight))
{
toView.transform = .init(rotationAngle: Double.pi * 0.5)
} else if orientation == .fullRight {
toView.transform = .init(rotationAngle: -Double.pi * 0.5)
}

toView.snp.remakeConstraints { make in
make.center.equalTo(fromCenter)
make.size.equalTo(fromSize)
}
playView.snp.remakeConstraints { make in
make.edges.equalToSuperview()
}
transitionContext.containerView.setNeedsLayout()
transitionContext.containerView.layoutIfNeeded()
toController.mainStackView.addArrangedSubview(playerView)
toView.bounds = initialBounds
toView.center = startCenter
toView.transform = .init(rotationAngle: toController.isKind(of: CLFullScreenLeftController.self) ? Double.pi * 0.5 : Double.pi * -0.5)

toView.snp.updateConstraints { make in
make.center.equalTo(transitionContext.containerView.center)
make.size.equalTo(transitionContext.containerView.bounds.size)
}
if #available(iOS 11.0, *) {
playView.contentView.animationLayout(safeAreaInsets: keyWindow?.safeAreaInsets ?? .zero, to: .fullScreen)
playerView.contentView.animationLayout(safeAreaInsets: keyWindow?.safeAreaInsets ?? .zero, to: .fullScreen)
} else {
playView.contentView.animationLayout(safeAreaInsets: .zero, to: .fullScreen)
playerView.contentView.animationLayout(safeAreaInsets: .zero, to: .fullScreen)
}
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .layoutSubviews, animations: {
toView.transform = .identity
transitionContext.containerView.setNeedsLayout()
transitionContext.containerView.layoutIfNeeded()
playView.contentView.setNeedsLayout()
playView.contentView.layoutIfNeeded()
toView.bounds = transitionContext.containerView.bounds
toView.center = transitionContext.containerView.center
playerView.contentView.setNeedsLayout()
playerView.contentView.layoutIfNeeded()
}) { _ in
toView.transform = .identity
toView.bounds = transitionContext.containerView.bounds
toView.center = transitionContext.containerView.center
transitionContext.completeTransition(true)
UIViewController.attemptRotationToDeviceOrientation()
}
} else {
guard let parentView = parentView else { return }
guard let parentStackView = parentStackView else { return }
guard let fromView = transitionContext.view(forKey: .from) else { return }
guard let toView = transitionContext.view(forKey: .to) else { return }

toView.frame = transitionContext.containerView.bounds

let fromCenter = CGPoint(x: toView.frame.width * 0.5, y: toView.frame.height * 0.5)
let fromSize = transitionContext.containerView.convert(playView.frame, from: nil).size

transitionContext.containerView.addSubview(toView)
transitionContext.containerView.addSubview(fromView)
toView.frame = transitionContext.containerView.bounds

fromView.snp.remakeConstraints { make in
make.center.equalTo(fromCenter)
make.size.equalTo(fromSize)
}

transitionContext.containerView.setNeedsLayout()
transitionContext.containerView.layoutIfNeeded()

let center = transitionContext.containerView.convert(centerInParent, from: parentView)
fromView.snp.updateConstraints { make in
make.center.equalTo(center)
make.size.equalTo(originSize)
}

playView.contentView.animationLayout(safeAreaInsets: .zero, to: .small)

playerView.contentView.animationLayout(safeAreaInsets: .zero, to: .small)
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: .layoutSubviews, animations: {
fromView.transform = .identity
transitionContext.containerView.setNeedsLayout()
transitionContext.containerView.layoutIfNeeded()
playView.contentView.setNeedsLayout()
playView.contentView.layoutIfNeeded()
fromView.center = self.finalCenter
fromView.bounds = self.initialBounds
playerView.contentView.setNeedsLayout()
playerView.contentView.layoutIfNeeded()
}) { _ in
fromView.transform = .identity
fromView.center = self.finalCenter
fromView.bounds = self.initialBounds
parentStackView.addArrangedSubview(playerView)
fromView.removeFromSuperview()
parentView.addArrangedSubview(playView)
transitionContext.completeTransition(true)
UIViewController.attemptRotationToDeviceOrientation()
}
Expand Down
17 changes: 17 additions & 0 deletions CLPlayer/CLFullScreenController/CLFullScreenController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ class CLFullScreenController: UIViewController {
}

deinit {}

private(set) lazy var mainStackView: UIStackView = {
let view = UIStackView()
view.isUserInteractionEnabled = true
view.axis = .horizontal
view.distribution = .fill
view.alignment = .fill
view.insetsLayoutMarginsFromSafeArea = false
view.isLayoutMarginsRelativeArrangement = true
view.layoutMargins = .zero
view.spacing = 0
return view
}()
}

// MARK: - JmoVxia---生命周期
Expand Down Expand Up @@ -56,6 +69,10 @@ extension CLFullScreenController {
private extension CLFullScreenController {
func initUI() {
view.backgroundColor = .black
view.addSubview(mainStackView)
mainStackView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions CLPlayer/CLPlayerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -362,15 +362,15 @@ private extension CLPlayerView {
})
}

func presentWithOrientation(_ orientation: CLAnimationTransitioning.CLAnimationOrientation) {
func presentWithOrientation(_ orientation: CLAnimationTransitioning.AnimationOrientation) {
guard Thread.isMainThread else { return DispatchQueue.main.async { self.presentWithOrientation(orientation) } }
guard superview != nil else { return }
guard fullScreenController == nil else { return }
guard contentView.screenState == .small else { return }
guard let rootViewController = keyWindow?.rootViewController else { return }
contentView.screenState = .animating

animationTransitioning = CLAnimationTransitioning(playView: self, orientation: orientation)
animationTransitioning = CLAnimationTransitioning(playerView: self, animationOrientation: orientation)

fullScreenController = orientation == .right ? CLFullScreenLeftController() : CLFullScreenRightController()
fullScreenController?.transitioningDelegate = self
Expand Down

0 comments on commit 3ff1ea8

Please sign in to comment.