I created an ActionSheet, but was unable to print the value I selected on the TextField.
I do not know how to do it. I will be glad if you can help.
struct illedetayyip: View {
#State private var iliskiDurumlari: [String] = ["Evli", "Bekar", "Ayrı", "anan"]
#State private var iliskiArray = NSMutableArray()
#State private var iliskiVisible = false
#State private var iliski = ""
func iliskiFunc() {
for i in 0 ..< self.iliskiDurumlari.count {
let button: ActionSheet.Button = .default(Text(self.iliskiDurumlari[i]), action: {
print(self.iliskiDurumlari[i])
})
self.iliskiArray[i] = button
}
}
init() {
iliskiFunc()
}
var body: some View {
VStack {
TextField("İlişki Durumu Seçiniz..", text: $iliski)
.frame(width: 300, height: 50, alignment: .center)
.padding(5)
.font(Font.system(size: 15, weight: .medium, design: .serif))
.overlay(RoundedRectangle(cornerRadius: 30).stroke(Color(red: 45 / 255,
green: 0 / 255, blue: 112 / 255), lineWidth: 1))
.actionSheet(isPresented: $iliskiVisible) {
ActionSheet(title: Text("Bir İlişki Durumu Seçiniz"), message:
Text("Aşagıda"), buttons: self.iliskiArray as! [ActionSheet.Button])
}
.onTapGesture {
self.iliskiVisible.toggle()
}
}
}
}
You don't need to create a NSMutableArray and then cast it back to [ActionSheet.Button].
Try this instead:
struct illedetayyip: View {
#State private var iliskiDurumlari: [String] = ["Evli", "Bekar", "Ayrı", "anan"]
#State private var iliskiVisible = false
#State private var iliski = ""
var body: some View {
VStack {
TextField("İlişki Durumu Seçiniz..", text: $iliski)
.frame(width: 300, height: 50, alignment: .center)
.padding(5)
.font(Font.system(size: 15, weight: .medium, design: .serif))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(red: 45 / 255, green: 0 / 255, blue: 112 / 255), lineWidth: 1)
)
.actionSheet(isPresented: $iliskiVisible, content: actionSheet)
.onTapGesture {
self.iliskiVisible.toggle()
}
}
}
func actionSheet() -> ActionSheet {
ActionSheet(
title: Text("Bir İlişki Durumu Seçiniz"),
message: Text("Aşagıda"),
buttons: iliskiDurumlari.map { value in
ActionSheet.Button.default(Text(value), action: {
self.iliski = value
})
}
)
}
}
Related
I'm making a math game and I'm trying to implement a circular progress bar, where I get errors. I'm not sure if I'm doing anything wrong, but I can't adapt it to the progress of the game, and that's what I want to do. Please look over my code down below...
struct QuestionView: View {
#State var show = false
#State var showSheet: Bool = false
#State var showSheetA: Bool = false
#State var showSheet2: Bool = false
#State private var correctAnswer = 0
#State private var choiceArray: [Int] = [0, 1, 2, 3]
#State private var firstNumber = 0
#State private var secondNumber = 0
#State private var difficulty = 100
#State private var score = 0
#State private var Background1 = "Background 1"
#State private var Background2 = "Background 2"
#State private var Background3 = "Background 3"
#State private var Background4 = "Background 4"
#State private var Background5 = "Background 5"
#State private var Background6 = "Background 6"
#State private var Background7 = "Background 7"
#State private var Background8 = "Background 8"
#State private var Background9 = "Background 9"
#State private var Background10 = "Background 10"
#State private var Background11 = "Background 11"
#State private var Background12 = "Background 12"
#State private var background = [
"Background 1",
"Background 2",
"Background 3",
"Background 4",
"Background 5",
"Background 6",
"Background 7",
"Background 8",
"Background 9",
"Background 10",
"Background 11",
"Background 12",
]
#State var value = "0"
let buttons: [[CalcButton]] = [
[.clear, .negative, .percent, .divide],
[.seven, .eight, .nine, .multiply],
[.four, .five, .six, .subtract],
[.one, .two, .three, .add],
[.zero, .decimal, .equal]
]
#State var currentOperation: Operation = .none
#State var runningNumber = 0
var body: some View {
ZStack {
Image("\(Background1)")
.resizable()
.aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all)
.blur(radius: 20)
.onAppear {
shuffle()
}
VStack {
VStack(alignment: .leading) {
HStack {
HStack {
Circle()
//Where the problem is happening at the trim
.trim(from: CGFloat(show ? Int(0.99) : answerIsCorrect(answer: correctAnswer)), to: 0.01)
.stroke(LinearGradient(gradient: Gradient(colors: [Color.white, Color.white.opacity(0.2)]), startPoint: .topLeading, endPoint: .bottomTrailing), style: StrokeStyle(lineWidth: 17.5, lineCap: .round))
.shadow(radius: 8)
.rotationEffect(.degrees(90))
.rotation3DEffect(Angle(degrees: 180), axis: (x: 1, y: 0, z: 0))
.frame(width: 60, height: 60)
.animation(.easeOut)
.padding()
.padding([.top, .leading])
Spacer()
}
Button {
showSheet.toggle()
} label: {
VStack {
ZStack {
Rectangle()
.fill(.thinMaterial)
.frame(width: 80, height: 40)
.cornerRadius(30)
.padding(.top, 13)
.padding(.trailing, 0)
HStack {
Image(systemName: "circle.grid.3x3.fill")
.foregroundColor(.white)
.font(.title3)
.padding(.top, 13)
.padding(.trailing, 0)
}
}
Text("CALCULATOR")
.font(.system(size: 11))
.padding(.trailing, 0)
}
}
.halfSheet(showSheet: $showSheet) {
ZStack {
Color.black.opacity(0.925).ignoresSafeArea()
VStack {
Spacer()
// Text display
HStack {
Spacer()
Text(value)
.bold()
.font(.system(size: 70))
.foregroundColor(.white)
.minimumScaleFactor(0.5)
}
.padding(.leading)
.padding([.top, .trailing], 23)
.padding(.bottom, 2)
// Our Buttons
ForEach(buttons, id: \.self) { row in
HStack(spacing: 12) {
ForEach(row, id: \.self) { item in
Button {
self.didTap(button: item)
} label: {
Text(item.rawValue)
.font(.system(size: 36))
.frame(width: self.buttonWidth(item: item), height: 55)
.scaledToFit()
.background(item.buttonColor)
.foregroundColor(.white)
.cornerRadius(95)
}
}
}
.padding(.bottom, 0.55)
.padding([.leading, .trailing], 20)
}
}
}
}
Button {
showSheet2.toggle()
} label: {
VStack {
ZStack {
Rectangle()
.fill(.thinMaterial)
.frame(width: 80, height: 40)
.cornerRadius(30)
.padding(.top, 13)
.padding(.trailing, 28.5)
HStack {
Image(systemName: "book")
.foregroundColor(.white)
.font(.title3)
.padding(.top, 13)
.padding(.trailing, 28.5)
}
}
Text("DICTIONARY")
.font(.system(size: 11))
.padding(.trailing, 25.5)
}
}
.halfSheet(showSheet: $showSheet2) {
ZStack {
Home()
}
}
}
.padding(.top, 50)
}
VStack {
Text("Solve the following:")
.foregroundColor(.white)
.font(.title2)
.fontWeight(.medium)
.padding(.bottom, 24)
Text("\(firstNumber) + \(secondNumber)")
.foregroundColor(.white)
.font(.system(size: 60, design: .rounded))
.fontWeight(.medium)
.padding(.bottom, 28)
.onAppear {
generateAnswers()
}
VStack(alignment: .center, spacing: 0.01) {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 150), spacing: 2.5)]) {
ForEach(0..<4, id: \.self) { index in
Button {
answerIsCorrect(answer: choiceArray[index])
generateAnswers()
} label: {
AnswerButton(number: choiceArray[index])
}
}
}
Spacer()
}
HStack {
Button {
} label: {
ZStack {
Rectangle()
.fill(Color.white.opacity(0.5))
.frame(maxWidth: 150, maxHeight: 50)
.cornerRadius(15)
.padding([.leading, .trailing])
Image(systemName: "chevron.left")
.font(.title)
}
}
Button {
showSheetA.toggle()
} label: {
VStack {
ZStack {
Rectangle()
.fill(Color.white.opacity(0.5))
.frame(maxWidth: 150, maxHeight: 50)
.cornerRadius(15)
.padding([.leading, .trailing])
Image(systemName: "xmark")
.font(.title)
.foregroundColor(.red)
}
}
}
ZStack {
Rectangle()
.fill(Color.white.opacity(0.5))
.frame(maxWidth: 150, maxHeight: 50)
.cornerRadius(15)
.padding([.leading, .trailing])
Image(systemName: "chevron.right")
.font(.title)
}
}
.padding(.trailing, 6)
.padding(.bottom)
Spacer(minLength: 65)
}
}
}
}
func shuffle() {
Background1 = background[Int.random(in: background.indices)]
Background2 = background[Int.random(in: background.indices)]
Background3 = background[Int.random(in: background.indices)]
Background4 = background[Int.random(in: background.indices)]
Background5 = background[Int.random(in: background.indices)]
Background6 = background[Int.random(in: background.indices)]
Background7 = background[Int.random(in: background.indices)]
Background8 = background[Int.random(in: background.indices)]
Background9 = background[Int.random(in: background.indices)]
Background10 = background[Int.random(in: background.indices)]
Background11 = background[Int.random(in: background.indices)]
Background12 = background[Int.random(in: background.indices)]
}
func answerIsCorrect(answer: Int) {
let isCorrect = answer == correctAnswer ? true : false
if isCorrect {
self.score += 1
} else {
self.score -= 1
}
}
func generateAnswers() {
firstNumber = Int.random(in: 0...(difficulty/2))
secondNumber = Int.random(in: 0...(difficulty/2))
var answerList = [Int]()
correctAnswer = firstNumber + secondNumber
for i in 0...2 {
answerList.append(Int.random(in: 0...difficulty))
}
answerList.append(correctAnswer)
choiceArray = answerList.shuffled()
}
func didTap(button: CalcButton) {
switch button {
case .add, .subtract, .multiply, .divide, .equal:
if button == .add {
self.currentOperation = .add
self.runningNumber = Int(self.value) ?? 0
} else if button == .subtract {
self.currentOperation = .subtract
self.runningNumber = Int(self.value) ?? 0
} else if button == .multiply {
self.currentOperation = .multiply
self.runningNumber = Int(self.value) ?? 0
} else if button == .divide {
self.currentOperation = .divide
self.runningNumber = Int(self.value) ?? 0
} else if button == .equal {
let runningValue = self.runningNumber
let currentValue = Int(self.value) ?? 0
switch self.currentOperation {
case .add:
self.value = "\(runningValue + currentValue)"
case .subtract:
self.value = "\(runningValue - currentValue)"
case .multiply:
self.value = "\(runningValue * currentValue)"
case .divide:
self.value = "\(runningValue / currentValue)"
case .none:
break
}
}
if button != .equal {
self.value = "0"
}
case .clear:
self.value = "0"
case .decimal, .percent, .negative:
break
default:
let number = button.rawValue
if self.value == "0" {
value = number
} else {
self.value = "\(self.value)\(number)"
}
}
}
func buttonWidth(item: CalcButton) -> CGFloat {
if item == .zero {
return ((UIScreen.main.bounds.width - (4*12)) / 4) * 2
}
return (UIScreen.main.bounds.width - (5*12)) / 4
}
func buttonHeight() -> CGFloat {
return (UIScreen.main.bounds.height - (5*12)) / 4
}
}
struct AnswerButton: View {
var number: Int
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color.white.opacity(0.6))
.frame(maxWidth: .infinity, minHeight: 110)
.cornerRadius(15)
.padding([.leading, .trailing], 10)
.padding(.top)
.padding(.trailing, 6)
Text("\(number)")
.font(.largeTitle)
.fontWeight(.medium)
.foregroundColor(.primary)
.padding([.leading, .trailing], 10)
.padding(.top)
.padding(.trailing, 6)
}
}
}
enum CalcButton: String {
case one = "1"
case two = "2"
case three = "3"
case four = "4"
case five = "5"
case six = "6"
case seven = "7"
case eight = "8"
case nine = "9"
case zero = "0"
case add = "+"
case subtract = "-"
case divide = "÷"
case multiply = "×"
case equal = "="
case clear = "AC"
case decimal = "."
case percent = "%"
case negative = "+/-"
var buttonColor: Color {
switch self {
case .add, .subtract, .multiply, .divide, .equal:
return .orange
case .clear, .negative, .percent:
return .gray
default:
return Color(UIColor(red: 55/255.0, green: 55/255.0, blue: 55/255.0, alpha: 1))
}
}
}
enum Operation {
case add, subtract, multiply, divide, none
}
extension View {
func halfSheet<SheetView: View>(showSheet: Binding<Bool>, #ViewBuilder sheetView: #escaping () -> SheetView) -> some View {
return self
.background(
HalfSheetHelper(sheetView: sheetView(), showSheet: showSheet)
)
}
}
struct HalfSheetHelper<SheetView: View>: UIViewControllerRepresentable {
var sheetView: SheetView
#Binding var showSheet: Bool
class Coordinator {
let dummyController = UIViewController()
let sheetController: CustomHostingController<SheetView>
init(sheetView: SheetView, showSheet: Binding<Bool>) {
sheetController = CustomHostingController(rootView: sheetView, onDismiss: { showSheet.wrappedValue = false })
dummyController.view.backgroundColor = .clear
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(sheetView: sheetView, showSheet: $showSheet)
}
func makeUIViewController(context: Context) -> UIViewController {
return context.coordinator.dummyController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
context.coordinator.sheetController.rootView = sheetView
if showSheet && uiViewController.presentedViewController == nil {
uiViewController.present(context.coordinator.sheetController, animated: true)
}
}
}
class CustomHostingController<Content: View>: UIHostingController<Content> {
var onDismiss: (() -> Void)?
convenience init(rootView: Content, onDismiss: #escaping () -> Void) {
self.init(rootView: rootView)
self.onDismiss = onDismiss
}
override func viewDidLoad() {
if let presentationController = presentationController as? UISheetPresentationController {
presentationController.detents = [
.large(),
.medium()
]
presentationController.prefersGrabberVisible = true
}
}
override func viewDidDisappear(_ animated: Bool) {
onDismiss?()
}
}
struct QuestionView_Previews: PreviewProvider {
static var previews: some View {
QuestionView()
}
}
Thank you for looking at my code. I look forward to your answer!
struct ContentView: View {
#State private var progress: Double = 0.1
var body: some View {
VStack {
Circle()
.trim(from: 0, to: progress)
.stroke(lineWidth: 20)
.rotationEffect(Angle(degrees: 180))
.shadow(radius: 8)
.rotationEffect(.degrees(90))
.frame(width: 60, height: 60)
.padding()
Slider(value: $progress, in: 0...1)
.padding()
}
}
}
I've been trying to find a way to change the color of every flashcard in my app. I am struggling with understanding how to use #Binding, which I believe is the best solution. I ended up creating static variables in my Card struct, which allows me to change the card colors via onTapGesture actions. It seems very slow and I know there has to be a better way to accomplish this. Below is my code. The action for changing the color is inside the Circle() in ContentView. Thank you in advance. Also could someone please tell me how to resize screenshots to post in here? The solutions online make my screenshots super blurry so I hate uploading them
CardView
import SwiftUI
struct CardView: View {
let card: Card
var removal: (() -> Void)? = nil
#State private var isShowingAnswer = false
#State private var changeColors = false
#State private var offset = CGSize.zero
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(LinearGradient(colors: [Card.gradCs[Card.selec][0].opacity(1 - Double(abs(offset.width / 50))), Card.gradCs[Card.selec][1].opacity(1 - Double(abs(offset.width / 50)))], startPoint: .topLeading, endPoint: .bottomTrailing))
.background(RoundedRectangle(cornerRadius: 25, style: .continuous).fill(offset.width > 0 ? .green : .red))
.shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:6, x:1, y:8)
VStack(spacing: 20){
Text(card.prompt)
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white.opacity(0.8))
if isShowingAnswer {
Text(card.answer)
.font(.title)
.fontWeight(.semibold)
.foregroundColor(Color(#colorLiteral(red: 0.8947916626930237, green: 0.8666666746139526, blue: 1, alpha: 1)))
}
}
.padding()
.multilineTextAlignment(.center)
}
.frame(width: 450, height: 250)
.rotationEffect(.degrees(Double(offset.width / 5)))
.offset(x: offset.width * 5, y: 0)
.opacity(2 - Double(abs(offset.width / 50)))
.gesture(
DragGesture()
.onChanged { gesture in
offset = gesture.translation
}
.onEnded { _ in
if abs(offset.width) > 100 {
removal?()
} else {
offset = .zero
}
}
)
.onTapGesture {
isShowingAnswer.toggle()
}
}
}
struct CardView_Previews: PreviewProvider {
static var previews: some View {
CardView(card: Card.example)
.previewInterfaceOrientation(.portraitUpsideDown)
}
}
ContentView
import SwiftUI
extension View {
func stacked(at position: Int, in total: Int) -> some View {
let offset = Double(total - position)
return self.offset(x: 0, y: offset * 10)
}
}
struct ContentView: View {
#Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
#State private var cards = Array(repeating: Card.example, count: 10)
#State private var timeRemaining = 100
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
#Environment(\.scenePhase) var scenePhase
#State private var isActive = true
var body: some View {
ZStack {
VStack {
HStack {
Text("\(timeRemaining / 60):\(timeRemaining % 60, specifier: "%02d")")
.font(.title)
.fontWeight(.semibold)
.foregroundColor(.white)
.padding(.horizontal, 20)
.padding(.vertical, 5)
.background(.black.opacity(0.75))
.clipShape(Capsule())
Circle()
.fill(LinearGradient(colors: Card.gradCs[Card.selec], startPoint: .topLeading, endPoint: .bottomTrailing))
.onTapGesture {
withAnimation {
if Card.selec == 0 {
Card.selec = 1
} else {
Card.selec = 0
}
}
}
.frame(width: 40, height: 40)
}
ZStack {
ForEach(0 ..< cards.count, id: \.self) { index in
CardView(card: cards[index]) {
withAnimation {
removeCard(at: index)
print(self.offset())
}
}
.stacked(at: index, in: cards.count)
}
}
.allowsHitTesting(timeRemaining > 0)
if cards.isEmpty {
Button("Start Again", action: resetCards)
.padding()
.background(.white)
.foregroundColor(.black)
.clipShape(Capsule())
}
}
if differentiateWithoutColor {
VStack {
Spacer()
HStack {
Image(systemName: "xmark.circle")
.padding()
.background(.black.opacity(0.7))
.clipShape(Circle())
Spacer()
Image(systemName: "checkmark.circle")
.padding()
.background(.black.opacity(0.7))
.clipShape(Circle())
}
.foregroundColor(.white)
.font(.largeTitle)
.padding()
}
}
}
.onReceive(timer) { time in
guard isActive else { return }
// Use if let when the non-nil case is valid. Use guard when the nil case represents some sort of error.
// use guard when there should only be one result.. use if when you need ELSE to do something
if timeRemaining > 0 {
timeRemaining -= 1
}
}
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
if cards.isEmpty == false {
isActive = true
}
} else {
isActive = false
}
}
}
func removeCard(at index: Int) {
cards.remove(at: index)
if cards.isEmpty {
isActive = false
}
}
func resetCards() {
cards = Array(repeating: Card.example, count: 10)
timeRemaining = 100
isActive = true
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Card
import Foundation
import SwiftUI
struct Card {
let prompt: String
let answer: String
static var example = Card(prompt: "What is the name of Chicago's NFL Team?", answer: "Da Bears")
static var gradCs = [[Color(#colorLiteral(red: 0.6039215922355652, green: 0.49803921580314636, blue: 1, alpha: 1)), Color(#colorLiteral(red: 1, green: 0.49803924560546875, blue: 1, alpha: 1))], [Color(#colorLiteral(red: 0.6039215922355652, green: 1, blue: 1, alpha: 1)), Color(#colorLiteral(red: 0.6039215922355652, green: 0.49803921580314636, blue: 1, alpha: 1))]]
static var selec = 0
}
binding is a possible way to change colors, but I prefer the use of ObservableObject
to manage the set of Cards and their color selection.
The code in my answer shows how to use a ObservableObject CardManager to change all cards color
resulting from your selection in Circle.
// manages the cards and all cards color selection
class CardManager: ObservableObject {
let gradCs = [[Color(#colorLiteral(red: 0.6039215922355652, green: 0.49803921580314636, blue: 1, alpha: 1)), Color(#colorLiteral(red: 1, green: 0.49803924560546875, blue: 1, alpha: 1))], [Color(#colorLiteral(red: 0.6039215922355652, green: 1, blue: 1, alpha: 1)), Color(#colorLiteral(red: 0.6039215922355652, green: 0.49803921580314636, blue: 1, alpha: 1))]]
#Published var cards = [Card]()
#Published var selec = 0
func getColorSet() -> [Color] {
return gradCs[selec]
}
}
struct Card {
let prompt: String
let answer: String
static var example = Card(prompt: "What is the name of Chicago's NFL Team?", answer: "Da Bears")
}
extension View {
func stacked(at position: Int, in total: Int) -> some View {
let offset = Double(total - position)
return self.offset(x: 0, y: offset * 10)
}
}
struct ContentView: View {
#Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
#StateObject var manager = CardManager() // <--- here
#State private var timeRemaining = 100
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
#Environment(\.scenePhase) var scenePhase
#State private var isActive = true
var body: some View {
ZStack {
VStack {
HStack {
Text("\(timeRemaining / 60):\(timeRemaining % 60, specifier: "%02d")")
.font(.title)
.fontWeight(.semibold)
.foregroundColor(.white)
.padding(.horizontal, 20)
.padding(.vertical, 5)
.background(.black.opacity(0.75))
.clipShape(Capsule())
Circle()
.fill(LinearGradient(colors: manager.getColorSet(), startPoint: .topLeading, endPoint: .bottomTrailing))
.onTapGesture {
withAnimation {
if manager.selec == 0 {
manager.selec = 1
} else {
manager.selec = 0
}
}
}
.frame(width: 40, height: 40)
}
ZStack {
ForEach(0 ..< manager.cards.count, id: \.self) { index in
CardView(card: manager.cards[index]) {
withAnimation {
removeCard(at: index)
print(self.offset())
}
}
.stacked(at: index, in: manager.cards.count)
}
}
.allowsHitTesting(timeRemaining > 0)
if manager.cards.isEmpty {
Button("Start Again", action: resetCards)
.padding()
.background(.white)
.foregroundColor(.black)
.clipShape(Capsule())
}
}
if differentiateWithoutColor {
VStack {
Spacer()
HStack {
Image(systemName: "xmark.circle")
.padding()
.background(.black.opacity(0.7))
.clipShape(Circle())
Spacer()
Image(systemName: "checkmark.circle")
.padding()
.background(.black.opacity(0.7))
.clipShape(Circle())
}
.foregroundColor(.white)
.font(.largeTitle)
.padding()
}
}
}
.onReceive(timer) { time in
guard isActive else { return }
// Use if let when the non-nil case is valid. Use guard when the nil case represents some sort of error.
// use guard when there should only be one result.. use if when you need ELSE to do something
if timeRemaining > 0 {
timeRemaining -= 1
}
}
.onChange(of: scenePhase) { newPhase in
if newPhase == .active {
if manager.cards.isEmpty == false {
isActive = true
}
} else {
isActive = false
}
}
.onAppear {
manager.cards = Array(repeating: Card.example, count: 10) // <--- here
}
.environmentObject(manager) // <--- here
}
func removeCard(at index: Int) {
manager.cards.remove(at: index)
if manager.cards.isEmpty {
isActive = false
}
}
func resetCards() {
manager.cards = Array(repeating: Card.example, count: 10)
timeRemaining = 100
isActive = true
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct CardView: View {
#EnvironmentObject var manager: CardManager // <--- here
let card: Card
var removal: (() -> Void)? = nil
#State private var isShowingAnswer = false
#State private var changeColors = false
#State private var offset = CGSize.zero
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(LinearGradient(colors: [manager.getColorSet()[0].opacity(1 - Double(abs(offset.width / 50))), manager.getColorSet()[1].opacity(1 - Double(abs(offset.width / 50)))], startPoint: .topLeading, endPoint: .bottomTrailing))
.background(RoundedRectangle(cornerRadius: 25, style: .continuous).fill(offset.width > 0 ? .green : .red))
.background(RoundedRectangle(cornerRadius: 25, style: .continuous).fill(offset.width > 0 ? .green : .red))
.shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:6, x:1, y:8)
VStack(spacing: 20){
Text(card.prompt)
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white.opacity(0.8))
if isShowingAnswer {
Text(card.answer)
.font(.title)
.fontWeight(.semibold)
.foregroundColor(Color(#colorLiteral(red: 0.8947916626930237, green: 0.8666666746139526, blue: 1, alpha: 1)))
}
}
.padding()
.multilineTextAlignment(.center)
}
.frame(width: 450, height: 250)
.rotationEffect(.degrees(Double(offset.width / 5)))
.offset(x: offset.width * 5, y: 0)
.opacity(2 - Double(abs(offset.width / 50)))
.gesture(
DragGesture()
.onChanged { gesture in
offset = gesture.translation
}
.onEnded { _ in
if abs(offset.width) > 100 {
removal?()
} else {
offset = .zero
}
}
)
.onTapGesture {
isShowingAnswer.toggle()
}
}
}
I Created Floating Menu in SwiftUI, but i am stuck in one issue, When press on bottom right plus button i open floating menu items and again press on plus button hide that floating menu items, but when press on menu items it will not hide that menu items.
Below is my code
MapContainerUIView.swift
struct MapContainerUIView: View {
let flotingMenuArray = [
MenuItemModel(title: "Camera", icon: "camera.fill"),
MenuItemModel(title: "Photo", icon: "photo.on.rectangle"),
MenuItemModel(title: "Share", icon: "square.and.arrow.up.fill")
]
var body: some View {
NavigationView{
ZStack {
FloatingMenu(dataSource: flotingMenuArray)
}
}
}
func floatingButtonAction(index: Int){
print("Floating item tap", index)
}
}
FloatingMenu.swift
struct FloatingMenu: View {
init() {
self.dataSource = []
}
init(dataSource: [MenuItemModel]) {
self.dataSource = dataSource
}
#State var isMenuShow = false
var dataSource: [MenuItemModel]
var body: some View {
ZStack(alignment: .trailing){
if isMenuShow{
Button(action: {
self.showMenu()
}) {
Text("")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.black)
.opacity(0.3)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
}
HStack{
Spacer()
VStack(alignment: .trailing, content: {
Spacer()
ForEach(0..<dataSource.count) { index in
if isMenuShow {
MenuItems(menuItemData: dataSource[index], index: index)
}
}
Button(action: {
self.showMenu()
}) {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 60, height: 60)
.foregroundColor(Color.white)
}
.background(Color.black)
.cornerRadius(35)
})
.shadow(color: .gray, radius: 4, x: 1, y: 1)
.padding(.init(top: 0, leading: 20, bottom: 20, trailing: 20))
}
}
}
func showMenu() {
self.isMenuShow.toggle()
}
}
MenuItems.swift
class MenuItemModel : Identifiable{
var id = UUID()
var title : String = ""
var icon : String = ""
init(title: String, icon: String) {
self.title = title
self.icon = icon
}
}
struct MenuItems: View {
var mapContainer = MapContainerUIView()
var menuItemData: MenuItemModel
var index : Int
var body: some View {
ZStack {
HStack{
Text(menuItemData.title)
.foregroundColor(.white)
.shadow(color: .gray, radius: 3, x: 1, y: 1)
Button(action: {
FloatingMenu().isMenuShow = false
print("button tap: ", menuItemData.title)
self.mapContainer.floatingButtonAction(index: index)
}) {
ZStack {
Circle()
.foregroundColor(Color.white)
.frame(width: 45, height: 45)
.shadow(color: .gray, radius: 3, x: 1, y: 1)
Image(systemName: menuItemData.icon)
.imageScale(.large)
.foregroundColor(.black)
}
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 10))
}
}
}
}
}
I want to hide floating menu when press on menu items, please someone guide me.
Right now, you're trying to set isMenuShow on a new instance of FloatingMenu, which is why it isn't working.
One solution is to pass a Binding from the original FloatingMenu instance.
struct MenuItems: View {
#Binding var isMenuShow : Bool //<-- Here
var mapContainer = MapContainerUIView()
var menuItemData: MenuItemModel
var index : Int
var body: some View {
ZStack {
HStack{
Text(menuItemData.title)
.foregroundColor(.white)
.shadow(color: .gray, radius: 3, x: 1, y: 1)
Button(action: {
self.isMenuShow = false //<-- Here
print("button tap: ", menuItemData.title)
self.mapContainer.floatingButtonAction(index: index)
}) {
And, in FloatingMenu:
if isMenuShow {
MenuItems(isMenuShow: $isMenuShow, //<-- Here
menuItemData: dataSource[index],
index: index)
}
Another solution would be to provide a closure as an argument to MenuItems that closes the menu:
struct MenuItems: View {
var closeMenu : () -> Void //<-- Here
var mapContainer = MapContainerUIView()
var menuItemData: MenuItemModel
var index : Int
var body: some View {
ZStack {
HStack{
Text(menuItemData.title)
.foregroundColor(.white)
.shadow(color: .gray, radius: 3, x: 1, y: 1)
Button(action: {
closeMenu() //<-- Here
print("button tap: ", menuItemData.title)
//self.mapContainer.floatingButtonAction(index: index)
}) {
if isMenuShow {
MenuItems(closeMenu: { self.isMenuShow = false },
menuItemData: dataSource[index],
index: index)
}
How can I cancel the text field editing. I want no other editing on the TextField when the selection is made. I tried it myself, but I couldn't.
struct profile: View {
#State private var iliskiDurumlari: [String] = ["Evli", "Bekar", "Ayrı", "anan"]
#State private var iliskiVisible = false
#State private var iliski = ""
var body: some View {
VStack {
TextField("İlişki Durumu Seçiniz..", text: $iliski)
.frame(width: 300, height: 50, alignment: .center)
.padding(5)
.font(Font.system(size: 15, weight: .medium, design: .serif))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(red: 45 / 255, green: 0 / 255, blue: 112 / 255), lineWidth: 1)
)
.actionSheet(isPresented: $iliskiVisible, content: actionSheet)
.onTapGesture {
self.iliskiVisible.toggle()
}
}
}
func actionSheet() -> ActionSheet {
ActionSheet(
title: Text("Bir İlişki Durumu Seçiniz"),
message: Text("Aşagıda"),
buttons: iliskiDurumlari.map { value in
ActionSheet.Button.default(Text(value), action: {
self.iliski = value
})
}
)
}
}
If you don't need user input (show keyboard) for this particular field, you can use Text instead:
var body: some View {
VStack {
Text(iliski) // <- change here
.frame(width: 300, height: 50, alignment: .center)
.padding(5)
.font(Font.system(size: 15, weight: .medium, design: .serif))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(red: 45 / 255, green: 0 / 255, blue: 112 / 255), lineWidth: 1)
)
.actionSheet(isPresented: $iliskiVisible, content: actionSheet)
.onTapGesture {
self.iliskiVisible.toggle()
}
}
}
and instead of placeholder add initial value:
#State private var iliski = "İlişki Durumu Seçiniz.."
If you want to dismiss the keyboard and cancel editing of the textfield when the user taps on the Action Sheet then in SwiftUI you need this code:
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) reference here: https://www.hackingwithswift.com/quick-start/swiftui/how-to-dismiss-the-keyboard-for-a-textfield
So your code must be like that:
func actionSheet() -> ActionSheet {
ActionSheet(
title: Text("Bir İlişki Durumu Seçiniz"),
message: Text("Aşagıda"),
buttons: iliskiDurumlari.map { value in
ActionSheet.Button.default(Text(value), action: {
self.iliski = value
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
})
}
)
}
}
Add your text field inside the button and disable the text field interaction.
var body: some View {
VStack {
Button(action: {
self.iliskiVisible.toggle()
}, label: {
TextField("İlişki Durumu Seçiniz..", text: $iliski)
.frame(width: 300, height: 50, alignment: .center)
.padding(5)
.font(Font.system(size: 15, weight: .medium, design: .serif))
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color(red: 45 / 255, green: 0 / 255, blue: 112 / 255), lineWidth: 1)
)
.allowsHitTesting(false)//<- Disable interection
})
.actionSheet(isPresented: $iliskiVisible, content: actionSheet)
}
}
I am fairly new to Swift, so please bear with me.
screenshot when nothing's tapped
screenshot when one button is tapped
I am trying to turn the other buttons, which are not tapped, inactive and change the opacity to 0.5.
So far I have tried using the $bindings but that did not work the way I wanted it to.
Here is the Code for my SelectionButtons:
struct SelectionButton: View {
var buttonText = "Selection Button"
var buttonColor = Color.white
var buttonWidth: CGFloat = 150
var active = false
var body: some View {
ZStack {
if active {
RoundedRectangle(cornerRadius: 45)
.frame(width: buttonWidth, height: 50)
.foregroundColor(Color("neonGreen"))
.shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:9, x:0, y:0)
Text(buttonText)
.font(.system(size: 18))
.foregroundColor(.black)
.bold()
}else{
RoundedRectangle(cornerRadius: 45)
.frame(width: buttonWidth, height: 50)
.foregroundColor(buttonColor)
.shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.25)), radius:9, x:0, y:0)
Text(buttonText)
.font(.system(size: 18))
.foregroundColor(.black)
}
}
}
And this is how I use them:
#State var gelbesBlatt = false
var body: some View {
NavigationView {
Button(action: {
self.gelbesBlatt.toggle()
}, label: {SelectionButton(buttonText: "gelb", buttonColor: .white, buttonWidth: 150, active: gelbesBlatt)
})
}
}
Thank you!
If you have an idea how I could add combinations, so that specific buttons which belong together (like "Ganzes Blatt > gelb" and "Ränder > braun") can be selected together, that would be awesome!
Check this:
#State var gelbesBlatt = false
#State var btnBraun = false
var body: some View {
NavigationView {
HStack {
Button(action: {
self.toggleButton(button: 0)
}, label: {SelectionButton(buttonText: "gelb", buttonColor: .white, buttonWidth: 150, active: gelbesBlatt)
})
Button(action: {
self.toggleButton(button: 1)
}, label: {SelectionButton(buttonText: "braun", buttonColor: .white, buttonWidth: 150, active: btnBraun)
})
}
}
}
func toggleButton(button: Int) {
if(button == 0) {
self.gelbesBlatt = true
self.btnBraun = false
} else {
self.gelbesBlatt = false
self.btnBraun = true
}
self.gelbesBlatt.toggle()
self.btnBraun.toggle()
}