Difference between revisions of "Mobile App Dev 2022W: Tutorial 3"

From Soma-notes
Jump to navigation Jump to search
Line 1: Line 1:
'''This tutorial is still being developed.'''
In this tutorial you will be playing with [https://homeostasis.scs.carleton.ca/~soma/mad-2022w/code/dragDemo2/ContentView.swift dragDemo2], a simple SwiftUI program where you drag a ball into a box.
==Key Concepts & Resources==
For this tutorial, however, you shouldn't need to refer to the documentation below; the code itself should be simple enough to understand and experiment with.  However, if you want to learn more, see below.
This code introduces these SwiftUI concepts and mechanisms:
* [https://developer.apple.com/documentation/swiftui/shape Shapes], specifically circles and rectangles. 
* [https://developer.apple.com/documentation/swiftui/button/position(_:) View positions]
* [https://developer.apple.com/documentation/swiftui/adding-interactivity-with-gestures Gestures]
* [https://developer.apple.com/documentation/swiftui/building-layouts-with-stack-views ZStack]
A list of key Apple articles on SwiftUI is [https://developer.apple.com/documentation/swiftui here].  Unfortunately, these articles are incomplete and sometimes ambiguous, so you may want to look at other online resources if you are looking to learn more about SwiftUI.  I've found the [https://www.hackingwithswift.com/books/ios-swiftui/ Hacking with Swift] online book to be helpful overall, and [https://medium.com/better-programming/drag-swipe-and-touch-gestures-in-swiftui-fa5364090745 Mark Lucking's article on drag and drop is informative] and [https://swiftui-lab.com/geometryreader-to-the-rescue/ The SwiftUI Lab's article on GeometryReader]. Unfortunately, I've found no online resource that is truly authoritative and complete.
==Tasks==
# What is the initial coordinates of the box?  Of the circle?  What are these coordinates relative to?
# How do you change the drag gesture to be processed "OnEnded" rather than "OnDrag"?  How does this change the behaviour of the program?
# Where does the circle have to be to get the success menu?  Be precise in terms of coordinates.
# Where is view state being stored?  Where is it being used?
# How would you make the lines of the rectangle thinner?
# Can you make it impossible for the ball to enter the square (but allow it to be dragged everywhere else on the screen)?
# Do you see any regular closures here?  If so, where are they being used and for what purpose?  (Do not consider closures that are actually Views.)
==Code==
==Code==



Revision as of 22:55, 25 January 2022

This tutorial is still being developed.

In this tutorial you will be playing with dragDemo2, a simple SwiftUI program where you drag a ball into a box.

Key Concepts & Resources

For this tutorial, however, you shouldn't need to refer to the documentation below; the code itself should be simple enough to understand and experiment with. However, if you want to learn more, see below.

This code introduces these SwiftUI concepts and mechanisms:

A list of key Apple articles on SwiftUI is here. Unfortunately, these articles are incomplete and sometimes ambiguous, so you may want to look at other online resources if you are looking to learn more about SwiftUI. I've found the Hacking with Swift online book to be helpful overall, and Mark Lucking's article on drag and drop is informative and The SwiftUI Lab's article on GeometryReader. Unfortunately, I've found no online resource that is truly authoritative and complete.

Tasks

  1. What is the initial coordinates of the box? Of the circle? What are these coordinates relative to?
  2. How do you change the drag gesture to be processed "OnEnded" rather than "OnDrag"? How does this change the behaviour of the program?
  3. Where does the circle have to be to get the success menu? Be precise in terms of coordinates.
  4. Where is view state being stored? Where is it being used?
  5. How would you make the lines of the rectangle thinner?
  6. Can you make it impossible for the ball to enter the square (but allow it to be dragged everywhere else on the screen)?
  7. Do you see any regular closures here? If so, where are they being used and for what purpose? (Do not consider closures that are actually Views.)

Code

dragDemo2 ContentView.swift

//
//  ContentView.swift
//  dragDemo2
//

import SwiftUI

struct ContentView: View {
    @State var circleLocation = CGPoint(x: -100, y: -100)
    var body: some View {
        GeometryReader{geometry in
            let w = geometry.size.width
            let h = geometry.size.height
            let boxLocation = CGPoint(x: w/2, y: h/2)
            let boxSize = (w < h ? w : h) / 2
            let startLocation = CGPoint(x: w/2, y: h/6)
            
            VStack{
                SuccessMsg(location: $circleLocation,
                           boxLocation: boxLocation)
                ZStack{
                    CenteredBox(location: boxLocation, size: boxSize)
                    MovableCircle(location: $circleLocation,
                                  size: boxSize * 0.8,
                                  startLocation: startLocation)
                }
                Text("Width: " + w.description +
                     ", Height: " + h.description)
            }
        }
    }
}

struct CenteredBox: View {
    var location: CGPoint
    var size: CGFloat
    var body: some View {
        Rectangle()
            .stroke(Color.green, lineWidth: 10)
            .frame(width: size, height: size)
            .position(location)
    }
}

struct MovableCircle: View {
    @Binding var location: CGPoint
    @State private var isDragging = false
    var size: CGFloat
    var startLocation: CGPoint
    
    var body: some View {
        return Circle()
            .fill(Color.blue)
            .frame(width: size, height: size)
            .position(location.x < 0 ? startLocation : location)
            .gesture(DragGesture()
                        .onChanged { value in
                            self.location = value.location})
    }
}

struct SuccessMsg: View {
    @Binding var location: CGPoint
    var boxLocation: CGPoint
    
    var body: some View {
        if (abs(location.x - boxLocation.x) < 20) &&
            (abs(location.y - boxLocation.y) < 20) {
            Text("Success!").font(.title).bold()
        } else {
            Text("Drag the circle into the box").font(.title).bold()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}