Paul Hudson's (@twostraws) 100 Days of Swift UI Project 17
Source URL: link
In this project we’re going to build an app that helps users learn things using flashcards – cards with one thing written on such as “to buy”, and another thing written on the other side, such as “comprar”. Of course, this is a digital app so we don’t need to worry about “the other side”, and can instead just make the detail for the flash card appear when it’s tapped.
Note: In this project, I chose to go with less branches and a shorter Read Me, focusing only on what I've found interesting or important for my own projects. One can always refer to Paul's original tutorial (always recommended) for a complete explanation.
Examples of gestures (note: it doesn't work well in the simulator):
import SwiftUI
struct ContentView: View {
@State var tapMessage = "Tap to start!"
@State var gestureChangedMessage = "This triggers whenever the gesture changes!"
@State var scaleMessage = "Scale gesture!"
@State var currentAmount = 0.0
@State var finalAmount = 1.0
@State var rotationMessage = "Rotation gesture!"
@State var currentAngleAmount = Angle.zero
@State var finalAngleAmount = Angle.zero
var body: some View {
Spacer()
Text(tapMessage)
.onTapGesture(count: 2) {
tapMessage = "You tapped 2 times"
}
.onLongPressGesture(minimumDuration: 2) {
tapMessage = "You pressed long for 2 seconds"
}
Spacer()
Text(gestureChangedMessage)
.onLongPressGesture(minimumDuration: 1) {
gestureChangedMessage = "Long press gesture started!"
} onPressingChanged: { inProgress in
gestureChangedMessage = ("In progress: \(inProgress ? "Long pressing": "Long pressing ended")")
}
Spacer()
Text(scaleMessage)
.scaleEffect(finalAmount + currentAmount)
.gesture(
MagnifyGesture()
.onChanged { value in
self.currentAmount = value.magnification - 1
}
.onEnded { value in
finalAmount += currentAmount
currentAmount = 0
}
)
Spacer()
Text(rotationMessage)
.rotationEffect(currentAngleAmount + finalAngleAmount)
.gesture(
RotateGesture()
.onChanged { value in
self.currentAngleAmount = value.rotation
}
.onEnded { value in
finalAngleAmount += currentAngleAmount
currentAngleAmount = .zero
}
)
Spacer()
}
}
#Preview {
ContentView()
}
Source URL: link
Result:
Source URL: link
I've found this extension
for stacking cards really interesting:
extension View {
func stacked(at position: Int, in total: Int) -> some View {
let offset = Double(total - position)
return self.offset(y: offset * 10)
}
}
And here's the code...
ZStack {
Image(.background)
.resizable()
.ignoresSafeArea()
VStack {
ZStack {
ForEach(0..<cards.count, id: \.self) { index in
CardView(card: cards[index])
.stacked(at: index, in: cards.count)
}
}
}
}
... that creates the end result below:
Source URL: Flashzilla Wrap Up
Branch: challenge-01
When adding a card, the text fields keep their current text. Fix that so that the textfields clear themselves after a card is added.
This problem was solved by simply setting the two state variables back to an empty string value after adding (and saving) the card as below:
func addCard() {
let trimmedPrompt = newPrompt.trimmingCharacters(in: .whitespaces)
let trimmedAnswer = newAnswer.trimmingCharacters(in: .whitespaces)
guard trimmedPrompt.isEmpty == false && trimmedAnswer.isEmpty == false else { return }
let card = Card(prompt: trimmedPrompt, answer: trimmedAnswer)
cards.insert(card, at: 0)
saveData()
// Challenge 1 solution below
newPrompt = ""
newAnswer = ""
}
Original code created by: Paul Hudson - @twostraws (Thank you!)
Made with ❤️ by @cewitte