| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- //
- // LNImagePreviewController.swift
- // Lanu
- //
- // Created by OneeChan on 2025/12/11.
- //
- import Foundation
- import UIKit
- import SnapKit
- extension UIView {
- func presentImagePreview(_ urls: [String], _ targetIndex: Int) {
- let vc = LNImagePreviewController()
- vc.loadImages(urls: urls, targetIndex: targetIndex)
- vc.modalPresentationStyle = .overFullScreen
- viewController?.present(vc, animated: true)
- }
- }
- class LNImagePreviewController: LNViewController {
- private var imageURLs: [String] = []
- private var curIndex: Int = 0 {
- didSet {
- titleLabel.text = "\(curIndex + 1)/\(imageURLs.count)"
- }
- }
-
- private var collectionView: UICollectionView?
-
- private let fakeBar = LNFakeNaviBar()
- private let titleLabel = UILabel()
-
- func loadImages(urls: [String], targetIndex: Int) {
- imageURLs = urls
- curIndex = targetIndex
-
- collectionView?.reloadData()
- DispatchQueue.main.async { [weak self] in
- guard let self else { return }
- collectionView?.scrollToItem(
- at: .init(row: curIndex, section: 0),
- at: .centeredHorizontally,
- animated: false)
- }
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- showNavigationBar = false
- setupViews()
- }
- }
- extension LNImagePreviewController: LNImagePreviewCellDelegate {
- func onImagePreviewCellDragToDismiss(cell: LNImagePreviewCell) {
- dismiss(animated: false)
- }
- }
- extension LNImagePreviewController: UICollectionViewDataSource, UICollectionViewDelegate {
- func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- imageURLs.count
- }
-
- func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LNImagePreviewCell.className, for: indexPath) as! LNImagePreviewCell
- cell.update(url: imageURLs[indexPath.row])
- cell.delegate = self
- return cell
- }
-
- func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
- let previewCell = cell as! LNImagePreviewCell
- previewCell.resetZoom()
- }
-
- func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
- curIndex = Int(scrollView.contentOffset.x / scrollView.bounds.width)
- }
-
- func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
- curIndex = Int(scrollView.contentOffset.x / scrollView.bounds.width)
- }
- }
- extension LNImagePreviewController {
- private func setupViews() {
- view.backgroundColor = .clear
-
- let layout = UICollectionViewFlowLayout()
- layout.scrollDirection = .horizontal
- layout.itemSize = view.bounds.size
- layout.minimumLineSpacing = 0
- layout.minimumInteritemSpacing = 0
-
- let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
- collectionView.isPagingEnabled = true
- collectionView.showsHorizontalScrollIndicator = false
- collectionView.backgroundColor = .black
- collectionView.register(LNImagePreviewCell.self, forCellWithReuseIdentifier: LNImagePreviewCell.className)
- collectionView.dataSource = self
- collectionView.delegate = self
- view.addSubview(collectionView)
- collectionView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
- self.collectionView = collectionView
-
- let fakeBar = buildFakeNavBar()
- view.addSubview(fakeBar)
- fakeBar.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- }
- }
-
- private func buildFakeNavBar() -> UIView {
- fakeBar.showBackButton { [weak self] in
- guard let self else { return }
- dismiss(animated: true)
- }
- fakeBar.backButton?.setImage(.init(systemName: "chevron.backward")?.withRenderingMode(.alwaysTemplate), for: .normal)
- fakeBar.backButton?.tintColor = .fill
-
- titleLabel.font = .body_l
- titleLabel.textColor = .text_1
- fakeBar.actionView.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.center.equalToSuperview()
- }
-
- return fakeBar
- }
- }
|