diff --git a/suixinkan/UI/TravelAlbum/TravelAlbumPhotoPreviewViewController.swift b/suixinkan/UI/TravelAlbum/TravelAlbumPhotoPreviewViewController.swift index 8b571c3..41555d5 100644 --- a/suixinkan/UI/TravelAlbum/TravelAlbumPhotoPreviewViewController.swift +++ b/suixinkan/UI/TravelAlbum/TravelAlbumPhotoPreviewViewController.swift @@ -639,11 +639,6 @@ private final class TravelAlbumPreviewImageCell: UICollectionViewCell, UIScrollV resetZoom() } - override func layoutSubviews() { - super.layoutSubviews() - imageView.frame = scrollView.bounds - } - func apply(asset newAsset: TravelAlbumPreviewAsset?) { asset = newAsset resetZoom() @@ -687,6 +682,7 @@ private final class TravelAlbumPreviewImageCell: UICollectionViewCell, UIScrollV imageView.contentMode = .scaleAspectFit imageView.backgroundColor = .black imageView.kf.indicatorType = .activity + imageView.accessibilityIdentifier = "travelAlbum.previewImageView" retryButton.setTitle("图片加载失败,点击重试", for: .normal) retryButton.setTitleColor(UIColor.white.withAlphaComponent(0.82), for: .normal) @@ -699,6 +695,11 @@ private final class TravelAlbumPreviewImageCell: UICollectionViewCell, UIScrollV scrollView.addSubview(imageView) contentView.addSubview(retryButton) scrollView.snp.makeConstraints { $0.edges.equalToSuperview() } + imageView.snp.makeConstraints { make in + make.edges.equalTo(scrollView.contentLayoutGuide) + make.width.equalTo(scrollView.frameLayoutGuide) + make.height.equalTo(scrollView.frameLayoutGuide) + } retryButton.snp.makeConstraints { $0.center.equalToSuperview() } let singleTap = UITapGestureRecognizer(target: self, action: #selector(singleTapped)) diff --git a/suixinkanTests/TravelAlbumDetailViewControllerTests.swift b/suixinkanTests/TravelAlbumDetailViewControllerTests.swift index 238530d..8d7b9bf 100644 --- a/suixinkanTests/TravelAlbumDetailViewControllerTests.swift +++ b/suixinkanTests/TravelAlbumDetailViewControllerTests.swift @@ -110,6 +110,60 @@ final class TravelAlbumDetailViewControllerTests: XCTestCase { window.isHidden = true } + func testPreviewImageViewKeepsViewportConstraintsWhenSwitchingVariant() throws { + UIView.setAnimationsEnabled(false) + defer { UIView.setAnimationsEnabled(true) } + let project = TravelAlbumPreviewProject( + originalMaterialId: 1, + assets: [ + TravelAlbumPreviewAsset( + id: "original-1", + kind: .original, + fileURL: "", + coverURL: "", + fileName: "原图.jpg", + fileSize: 0 + ), + TravelAlbumPreviewAsset( + id: "retouched-1", + kind: .retouched, + fileURL: "", + coverURL: "", + fileName: "精修后.jpg", + fileSize: 0 + ), + ] + ) + let controller = TravelAlbumPhotoPreviewViewController( + projects: [project], + totalCount: 1, + startProjectIndex: 0 + ) + controller.loadViewIfNeeded() + controller.view.frame = CGRect(x: 0, y: 0, width: 390, height: 844) + controller.view.layoutIfNeeded() + + let retouchedButton = try XCTUnwrap( + controller.view.findSubview { + ($0 as? UIButton)?.accessibilityLabel == "精修后" + } as? UIButton + ) + retouchedButton.sendActions(for: .touchUpInside) + controller.view.layoutIfNeeded() + + let imageView = try XCTUnwrap( + controller.view.findSubview { + $0.accessibilityIdentifier == "travelAlbum.previewImageView" + } as? UIImageView + ) + let scrollView = try XCTUnwrap(imageView.superview as? UIScrollView) + scrollView.layoutIfNeeded() + + XCTAssertEqual(imageView.bounds.size, scrollView.bounds.size) + XCTAssertFalse(imageView.constraintsAffectingLayout(for: .horizontal).isEmpty) + XCTAssertFalse(imageView.constraintsAffectingLayout(for: .vertical).isEmpty) + } + func testSelectionModeShowsAIRetouchOnLeftAndDeleteOnRight() async throws { let controller = TravelAlbumDetailViewController(albumId: 0) controller.loadViewIfNeeded()