I have a Picker within a Form. I don't want to show any label on this Picker, so I set the label to EmptyView(). Though, the UI still presents an empty space where the label would be. I'm looking for a way to remove this space.
var body: some View {
NavigationView{
Form {
...
Section(header: Text("Emails")){
HStack{
Picker(selection: $phoneType, label: EmptyView()){
ForEach(phoneTypes, id: \.self){
Text($0)
}
}
.pickerStyle(.navigationLink)
Spacer()
Link("my#email.com", destination: URL(string: "mailto:my#email.com")!)
}
Button("Add Email") {}
}
...
}
}
.navigationTitle("John Doe")
}
The correct approach is to use labelsHidden() to hide the label of Picker.
Picker(selection: $phoneType, label: EmptyView()){
ForEach(phoneTypes, id: \.self){
Text($0)
}
}
.labelsHidden()
.pickerStyle(.navigationLink)
A possible workaround is using Picker inside Menu:
HStack{
Menu {
Picker("", selection: $phoneType){
ForEach(["Work","Home","Cell"], id: \.self){ type in
Button(type) { phoneType = type }
}
}
} label: {
Text(phoneType).foregroundColor(.secondary)
}
Spacer()
Link("my#email.com", destination: URL(string: "mailto:my#email.com")!)
}
Put the Text in the loop inside an HStack and add a trailing Spacer
var body: some View {
NavigationView{
Form {
...
Section(header: Text("Emails")){
HStack{
Picker(selection: $phoneType, label: EmptyView()){
ForEach(phoneTypes, id: \.self){ t in
HStack {
Text(t)
Spacer()
}
}
}
.pickerStyle(.navigationLink)
Spacer()
Link("my#email.com", destination: URL(string: "mailto:my#email.com")!)
}
Button("Add Email") {}
}
...
}
}
.navigationTitle("John Doe")
}
Related
There was a similar question Center Item Inside Horizontal Stack that I followed the Asperi's basic answer that suited for me ( other answer did not worked, too).
struct HeaderTestView: View {
#State private var currentDate = Date()
var body: some View {
ZStack {
HStack {
HStack {
Button(action: {
}) {
Image(systemName: "arrowtriangle.left.fill")
}
}
Spacer()
HStack {
Button(action: {
}) {
Image(systemName: "arrowtriangle.right.fill")
}
}
}
HStack {
Text("Title")
DatePicker("Date", selection: $currentDate, displayedComponents: [.date])
}
}
}
}
My Center Item are a Text and a DatePicker, everything works as expected until the date picker is placed. The title of DatePicker is placed on the left and date is placed on the right.
Without the DatePicker
With the DatePicker
Any idea to solve this beautifully so that a Text and a DatePicker are close on the center while there are two HStacks that are adjested to on the left and right
Add .fixedSize() to the HStack containing the Text view and DatePicker:
struct ContentView: View {
#State private var currentDate = Date()
var body: some View {
ZStack {
HStack {
HStack {
Button(action: {
}) {
Image(systemName: "arrowtriangle.left.fill")
}
}
Spacer()
HStack {
Button(action: {
}) {
Image(systemName: "arrowtriangle.right.fill")
}
}
}
HStack {
Text("Title")
DatePicker("Date", selection: $currentDate, displayedComponents: [.date])
}
.fixedSize() // here
}
}
}
or add .fixedSize() to the DatePicker.
I have a navigation title for a list view. After navigating back and forth, my navigation title is missing. I am new to swiftui and unable to debug. Kindly help.
var body: some View {
NavigationView {
VStack {
TabView(selection: $choice,
content: {
OPListCell()
IPListCell()
})
.tabViewStyle(PageTabViewStyle())
}
.listStyle(PlainListStyle())
.navigationBarTitle("My Patients")
.toolbar {
ToolbarItem(placement: .principal) {
HStack {
Picker(selection: self.$choice, label: Text("")) {
ForEach(0 ..< self.choices.count) {
Text(self.choices[$0])
}
}
.frame(width: 175)
.pickerStyle(SegmentedPickerStyle())
.padding(.leading, 10)
}
}
}
}
}
}
I'm trying to implement a ZStack inside of navigationBarItems to load a custom alert. Here is my implementation:
var body: some View {
VStack{
List(self.itemsStore.names){ item in
Text("hello")
}
}
.navigationBarItems(trailing: Button(action: {
ZStack {
ItemsAlert(isShown: $isPresented, text: $text)
}
}, label: {
Image(systemName: "plus")
}))
}
On this line I'm getting this error:
Any of you knows why I'm getting this warning? or if is a work around this error?
I'll really appreciate your help
You cannot put SwiftUI view in closure - it has not sense, view should be in the view hierarchy, button can activate states to manipulate with views, like
var body: some View {
ZStack {
ItemsAlert(isShown: $isPresented, text: $text)
VStack{
List(self.itemsStore.names){ item in
Text("hello")
}
}
}
.navigationBarItems(trailing: Button(action: {
self.isPresented = true // << activate state
}, label: {
Image(systemName: "plus")
}))
}
I've added a .toolbar to the top level of a NavigationView that will eventually be used to select items in a list without using swipe gestures (up button, down button, etc.). I also have a .navigationBar going on, to access other views for Account and Settings.
For the most part it's looking really good, but when I follow a NavigationLink (in .navigationBarItems) within NavigationView, and then use the built-in back navigation, my .toolbar disappears from the top level.
Am I putting the .toolbar in the wrong place? It feels like a problem with .navigationViewStyle(StackNavigationViewStyle()) because when I comment that out, the toolbar will not disappear upon navigation... but I don't like how the default behavior works in landscape so I'm relying on it.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
Group {
Section(header: Text("List Items").foregroundColor(.gray).font(.footnote)) {
Text("List Item One")
Text("List Item Two")
Text("List Item Three")
}
}
}.navigationTitle("Top Level List").navigationBarTitleDisplayMode(.inline)
.ignoresSafeArea(.all)
// MARK: NAVBAR
.navigationBarItems(
leading:
NavigationLink(destination: UserView()) {
Image(systemName: "person.crop.circle").font(.title2)
},
trailing:
NavigationLink(destination: SettingsView()) {
Image(systemName: "gear").font(.title2)
})
//MARK: - CONTENT NAV
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button(action: {}, label: {Label("Mute", systemImage: "speaker.slash.fill")})
Spacer()
Button(action: {}, label: {Label("Repeat", systemImage: "arrow.clockwise")})
Spacer()
Button(action: {}, label: {Label("Previous", systemImage: "arrow.up")})
Spacer()
Button(action: {}, label: {Label("Next", systemImage: "arrow.down")})
Spacer()
Button(action: {}, label: {Label("Select", systemImage: "arrow.right")})
}
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct UserView: View {
#State private var username: String = ""
#State private var password: String = ""
var body: some View {
Form {
TextField("Username", text: $username)
SecureField("Password", text: $password)
}
.navigationBarTitle("Account").font(.subheadline)
}
}
struct SettingsView: View {
#State private var setting1: String = ""
#State private var setting2: String = ""
var body: some View {
Form {
TextField("Setting One", text: $setting1)
SecureField("Setting Two", text: $setting2)
}
.navigationBarTitle("Settings").font(.subheadline)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
You right, it's in a wrong place. Here is how it should be if you need a toolbar always shown:
struct ContentView: View {
var body: some View {
NavigationView {
List {
Group {
Section(header: Text("List Items").foregroundColor(.gray).font(.footnote)) {
Text("List Item One")
Text("List Item Two")
Text("List Item Three")
}
}
}.navigationTitle("Top Level List").navigationBarTitleDisplayMode(.inline)
.ignoresSafeArea(.all)
// MARK: NAVBAR
.navigationBarItems(
leading:
NavigationLink(destination: UserView()) {
Image(systemName: "person.crop.circle").font(.title2)
},
trailing:
NavigationLink(destination: SettingsView()) {
Image(systemName: "gear").font(.title2)
})
//MARK: - CONTENT NAV
}.navigationViewStyle(StackNavigationViewStyle())
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button(action: {}, label: {Label("Mute", systemImage: "speaker.slash.fill")})
Spacer()
Button(action: {}, label: {Label("Repeat", systemImage: "arrow.clockwise")})
Spacer()
Button(action: {}, label: {Label("Previous", systemImage: "arrow.up")})
Spacer()
Button(action: {}, label: {Label("Next", systemImage: "arrow.down")})
Spacer()
Button(action: {}, label: {Label("Select", systemImage: "arrow.right")})
}
}
}
}
I have created a reusable component that has a picker, textfield and button within a form. However, with the button present, a tap on the picker field does not go to the picker. Rather it executes the button code. The TextField works fine. If I remove the button code, the proper behavior will occur with the picker. So the question is how to have both elements within this component? Please note that the preview adds the Navigation and Form which would otherwise come from the parent view.
var body: some View {
HStack {
if !showFee {
Spacer()
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
self.showFee.toggle()
}
}) {
Image(systemName: "plus.circle")
.font(.largeTitle)
}
Spacer()
} else {
VStack(spacing:20) {
Picker(selection: $feeSelection, label: Text("Fee Type")) {
ForEach(0 ..< fees.count) {
Text(self.fees[$0])
}
}
TextField("Fee Amount: $", value: $feeAmount, formatter: NumberFormatter.currency)
.keyboardType(.decimalPad)
Divider()
Button(action: {
withAnimation(.easeInOut(duration: 0.3)) {
self.showFee.toggle()
}
}) {
Image(systemName: "trash.circle.fill")
.font(.largeTitle)
.foregroundColor(.red)
}
}
}
}
.padding()
}
}
struct FeeCell_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
Form {
FeeCell()
}
}
}
}
What you can do is to apply the PlainButtonStyle to your button. This will stop the button's tap covering to the whole cell in the Form:
Button(action: {}) {
Text("Button")
}
.buttonStyle(PlainButtonStyle())