103 lines
3.6 KiB
Swift
103 lines
3.6 KiB
Swift
//
|
||
// ImagePreviewViewController.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import SnapKit
|
||
import UIKit
|
||
|
||
/// 图片全屏预览,对齐 Android `MediaPreviewDialog`。
|
||
final class ImagePreviewViewController: UIViewController {
|
||
|
||
private let imageURLs: [String]
|
||
private let startIndex: Int
|
||
private let scrollView = UIScrollView()
|
||
private let pageControl = UIPageControl()
|
||
|
||
init(imageURLs: [String], startIndex: Int) {
|
||
self.imageURLs = imageURLs
|
||
self.startIndex = min(max(0, startIndex), max(0, imageURLs.count - 1))
|
||
super.init(nibName: nil, bundle: nil)
|
||
modalPresentationStyle = .fullScreen
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
view.backgroundColor = .black
|
||
|
||
scrollView.isPagingEnabled = true
|
||
scrollView.showsHorizontalScrollIndicator = false
|
||
scrollView.delegate = self
|
||
|
||
pageControl.numberOfPages = imageURLs.count
|
||
pageControl.currentPage = startIndex
|
||
pageControl.isHidden = imageURLs.count <= 1
|
||
|
||
let closeButton = UIButton(type: .system)
|
||
closeButton.setImage(UIImage(systemName: "xmark"), for: .normal)
|
||
closeButton.tintColor = .white
|
||
closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
|
||
|
||
view.addSubview(scrollView)
|
||
view.addSubview(pageControl)
|
||
view.addSubview(closeButton)
|
||
|
||
scrollView.snp.makeConstraints { make in
|
||
make.edges.equalToSuperview()
|
||
}
|
||
pageControl.snp.makeConstraints { make in
|
||
make.bottom.equalTo(view.safeAreaLayoutGuide).inset(AppSpacing.md)
|
||
make.centerX.equalToSuperview()
|
||
}
|
||
closeButton.snp.makeConstraints { make in
|
||
make.top.equalTo(view.safeAreaLayoutGuide).offset(AppSpacing.sm)
|
||
make.trailing.equalToSuperview().inset(AppSpacing.md)
|
||
make.size.equalTo(AppSpacing.minTouchTarget)
|
||
}
|
||
|
||
imageURLs.enumerated().forEach { index, url in
|
||
let imageView = UIImageView()
|
||
imageView.contentMode = .scaleAspectFit
|
||
imageView.loadRemoteImage(urlString: url, placeholderColor: .darkGray)
|
||
scrollView.addSubview(imageView)
|
||
imageView.snp.makeConstraints { make in
|
||
make.top.bottom.equalToSuperview()
|
||
make.width.equalTo(view.snp.width)
|
||
make.height.equalTo(view.snp.height)
|
||
make.leading.equalToSuperview().offset(CGFloat(index) * view.bounds.width)
|
||
}
|
||
}
|
||
}
|
||
|
||
override func viewDidLayoutSubviews() {
|
||
super.viewDidLayoutSubviews()
|
||
scrollView.contentSize = CGSize(width: view.bounds.width * CGFloat(imageURLs.count), height: view.bounds.height)
|
||
scrollView.setContentOffset(CGPoint(x: view.bounds.width * CGFloat(startIndex), y: 0), animated: false)
|
||
scrollView.subviews.enumerated().forEach { index, subview in
|
||
subview.frame = CGRect(
|
||
x: view.bounds.width * CGFloat(index),
|
||
y: 0,
|
||
width: view.bounds.width,
|
||
height: view.bounds.height
|
||
)
|
||
}
|
||
}
|
||
|
||
@objc private func closeTapped() {
|
||
dismiss(animated: true)
|
||
}
|
||
}
|
||
|
||
extension ImagePreviewViewController: UIScrollViewDelegate {
|
||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||
guard view.bounds.width > 0 else { return }
|
||
let page = Int(round(scrollView.contentOffset.x / view.bounds.width))
|
||
pageControl.currentPage = page
|
||
}
|
||
}
|