-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImageScrollViewController.swift
146 lines (130 loc) · 4.83 KB
/
ImageScrollViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// ImageScrollViewController.swift
// FolderImageViewer
//
// Created by Gualtiero Frigerio on 30/01/2019.
//
import UIKit
private struct ImageViewInfo {
var index:Int!
var view:UIImageView?
var disposable:Bool!
}
class ImageScrollViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView!
var imageProvider:ImageProvider?
private var files:[FilesystemEntry]?
private var imageViews = [ImageViewInfo]()
private var currentIndex:Int = 0
private var internalView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
imageViews.append(ImageViewInfo(index: -1, view: nil, disposable: true))
imageViews.append(ImageViewInfo(index: -1, view: nil, disposable: true))
imageViews.append(ImageViewInfo(index: -1, view: nil, disposable: true))
if files != nil {
initScrollView()
}
scrollView.delegate = self
self.view.accessibilityIdentifier = "imageScrollViewController"
scrollView.accessibilityIdentifier = "scrollView"
internalView.accessibilityIdentifier = "scrollViewContainer"
}
func setFiles(_ files:[FilesystemEntry], startIndex:Int) {
self.files = files;
currentIndex = startIndex
if scrollView != nil {
initScrollView()
}
}
private func initScrollView() {
let x = scrollView.visibleSize.width * CGFloat(currentIndex)
scrollView.contentOffset = CGPoint(x: x, y: 0)
scrollView.isPagingEnabled = true
scrollView.maximumZoomScale = 2.0
scrollView.minimumZoomScale = 1.0
let totalWidth = scrollView.visibleSize.width * CGFloat(files!.count)
let height = scrollView.visibleSize.height
scrollView.contentSize = CGSize(width: totalWidth, height: height)
internalView.frame = CGRect(x:0, y:0, width:totalWidth, height:height)
scrollView.addSubview(internalView)
refreshScrollView()
}
private func refreshScrollView() {
markValidEntries(startIndex: currentIndex - 1, endIndex: currentIndex + 1)
loadImageView(atIndex: currentIndex)
loadImageView(atIndex: currentIndex - 1)
loadImageView(atIndex: currentIndex + 1)
}
private func loadImageView(atIndex index:Int) {
if index < 0 || index >= files!.count {
return
}
let entryIndex = getImageViewEntryIndex(forImageAtIndex: index)
var entry = imageViews[entryIndex]
if entry.view == nil {
entry.view = createImageView(withImageAtIndex: index)
}
entry.disposable = false
entry.index = index
imageViews[entryIndex] = entry
if entry.view!.superview == nil {
internalView.addSubview(entry.view!)
}
var frame = entry.view!.frame
frame.origin.x = frame.size.width * CGFloat(index)
entry.view!.frame = frame
//print("image at index \(index) starts at \(frame.origin.x)")
}
/*
* search for an entry with the same index
* if none of the 3 entries is valid we look for the first disposable one
* and if none of them are disposable we take the first one
*/
private func getImageViewEntryIndex(forImageAtIndex imageIndex:Int) -> Int {
for i in 0..<imageViews.count {
let entry = imageViews[i]
if entry.index == imageIndex {
return i
}
}
for i in 0..<imageViews.count {
let entry = imageViews[i]
if entry.disposable {
return i
}
}
return 0
}
private func markValidEntries(startIndex:Int, endIndex:Int) {
for i in 0..<imageViews.count {
var entry = imageViews[i]
if entry.index < startIndex || entry.index > endIndex {
entry.disposable = true
imageViews[i] = entry
}
}
}
private func createImageView(withImageAtIndex index:Int) -> UIImageView {
let size = scrollView.visibleSize
let frame = CGRect(x:0, y:0, width:size.width, height: size.height)
let imageView = UIImageView(frame: frame)
let fileEntry = files![index]
let image = imageProvider?.getImage(atFileURL: fileEntry.url)
imageView.image = image
imageView.contentMode = .scaleAspectFit
return imageView
}
}
extension ImageScrollViewController : UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let position = (Int)(scrollView.contentOffset.x / scrollView.visibleSize.width)
if position != currentIndex {
currentIndex = position
refreshScrollView()
}
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return internalView
}
}