Mobile App Dev 2022W: Assignment 2
This assignment is still being developed.
Questions
- [1] Explain how to add this image from Wikipedia to the image list under the name "Boxer".
- [2] What name is added to the menu if we manually enter a URL and select "Remember Image"? Why? Explain with an example.
Code: remotePicViewer2 ContentView.swift
// remotePicViewer2
//
// code for Assignment 2
// COMP 1601 2022W, Carleton University
//
// Anil Somayaji, February 10, 2022
// Code is licenced under the FSF GPLv3 or newer
//
// Note this code is for teaching purposes only. In particular
// it is not robust and does not handle error conditions properly.
//
import SwiftUI
var images: [String: String] = [
"Kittens": "https://homeostasis.scs.carleton.ca/~soma/mad-2022w/images/kittens.jpeg",
"Sad Dog":
"https://homeostasis.scs.carleton.ca/~soma/mad-2022w/images/roshi.jpeg",
]
@available(macOS 12.0, *)
struct ContentView: View {
@State private var imageName = "Kittens"
@State private var theImage = getImage("Kittens")
@State private var moved = false
@State private var finalAmount: CGFloat = 1
@State private var angle = Angle(degrees: 0.0)
@State private var imageNames = [String] (images.keys)
func resetState() {
moved = false
finalAmount = 1
angle = Angle(degrees: 0.0)
}
var body: some View {
VStack {
Text("Image Viewer")
.font(.title)
TextField("Enter an image URL", text: $theImage)
Menu("Known Images") {
ForEach(imageNames, id: \.self) {s in
Button(s, action: {
theImage = getImage(s)
resetState()
})
}
Divider()
Button("Remember Image", action: {
let urlParts = theImage.split(separator: "/")
let newName = String(urlParts[urlParts.count - 1])
imageNames.append(newName)
images[newName] = theImage
})
}
Divider().background(Color.black)
ActiveImage(theImage: $theImage, imageName: $imageName, moved: $moved, finalAmount: $finalAmount, angle: $angle)
}
}
}
func getImage(_ imageName: String) -> String {
return images[imageName] ?? "https://homeostasis.scs.carleton.ca/~soma/year.jpg"
}
@available(macOS 12.0, *)
struct ActiveImage: View {
@State private var position = CGPoint(x: 0, y: 0)
@State private var currentAmount: CGFloat = 0
@Binding var theImage: String
@Binding var imageName: String
@Binding var moved: Bool
@Binding var finalAmount: CGFloat
@Binding var angle: Angle
var body: some View {
GeometryReader {g in
AsyncImage(url: URL(string: theImage), content: {image in
image
.resizable()
.scaledToFit()
.position(moved ? position :
CGPoint(x: g.size.width / 2,
y: g.size.height / 2))
.scaleEffect(finalAmount + currentAmount)
.gesture(dragging)
.gesture(magnifying)
.rotationEffect(self.angle)
.onLongPressGesture(perform: tapReset)
.onTapGesture(count: 2, perform: zoom)
.onTapGesture(count: 1, perform: rotateImage)
}, placeholder: {
ProgressView()
.position(moved ? position :
CGPoint(x: g.size.width / 2,
y: g.size.height / 2))
})
}
}
func zoom() {
self.finalAmount = self.finalAmount * 2
}
func tapReset() {
self.finalAmount = 1
self.moved = false
self.angle = Angle(degrees: 0.0)
}
func rotateImage() {
let oldDegrees = self.angle.degrees
self.angle = Angle(degrees: oldDegrees + 45)
}
var magnifying: some Gesture {
MagnificationGesture().onChanged { amount in
self.currentAmount = amount - 1
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
}
}
var dragging: some Gesture {
DragGesture()
.onChanged {s in
self.moved = true
self.position = s.location
}
.onEnded {s in
self.moved = true
self.position = s.location
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}