When I present a sheet with SwiftUI, everything gets bolded. If I swipe a bit, the bold goes away.
Example:
.navigationBarItems(leading:
Button(action:{
self.isSheetPresented.toggle()
}) {
Text("Display")
}
.frame(width: 25, height: 45)
.sheet(isPresented: $isSheetPresented) {
Textfield("Hello", text: $binding)
})
}
Is there an easy workaround besides applying
.fontWeight(.regular) or .font(.body)
to everything?
PS: running Xcode Version 12.2 beta 3 (12B5035g) on MacOS 11.0 Beta (20A5395g)
Try to move sheet out of navigationBarItems and attach to some view inside body, like
// ... other views
.navigationBarItems(leading:
Button(action:{
self.isSheetPresented.toggle()
}) {
Text("Display")
}
.frame(width: 25, height: 45)
)
...
} // end of NavigationView
.sheet(isPresented: $isSheetPresented) { // << here !!
Textfield("Hello", text: $binding)
}
Ok, I did some tests:
.navigationBarItems(leading:
Button(action: {self.showingSettings = true}) {
Image(systemName: "gear")
}
//.sheet(isPresented: $showingAddItem, content: {
// AddView(expirations: self.expirations)
,
trailing:
Button(action: {self.showingAddItem = true}) {
Image(systemName: "plus")
}
//.sheet(isPresented: $showingSettings, content: {
// SettingsView()
)
.sheet(isPresented: $showingAddItem, content: {
AddView(expirations: self.expirations)
})
.sheet(isPresented: $showingSettings, content: {
SettingsView()
})
But by doing so the trailing button is not working, only the leading one
Related
I'm trying to figure out why the navigation title is not working with some devices, but I'm not able to figure out this issue. Can any one please help me to find out this issue, why the navigation title shows only the first 3 letters and after showing?
I have attached the Screenshot also please check.
iPhone 11 Device
iPhone 11 Simulator
Code:-
var body: some View {
ZStack {
Color.init(ColorConstantsName.MainThemeBgColour)
.ignoresSafeArea()
GeometryReader { geo in
ScrollView(.vertical) {
Text("Testing")
}
}
}
.navigationBarBackButtonHidden(true)
.navigationTitle(CommonAllString.BlankStr)
.navigationViewStyle(.stack)
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(leading:AnyView(leadingButton),trailing:AnyView(self.trailingButton))
.foregroundColor(Color.white)
}
var trailingButton: some View {
HStack {
Image(systemName: ImageConstantsNameForChatScreen.PersonImg)
.padding(.trailing)
Image(ImageConstantsName.DTRShareIconImg)
.resizable().frame(width: 20, height: 20)
}
}
Below Code Working:-
struct PSScreen: View {
var body: some View {
ZStack {
Color.init("Colour")
.ignoresSafeArea()
VStack{
Text("PSScreen")
}
}
.navigationBarBackButtonHidden(true)
.navigationBarTitle("", displayMode: .inline)
.navigationViewStyle(.stack)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
leadingButton.frame(width: 50, alignment: .leading)
}
ToolbarItem(placement: .navigationBarTrailing) {
trailingButton
}
}.foregroundColor(Color.white)
}
var leadingButton: some View {
HStack{
Text("Profile")
}
}
var trailingButton: some View {
HStack {
Image(systemName: "Person")
.padding(.trailing)
Image("Share")
.resizable().frame(width: 20, height: 20)
}
}
}
I have a list item with some text stuff, navigationLink and button to show .sheet.When I click on either navigation link or show sheet button both navigation destination and the sheet appear.How to avoid this behaviour?
Note: This is minimal produceable code.
struct ContentView: View {
#State var shouldSheetShow:Bool = false;
var body: some View {
NavigationView{
List{
VStack(alignment: .leading){
Text("Some Text Stuff")
NavigationLink(
destination: Text("navigation link"),
label: {
Text("Navigate To some view")
.background(Color.green)
})
Button(action: {
self.shouldSheetShow = true
}, label: {
HStack{
Text("Show sheet")
}
.background(Color.blue)
.sheet(isPresented: $shouldSheetShow, content: {
Text("sheet")
})
})
}
.frame(width: 300, height: 150, alignment: .center)
.background(Color.gray)
}
}
}
}
A possible solution is to replace the Button with Text plus an onTapGesture
Replace
Button(action: {
self.shouldSheetShow = true
}, label: {
HStack{
Text("Show sheet")
}
.background(Color.blue)
.sheet(isPresented: $shouldSheetShow, content: {
Text("sheet")
})
})
with
Text("Show sheet")
.background(Color.blue)
.sheet(isPresented: $shouldSheetShow, content: {
Text("sheet")
})
.onTapGesture {
self.shouldSheetShow = true
}
When I use toolbar group in SwiftUI, there is too much space between elements. I put it with HStack in iOS 13, it is ok. But when I put it with toolbar in iOS 14, there is a problem. How can I fix this?
var muteUser: some View {
NavigationLink(destination: Text("dddd").environmentObject(CurrentUser)) {
Image(systemName: "speaker.slash")
.frame(width: 22, height: 22)
}
}
var friendSetting: some View {
NavigationLink(destination: FriendSettings().environmentObject(CurrentUser)) {
Image(systemName: "gear")
.frame(width: 22, height: 22)
}
}
var body: some View {
GeometryReader { geometry in
if #available(iOS 14.0, *) {
chatView
.toolbar {
ToolbarItem(placement: .principal) {
centerNavBar()
.frame(maxWidth: geometry.size.width*0.75)
}
ToolbarItemGroup(placement: .navigationBarTrailing) {
muteUser
friendSetting
}
}
} else {
chatView
.navigationBarItems(trailing:
HStack(){
centerNavBar()
Spacer()
rightNavBar
}
.frame(width: geometry.size.width*0.75)
)
}
}
}
It looks like this is the standard appearance of two buttons inside ToolbarItemGroup.
You can use a HStack instead:
.toolbar {
ToolbarItem(placement: .principal) {
Image(systemName: "star.fill")
}
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
NavigationLink(destination: Text("dddd").environmentObject(CurrentUser)) {
Image(systemName: "speaker.slash")
.imageScale(.large)
}
NavigationLink(destination: FriendSettings().environmentObject(CurrentUser)) {
Image(systemName: "gear")
.imageScale(.large)
}
}
}
}
Try omitting the .frame(width: 22, height: 22) on the toolbar item Images. I think that’s causing the iOS 14 toolbar to create UIToolbarItems with embedded views instead of simple images.
In Xcode 12 Beta 6, dismissing a sheet doesn't work inside a button's action inside a ToolbarItem.
My sheet view looks like:
NavigationView {
Form {
Section {
TextField("Name", text: $name)
}
}
.navigationTitle("New Thing")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(action: {
self.presentation.wrappedValue.dismiss()
}, label: {
Text("Cancel")
})
}
ToolbarItem(placement: .confirmationAction) {
Button(action: {
do {
// some saving logic
try managedObjectContext.save()
self.presentation.wrappedValue.dismiss()
} catch {
print("didn't save due to \(error.localizedDescription)")
}
}, label: {
Text("Save")
})
}
}
}
EDIT: here's how I constructed the sheet
var body: some View {
List {
ForEach(results) { result in
HStack {
NavigationLink(destination: SingleResultView(result: result)) {
SingleResultRowView(result: result)
}
}
}
.onDelete(perform: deleteResult)
}
.navigationTitle("All Results")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: {
self.isNewResultSheetPresented.toggle()
}, label: {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30, alignment: .center)
})
.sheet(isPresented: $isNewResultSheetPresented) {
NewResultView()
// ^ this contains the code above
.environment(\.managedObjectContext, self.managedObjectContext)
}
}
}
}
When the sheet is first presented, immediately a console log appears:
2020-09-13 20:52:02.333679-0700 MyApp[2710:89263]
[Presentation] Attempt to present <_TtGC7SwiftUI22SheetHostingControllerVS_7AnyView_: 0x1027b7890> on
<_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10270d620>
(from <_TtGC7SwiftUIP10$194f39bd428DestinationHostingControllerVS_7AnyView_: 0x103605930>)
which is already presenting <_TtGC7SwiftUI22SheetHostingControllerVS_7AnyView_: 0x103606d60>.
I can dismiss the sheet only by swiping down.
For reference, I went back to an older commit where I used NavigationBarItems and it worked perfectly. But from what I understand, this is a situation where I'm supposed to be using ToolbarItem.
Does anybody know why the good old self.presentation.wrappedValue.dismiss() doesn't work here or why is the sheet being presented twice?
Move sheet out of toolbar, as
var body: some View {
List {
ForEach(results) { result in
HStack {
NavigationLink(destination: SingleResultView(result: result)) {
SingleResultRowView(result: result)
}
}
}
.onDelete(perform: deleteResult)
}
.navigationTitle("All Results")
.sheet(isPresented: $isNewResultSheetPresented) { // << here !!
NewResultView()
// ^ this contains the code above
.environment(\.managedObjectContext, self.managedObjectContext)
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: {
self.isNewResultSheetPresented.toggle()
}, label: {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 30, height: 30, alignment: .center)
})
}
}
}
I need to make an Alert in SwiftUI that has an editable TextField in it. Currently, this isn't supported by SwiftUI (as of Xcode 11.3), so I'm looking for a work-around.
I know I can implement by wrapping the normal UIKit bits in a UIHostingController, but really want to stick with an all-SwiftUI implementation.
I've got two VStacks in a ZStack, with the front one (the one with the TextView) being hidden and disabled until until you tap the button. Take a look at this:
import SwiftUI
struct ContentView: View {
#State var isShowingEditField = false
#State var text: String = "12345"
var body: some View {
ZStack {
VStack {
Text("Value is \(self.text)")
Button(action: {
print("button")
self.isShowingEditField = true
}) {
Text("Tap To Test")
}
}
.disabled(self.isShowingEditField)
.opacity(self.isShowingEditField ? 0.25 : 1.00)
VStack(alignment: .center) {
Text("Edit the text")
TextField("", text: self.$text)
.multilineTextAlignment(.center)
.lineLimit(1)
Divider()
HStack {
Button(action: {
withAnimation {
self.isShowingEditField = false
print("completed... value is \(self.text)")
}
}) {
Text("OK")
}
}
}
.padding()
.background(Color.white)
.shadow(radius: CGFloat(1.0))
.disabled(!self.isShowingEditField)
.opacity(self.isShowingEditField ? 1.0 : 0.0)
}
}
}
This seems like it should work to me. Switching between the two VStacks works well, but the TextField is not editable.
It acts like it's disabled, but it's not. Explicitly .disabled(false) to the TextField doesn't help. Also, it should already be enabled anyway since 1) that's the default, 2) the VStack it's in is specifically being set as enabled, and 3) The OK button works normally.
Ideas/workarounds?
Thanks!
You need to force the TextField updating with some methods. Like the following:
TextField("", text: self.$text)
.multilineTextAlignment(.center)
.lineLimit(1)
.id(self.isShowingEditField)
That is really ridiculous, but the problem disappears if you comment just one line of code:
//.shadow(radius: CGFloat(1.0))
I commented it and everything works. I think you need to use ZStack somewhere in your custom alert view to avoid this.. hm, bug, maybe?
update
try some experiments. If you leave just this code in that View:
struct CustomAlertWithTextField: View {
#State var isShowingEditField = false
#State var text: String = "12345"
var body: some View {
TextField("", text: $text)
.padding()
.shadow(radius: CGFloat(1.0))
}
}
it would not work again. only if you comment .padding() or .shadow(...)
BUT if you relaunch Xcode - this code begin to work (which made me crazy). Tried it at Xcode Version 11.2 (11B52)
update 2 the working code version:
struct CustomAlertWithTextField: View {
#State var isShowingEditField = false
#State var text: String = "12345"
var body: some View {
ZStack {
VStack {
Text("Value is \(self.text)")
Button(action: {
print("button")
self.isShowingEditField = true
}) {
Text("Tap To Test")
}
}
.disabled(self.isShowingEditField)
.opacity(self.isShowingEditField ? 0.25 : 1.00)
ZStack {
Rectangle()
.fill(Color.white)
.frame(width: 300, height: 100)
.shadow(radius: 1) // moved shadow here, so it doesn't affect TextField now
VStack(alignment: .center) {
Text("Edit the text")
TextField("", text: self.$text)
.multilineTextAlignment(.center)
.lineLimit(1)
.frame(width: 298)
Divider().frame(width: 300)
HStack {
Button(action: {
withAnimation {
self.isShowingEditField = false
print("completed... value is \(self.text)")
}
}) {
Text("OK")
}
}
}
}
.padding()
.background(Color.white)
.disabled(!self.isShowingEditField)
.opacity(self.isShowingEditField ? 1.0 : 0.0)
}
}
}
after some research i solved this problem by adding .clipped() to the VStack.
For your problem, it would look like this:
VStack(alignment: .center) {
Text("Edit the text")
TextField("", text: self.$text)
.multilineTextAlignment(.center)
.lineLimit(1)
Divider()
HStack {
Button(action: {
withAnimation {
self.isShowingEditField = false
print("completed... value is \(self.text)")
}
}) {
Text("OK")
}
}
}
.padding()
.clipped() // <- here
.background(Color.white)
.shadow(radius: CGFloat(1.0))
.disabled(!self.isShowingEditField)
.opacity(self.isShowingEditField ? 1.0 : 0.0)