I am trying to insert a row in my table when I click my "Add Sets" button. TableRow is a very simple view that is just an HStack with a text field and two text input fields. I am stuck and there isn't much online for this issue. Thank You
struct ExerciseCard: View {
#State private var exercise : String = "Bench Press"
#State private var sets : Int = 1
var body: some View {
VStack{
TextField("Enter Exercise", text: $exercise).textFieldStyle(RoundedBorderTextFieldStyle())
.frame(width: 300)
.multilineTextAlignment(.center)
HStack{
Group{
Text("Set")
Text("Weight")
Text("Reps")
}.padding(.horizontal, 30)
}
VStack{
ForEach(0..<sets){ number in
TableRow()
}
}.padding(.bottom, 5)
Button(action: {
self.sets += 1
}) {
Text("Add Set")
.frame(minWidth: 200)
.padding(.vertical, 5)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(20)
}
}
.padding()
.background(Color.blue.opacity(0.6))
.cornerRadius(20)
}
}
struct ExerciseCard_Previews: PreviewProvider {
static var previews: some View {
ExerciseCard()
}
}
Related
I want to recreate system picker behavioral with two options in wheels with SwiftUI and faced ton of problem. Some of this I solved but some still unsolved. I have pop-ups with different views inside. One of the view it's a DatePicker with displayedComponents: .hourAndMinute. And other one is two Pickers inside HStack. My question is how to make Pickers make look like in system: without white spacing between?
struct MultyPicker: View {
#State var value = 1
#State var value2 = 1
var body: some View {
ZStack(alignment: .bottom) {
Color.black.opacity(0.5)
ZStack {
VStack {
Text("Header")
.font(.title3)
.fontWeight(.bold)
HStack(spacing: 0) {
Picker(selection: $value, label: Text("")) {
ForEach(1..<26) { number in
Text("\(number)")
.tag("\(number)")
}
}
.pickerStyle(WheelPickerStyle())
.compositingGroup()
.clipped(antialiased: true)
Picker(selection: $value2, label: Text("")) {
ForEach(25..<76) { number in
Text("\(number)")
.tag("\(number)")
}
}
.pickerStyle(WheelPickerStyle())
.compositingGroup()
.clipped(antialiased: true)
}
}
.padding()
.background(
RoundedRectangle(cornerRadius: 34)
.foregroundColor(.white)
)
}
.padding(.horizontal)
.padding(.bottom, 50)
}
.edgesIgnoringSafeArea([.top, .horizontal])
}
}
// This extension for correct touching area
extension UIPickerView {
open override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric, height: super.intrinsicContentSize.height)
}
}
Want to achive looks like that with one grey line in selected value
//
// Test2.swift
// Test
//
// Created by Serdar Onur KARADAĞ on 26.08.2022.
//
import SwiftUI
struct Test2: View {
#State var choice1 = 0
#State var choice2 = 0
var body: some View {
ZStack {
Rectangle()
.fill(.gray.opacity(0.2))
.cornerRadius(30)
.frame(width: 350, height: 400)
Rectangle()
.fill(.white.opacity(1))
.cornerRadius(30)
.frame(width: 300, height: 350)
VStack {
Text("HEADER")
HStack(spacing: 0) {
Picker(selection: $choice1, label: Text("C1")) {
ForEach(0..<10) { n in
Text("\(n)").tag(n)
}
}
.pickerStyle(.wheel)
.frame(minWidth: 0)
.clipped()
Picker(selection: $choice2, label: Text("C1")) {
ForEach(0..<10) { n in
Text("\(n)").tag(n)
}
}
.pickerStyle(.wheel)
.frame(minWidth: 0)
.clipped()
}
}
}
}
}
struct Test2_Previews: PreviewProvider {
static var previews: some View {
Test2()
}
}
SwiftUI multi-component Picker basically consists of several individual Picker views arranged horizontally. Therefore, we start by creating an ordinary Picker view for our first component. I am using Xcode version 13.4.1(iOS 15.0).
import SwiftUI
struct ContentView: View {
#State var hourSelect = 0
#State var minuteSelect = 0
var hours = [Int](0..<24)
var minutes = [Int](0..<60)
var body: some View {
ZStack {
Color.black
.opacity(0.5)
.ignoresSafeArea()
.preferredColorScheme(.light)
Rectangle()
.fill(.white.opacity(1))
.cornerRadius(30)
.frame(width: 300, height: 350)
VStack {
Text("Header")
HStack(spacing: 0) {
Picker(selection: $hourSelect, label: Text("")) {
ForEach(0..<self.hours.count) { index in
Text("\(self.hours[index])").tag(index)
}
}
.pickerStyle(.wheel)
.frame(minWidth: 0)
.compositingGroup()
.clipped()
Picker(selection: $minuteSelect, label: Text("")) {
ForEach(0..<self.minutes.count) { index in
Text("\(self.minutes[index])").tag(index)
}
}
.pickerStyle(.wheel)
.frame(minWidth: 0)
.compositingGroup()
.clipped()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Output :
I'm trying to implement such dropdown menu https://imgur.com/a/3KcKhv4 but could do it like that https://imgur.com/67bKU5Q
The problem is that selected option doesn't have to repeated. Could you please help me how can I do dropdown menu like in design?
class MenuViewModel: ObservableObject {
#Published var selectedOption: String = "За все время"
}
struct DropdDown: View {
let buttons = ["За все время", "За день", "За неделю"]
#ObservedObject var viewModel = MenuViewModel()
#State var expanded: Bool = false
var body: some View {
VStack(spacing: 30) {
Button {
self.expanded.toggle()
} label: {
Text(viewModel.selectedOption)
.fontWeight(.bold)
.foregroundColor(Color.black)
Spacer()
Image(systemName: "chevron.down")
.foregroundColor(Color.white)
}
if expanded {
ForEach(self.buttons, id: \.self) { buttonTitle in
VStack(alignment: .leading, spacing: 5) {
Button {
self.expanded.toggle()
viewModel.selectedOption = buttonTitle
} label: {
Text(buttonTitle)
.padding(10)
}
.foregroundColor(Color.black)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
.padding()
.frame(width: 300)
.background(Color.gray)
.cornerRadius(10)
}
}
struct DropdDown_Previews: PreviewProvider {
static var previews: some View {
DropdDown()
}
}
Just create computed property array in DropdDown View for store buttons without selectedOption
var availableButtons: [String] {
return buttons.filter { $0 != viewModel.selectedOption }
}
And use in ForEach loop instead buttons array
ForEach(self.availableButtons, id: \.self) {}
I am trying to make a stock control system in SwiftUI where users can add an ingredient and then ad an amount and then select a unit of measurement(kg, g, l ,ml).
The app allows them to click a button which allows them to add an ingredient to a text-box which is created and then their input is added to a list.
I am having trouble allowing the user to also type in a number in a text-box next to the ingredient text-box and making the picker clickable
Here is my code
import SwiftUI
struct UploadView2: View {
#State var ingredients = [String]()
#State var amount = [String]()
#State var choices = ["g", "kg", "ml", "l"]
#State var choosen: String = ""
#EnvironmentObject var viewRouter: ViewRouter
func getBinding(forIndex index: Int) -> Binding<String> {
return Binding<String>(get: { ingredients[index] },
set: { ingredients[index] = $0 })
}
var body: some View {
VStack{
HStack{
Button {
print("Going Back")
viewRouter.currentPage = .UploadView
} label: {
Image(systemName: "arrow.left")
.font(.system(size: 30))
.foregroundColor(.black)
}
.padding(.horizontal)
Spacer()
Text("Add Ingredients")
.font(.system(size: 30))
.fontWeight(.bold)
Spacer()
Button {
print("Saved")
} label: {
Image(systemName: "bookmark")
.font(.system(size: 30))
.foregroundColor(.black)
}
.padding()
}
Form {
ForEach(0..<ingredients.count, id: \.self) { index in
HStack {
Button(action: { ingredients.remove(at: index) }) {
Image(systemName: "minus.circle.fill")
.foregroundColor(.red)
.padding(.horizontal)
}
TextField("Ingredient", text: getBinding(forIndex: index))
Picker("", selection: $choosen){
ForEach(choices, id: \.self) { i in
Text("\(i)").tag(i)
}
}
}
}
Button(action: { ingredients.append("") }) {
HStack {
Image(systemName: "plus")
.foregroundColor(.black)
.padding(.horizontal)
Text("add an ingredient")
.foregroundColor(.black)
}
}
}
Button {
//change view router
//add data to data class
viewRouter.currentPage = .UploadView3
} label: {
Label("next", systemImage: "arrow.right")
}
.padding()
.frame(width: 100)
.foregroundColor(Color.white)
.background(Color.red)
.cornerRadius(8)
}
}
}
struct UploadView2_Previews: PreviewProvider {
static var previews: some View {
UploadView2()
.previewDevice(PreviewDevice(rawValue: "iPhone 13"))
.previewInterfaceOrientation(.portrait)
UploadView2()
.previewDevice(PreviewDevice(rawValue: "iPhone 8"))
}
}
When i click on my click it removes the text-box like the dismiss button
My overall goal is to have a text-box to enter an ingredient and then a text-box to enter an amount and then a picker to select a unit of measurement.
How can I achieve this using my current code as much as I can?
to be able to "select" your Picker, you could try this approach, as shown in this example code:
struct ContentView: View {
#State var ingredient = ""
#State var amount = ""
#State var choosen = ""
#State var choices = ["g", "kg", "ml", "l"]
var body: some View {
HStack {
TextField("Ingredient", text: $ingredient) // <-- or your getBinding thing
TextField("Amount", text: $amount)
Picker("", selection: $choosen){
ForEach(choices, id: \.self) { i in
Text("\(i)").tag(i)
}
}
.pickerStyle(.inline)
.frame(width: 55)
.clipped() // <-- here
}
}
}
I'm writing a widget with WidgetKit and I want to make the widget's content is clickable. For example, if users click to standings, I want to open the standings tab when the app becomes active.
I tried to use notification between the app and widget but the tap gesture is not working, I added print inside of the tap gesture but it did not appear in the console. Also, I added the same app group to both of them.
WidgetView:
struct LargeWidget : View {
#State var standings : [StandingsTable]
var body: some View {
VStack(alignment:.leading){
if standings.count > 0{
HStack(spacing:5){
Text("#").foregroundColor(.gray)
.frame(width: 30)
Text("Team".localized).foregroundColor(.gray)
Spacer()
Text("_D".localized).foregroundColor(.gray)
.frame(width: 30)
Text("_L".localized).foregroundColor(.gray)
.frame(width: 30)
Text("_W".localized).foregroundColor(.gray)
.frame(width: 30)
Text("_P".localized).foregroundColor(.gray)
.frame(width: 30)
}
Divider()
ForEach(0..<5, id: \.self) { i in
HStack(spacing:5){
Text(standings[i].rank)
.font(.system(size: 15))
.padding(.vertical, 3)
.frame(width: 30)
.background(Color(UIColor.systemBackground))
.cornerRadius(4)
Text(standings[i].name)
.lineLimit(1)
.padding(.leading, 5)
Spacer()
Text(standings[i].drawn)
.frame(width: 30)
Text(standings[i].lost)
.frame(width: 30)
Text(standings[i].won)
.frame(width: 30)
Text(standings[i].points)
.frame(width: 30)
}
.padding(.vertical, 5)
.background(standings[i].name == "Besiktas" ? Color(UIColor.systemGray6) : Color.clear)
.cornerRadius(8)
}
Spacer(minLength: 0)
}else{
Text("Large")
.padding()
}
}.padding()
.onTapGesture {
print("clicked to standings")
DispatchQueue.main.async(execute: {
NotificationCenter.default.post(name: NSNotification.Name("standings"), object: nil, userInfo: nil)
})
}
}
}
and here ContentView in app:
import SwiftUI
extension NSNotification {
static let openStandings = NSNotification.Name.init("standings")
}
struct ContentView: View {
#State var show: Bool = false
var body: some View {
NavigationView{
Text("Hello, world!")
.padding()
}.sheet(isPresented: self.$show) {
VStack{
Text("Notification")
.padding()
}
}
.onReceive(NotificationCenter.default.publisher(for: NSNotification.openStandings))
{ obj in
self.show.toggle()
}
}
}
Screenshot of Widget
Okay I created a new project with SwiftUI Environments (not old way AppDelegate and SceneDelegate).
Then I use Link for tap actions and I got it with .onOpenURL modifier in ContentView. It works :)
ContentView:
import SwiftUI
enum SelectedTab: Hashable {
case home
case standings
case options
}
struct ContentView: View {
#State var selectedTab: SelectedTab = .home
var body: some View {
TabView(selection: self.$selectedTab) {
Text("Home")
.tabItem {
Image(systemName: "house")
.renderingMode(.template)
Text("Home")
}.tag(SelectedTab.home)
Text("Standings")
.tabItem {
Image(systemName: "list.number")
.renderingMode(.template)
Text("Standings")
}.tag(SelectedTab.standings)
Text("Options")
.tabItem {
Image(systemName: "gear")
.renderingMode(.template)
Text("Options")
}.tag(SelectedTab.options)
.onOpenURL { (url) in
if url.absoluteString == "widget-deeplink://standings"{
self.selectedTab = .standings
}
}
}
}
}
Link usage example in Widget:
Link(destination: URL(string: "widget-deeplink://standings")!) {
Text("Link Test")
}
I am trying to add some filter options to sit at the top of my view, above the NavigationView. I wrote the following code that mostly does what I want, however it disabled the ability to click on the rows to get to the detailed view. I assume this is because my filter buttons are on top of the ZStack, but I'm not sure how else to get this to work.
Here is the code I wrote:
import SwiftUI
struct BonusList: View {
var bonuses = sampleBonusData
#State var showSettings = false
#State var showBonuses = false
#State var bonusEarned = true
#State var showStatePicker = false
#State var showCategoryPicker = false
var body: some View {
ZStack {
NavigationView {
List(bonuses) { item in
NavigationLink(destination: BonusDetail(bonusName: item.bonusName, bonusCode: item.bonusCode, city: item.city, sampleImage: item.sampleImage)) {
HStack(spacing: 12.0) {
Image(item.sampleImage)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 60, height: 60)
.background(Color.white)
.cornerRadius(15)
VStack(alignment: .leading) {
HStack {
Text(item.bonusName)
.font(.headline)
Spacer()
Image(systemName: "checkmark.shield")
.opacity(self.bonusEarned ? 100 : 0)
}
Text("\(item.city), \(item.state)")
.font(.subheadline)
.frame(height: 25.0)
HStack {
Text(item.bonusCategory)
.font(.caption)
.fontWeight(.bold)
.foregroundColor(.gray)
.padding(.top, 4)
Spacer()
Text(item.bonusCode)
.font(.caption)
.fontWeight(.bold)
.foregroundColor(.gray)
.padding(.top, 4)
}
}
}
}
}
.navigationBarTitle(Text("Bonuses"))
// .navigationBarHidden(true)
}
.saturation(self.bonusEarned ? 0 : 1)
HStack {
FilterByCategory(showCategoryPicker: $showCategoryPicker)
Spacer()
FilterByState(showStatePicker: $showStatePicker)
}
StatePicker(showStatePicker: $showStatePicker)
CategoryPicker(showCategoryPicker: $showCategoryPicker)
}
}
}
This is what it looks like when I run it:
If I'm understanding correctly, you have a view or two which sit higher in the ZStack that are off canvas and come in when those buttons are tapped?
You could consider using a modal and setting the view you want to show for each button as the view for the modal. This will keep your views off screen and still allow interaction with your list. Here's what I've done...
On the main view
import SwiftUI
struct MainView: View {
#State private var isPresented = false
var body: some View {
NavigationView {
VStack {
//...
}
//Modal
.sheet(isPresented: $isPresented, content: {
AddItem(showModal: self.$isPresented)
})
}
}
}
The modal's view
import SwiftUI
struct AddItem: View {
#Binding var showModal: Bool
var body: some View {
VStack {
Button(action: {
self.showModal = false
}, label: {
Text("Cancel")
})
}
}
}