benchmarks/showcases/LazyGridImageView/nativeiosApp/nativeiosApp/ContentView.swift (109 lines of code) (raw):
import SwiftUI
import Foundation
import UIKit
import Combine
struct ContentView: View {
// in testing mode it is allowed to have not all images downloaded
private let testingMode: Bool = false
@State private var imageNames: [String] = []
@State private var autoScroll: Bool = false
@State private var scrollPosition: Int = 0
@State private var scrollingDown: Bool = true
@State private var timer: AnyCancellable?
private let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
var body: some View {
VStack {
// Toggle for auto-scrolling
Toggle(isOn: $autoScroll) {
Text("Auto Scroll")
}
.padding(.horizontal)
.onChange(of: autoScroll) { newValue in
if newValue {
startAutoScroll()
} else {
stopAutoScroll()
}
}
ScrollViewReader { proxy in
ScrollView {
// Grid with 3 columns
LazyVGrid(columns: columns, spacing: 8) {
ForEach(0..<imageNames.count, id: \.self) { index in
GridItemView(imageName: imageNames[index])
.aspectRatio(1, contentMode: .fill)
.id(index) // Add id for ScrollViewReader
}
}
.padding(8)
}
.onChange(of: scrollPosition) { newPosition in
// Scroll to the new position when scrollPosition changes
withAnimation(.linear) {
proxy.scrollTo(newPosition, anchor: .top)
}
}
}
}
.onAppear {
// Load image names when the view appears
loadImageNames()
}
.onDisappear {
// Stop auto-scrolling when view disappears
stopAutoScroll()
}
}
private func loadImageNames() {
let numOfImages = 999
if testingMode {
var existingImages: [String] = []
(1...numOfImages).forEach { index in
let name = "downloaded_image\(String(format: "%03d", index))"
if (UIImage(named: name) != nil) {
existingImages.append(name)
}
}
if (existingImages.count == 0) {
return
}
imageNames = (0..<numOfImages).map { index in
existingImages[index % existingImages.count]
}
} else {
imageNames = (0..<numOfImages).map { index in
"downloaded_image\(String(format: "%03d", index + 1))"
}
}
}
private func startAutoScroll() {
// Cancel any existing timer
stopAutoScroll()
timer = Timer.publish(every: 0.1, on: .main, in: .common)
.autoconnect()
.sink { _ in
self.updateScrollPosition()
}
}
private func stopAutoScroll() {
timer?.cancel()
timer = nil
}
private func updateScrollPosition() {
if scrollingDown {
// Scrolling down
if scrollPosition < imageNames.count - columns.count - 1 {
scrollPosition += columns.count
} else {
// Reached bottom, change direction
scrollingDown = false
}
} else {
// Scrolling up
if scrollPosition > 0 {
scrollPosition -= columns.count
} else {
// Reached top, change direction
scrollingDown = true
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}