Fix layout in gallery detail view.

This commit is contained in:
Matthew Chen 2021-08-11 02:15:07 -03:00
parent f3eea69045
commit 74ced565bd
2 changed files with 58 additions and 23 deletions

View File

@ -24,7 +24,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface MediaDetailViewController () <UIScrollViewDelegate,
UIGestureRecognizerDelegate,
PlayerProgressBarDelegate,
OWSVideoPlayerDelegate>
OWSVideoPlayerDelegate,
LoopingVideoViewDelegate>
@property (nonatomic) UIScrollView *scrollView;
@property (nonatomic) UIView *mediaView;
@ -95,16 +96,22 @@ NS_ASSUME_NONNULL_BEGIN
- (void)viewWillAppear:(BOOL)animated
{
OWSAssertIsOnMainThread();
[super viewWillAppear:animated];
[self resetMediaFrame];
[self updateZoomScaleAndConstraints];
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}
- (void)viewDidAppear:(BOOL)animated
{
OWSAssertIsOnMainThread();
[super viewDidAppear:animated];
if (self.isVideo && self.shouldAutoPlayVideo && !self.hasAutoPlayedVideo) {
[self playVideo];
self.hasAutoPlayedVideo = YES;
}
@ -263,6 +270,7 @@ NS_ASSUME_NONNULL_BEGIN
LoopingVideoView *view = [[LoopingVideoView alloc] init];
view.video = video;
return view;
}
@ -282,6 +290,7 @@ NS_ASSUME_NONNULL_BEGIN
VideoPlayerView *playerView = [VideoPlayerView new];
playerView.player = player.avPlayer;
return playerView;
}
@ -403,26 +412,21 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
CGSize newMediaSize
= CGSizeMake(MIN(scrollViewSize.width, mediaSize.width), MIN(scrollViewSize.height, mediaSize.height));
OWSAssertDebug(newMediaSize.width > 0);
OWSAssertDebug(newMediaSize.height > 0);
CGFloat scaleWidth = scrollViewSize.width / newMediaSize.width;
CGFloat scaleHeight = scrollViewSize.height / newMediaSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
CGFloat scaleWidth = scrollViewSize.width / mediaSize.width;
CGFloat scaleHeight = scrollViewSize.height / mediaSize.height;
CGFloat minScale = MIN(1, MIN(scaleWidth, scaleHeight));
// UIScrollView transforms its content.
// Therefore its subviews operate in a different coordinate system.
// These constraints should reflect the _transformed_ frame of the mediaView,
// so we need to scale by the minScale.
CGSize newMediaSizeScaled = CGSizeScale(newMediaSize, minScale);
CGFloat yOffset = MAX(0, (scrollViewSize.height - newMediaSizeScaled.height) / 2);
CGFloat xOffset = MAX(0, (scrollViewSize.width - newMediaSizeScaled.width) / 2);
CGSize newMediaSize = CGSizeScale(mediaSize, minScale);
CGFloat yOffset = MAX(0, (scrollViewSize.height - newMediaSize.height) / 2);
CGFloat xOffset = MAX(0, (scrollViewSize.width - newMediaSize.width) / 2);
self.mediaViewTopConstraint.constant = yOffset;
self.mediaViewBottomConstraint.constant = yOffset;
self.mediaViewLeadingConstraint.constant = xOffset;
self.mediaViewTrailingConstraint.constant = -xOffset;
self.mediaViewTrailingConstraint.constant = xOffset;
CGFloat maxScale = minScale * 8;
self.scrollView.minimumZoomScale = minScale;
@ -546,6 +550,16 @@ NS_ASSUME_NONNULL_BEGIN
}
}
#pragma mark - LoopingVideoViewDelegate
- (void)loopingVideoViewChangedPlayerItem {
OWSAssertIsOnMainThread();
[self updateZoomScaleAndConstraints];
self.scrollView.zoomScale = self.scrollView.minimumZoomScale;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -113,8 +113,20 @@ private class LoopingVideoPlayer: AVPlayer {
}
}
// MARK: -
@objc
public protocol LoopingVideoViewDelegate: AnyObject {
func loopingVideoViewChangedPlayerItem()
}
// MARK: -
@objc
public class LoopingVideoView: UIView {
@objc
public weak var delegate: LoopingVideoViewDelegate?
private let player = LoopingVideoPlayer()
@objc
@ -125,16 +137,25 @@ public class LoopingVideoView: UIView {
invalidateIntrinsicContentSize()
if let assetPromise = video?.assetPromise {
assetPromise.done(on: .global(qos: .userInitiated)) { asset in
guard asset === self.video?.asset else { return }
if let asset = asset {
let playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["tracks"])
self.player.replaceCurrentItem(with: playerItem)
self.player.play()
DispatchQueue.main.async { self.invalidateIntrinsicContentSize() }
firstly {
assetPromise
}.map(on: .global(qos: .userInitiated)) { [weak self] asset -> Bool in
guard let self = self,
let asset = asset,
asset === self.video?.asset else {
return false
}
let playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["tracks"])
self.player.replaceCurrentItem(with: playerItem)
self.player.play()
return true
}.done(on: .main) { [weak self] didLoadPlayer in
guard let self = self,
didLoadPlayer else {
return
}
self.invalidateIntrinsicContentSize()
self.delegate?.loopingVideoViewChangedPlayerItem()
}
}
}