SwipeAction does not work in TabView SwiftUI - xcode

I have List in the TabView. List has text/button with delete and update swipe action. The swipe action does not work in the tabview but it is work fine without tab view. Below is my code.
TabView {
List {
ForEach(0..<5, id: \.self) {index in
Text(“\(index)”)
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
Button {
} label: {
Label {
Text("Delete")
} icon: {
Image("ic_delete")
.renderingMode(.template)
.foregroundColor(.white)
}
}
.tint(.red)
Button {
} label: {
Label {
Text("Update")
} icon: {
Image("ic_edit")
.renderingMode(.template)
.foregroundColor(.white)
}
}
.tint(.accentColor)
}
}
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
Can Anyone help me to fix this issue?

Related

Placing the toggle sidebar button on the sidebar toolbar

I have a three column layout macOS application with the first being the sidebar. I have a button that toggles that enabling the user to hide the sidebar.
On Xcode and other macOS, the toggle sidebar button resides on the toolbar on top of the sidebar, and becomes part of the main toolbar when the sidebar is hidden.
For example, open sidebar on Xcode:
And when you hide the sidebar:
I have added the toolbar with the toggle sidebar to the view containing my sidebar, and another toolbar to the second column, but still toggle sidebar appears on the main toolbar, on top of the second column.
Am I missing anything? Here's the code:
// sidebar view, first of three columns
struct ContentView: View {
#State var selection: Set<Int> = [0]
var body: some View {
NavigationView {
List(selection: self.$selection) {
NavigationLink(destination: AllData()) {
Label("All Data", systemImage: "note.text")
}
.tag(0)
Label("Trash", systemImage: "trash")
}
.listStyle(SidebarListStyle())
.toolbar {
ToolbarItem(placement: .navigation) {
Button(action: toggleSidebar, label: {
Image(systemName: "sidebar.left") }).help("Toggle Sidebar")
}
}
}
}
func toggleSidebar() {
NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
}
// second column view, with the rest of the toolbar
struct AllData: View {
var body: some View {
NavigationView {
List(filteredData) {
// list items here.
}
.toolbar {
ToolbarItem(placement: .automatic) {
Button("Press Me") {
print("Pressed")
}
}
ToolbarItem(placement: .automatic) {
Button("Press Me too") {
print("Pressed too")
}
}
}
}
}
}
If you use the .frame modifier on the sidebar then you are able to set constraints for minimum width, ideal width and maximum width.
I find a minWidth: 148 ensures the sidebar cannot be collapsed to the point where SwiftUI shuffles the toolbar button off to the trailing edge of the nav toolbar and behind (need to click) the double chevron expander.
So your code might look like this...
...
var body: some View {
NavigationView {
List(selection: self.$selection) {
NavigationLink(destination: AllData()) {
Label("All Data", systemImage: "note.text")
}
.tag(0)
Label("Trash", systemImage: "trash")
}
.listStyle(.sidebar) //<-- from iOS 14 and macOS 10.15
.frame(minWidth: 148, idealWidth: 160, maxWidth: 192, maxHeight: .infinity)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: {
toggleSidebar
}, label: {
Image(systemName: "sidebar.left")
})
.help("Toggle Sidebar")
}
}
}
}
...
PS. I note that the .primaryAction and .status modifiers both place the sidebar button in a similar position, although I've not tested this thoroughly or completed any research.
try this:
ToolbarItem(placement: .primaryAction) {

SwiftUI Conditional TextField in Form appears as white space when not triggered

I have made a form that has conditional TextFields based on the previous question (eg. Have you ever traveled? (Bool answer) next question: If yes "Where?" (no else).
When the condition to display the next question is not fulfilled, a white space appears in my form (see screenshot) (if the condition is fulfilled then things work properly).
I don't want these white spaces to appear as it does not look good. How can I solve this?
Here's my code:
var body: some View {
Form {
Section(header: Text("Work Order")) {
TextField("Work order title", text: $wovm.workorder.title)
Picker("Brand",selection: $wovm.workorder.brand) {
Group {
Text("Beneteau").tag(Brand.brand1)
Text("Jeanneau").tag(Brand.brand2)
Text("IslandP").tag(Brand.brand3)
}
}
}
Section(header: Text("Description of the boat")) {
VStack {
TextField("Description of the boat", text: $wovm.workorder.description)
}
HStack {
Text("Brand")
Spacer()
TextField("entrer date", text: $wovm.workorder.symptomesqd)
.multilineTextAlignment(.trailing)
}
Picker("Is it a pre-owned boat",selection: $wovm.workorder.preowned) {
Group {
Text("Pre-Owned").tag(Preowned.preowned)
Text("Not pre-owned").tag(Preowned.notpreowned)
Text("I don’t know").tag(Preowned.noidea)
}
}
HStack {
Picker("Is this the first repais of this type?", selection: $wovm.workorder.firstrepair){
Text("Oui").tag(true)
Text("Non").tag(false)
}
}
HStack {
if wovm.workorder.firstrepair == false {
}
else {
TextField"When was the last time it happened", text: $wovm.workorder.lasttime)
.multilineTextAlignment(.trailing)
}
}
}
HStack {
if wovm.workorder.firstrepair == false {
}
else {
TextField("Who made the previous work order ?", text: $wovm.workorder.whomade)
}
}
}
Section(header: Text("Facteurs extérieurs")) {
HStack {
Picker("Is this urgent", selection: $wovm.workorder.urgent){
Text("Oui").tag(Urgent.oui)
Text("Non").tag(Urgent.non)
Text("Je ne sais pas").tag(Urgent.saispas)
}
}
HStack {
Picker("Have you had similar problems in the past?", selection: $wovm.workorder.similarpb){
Text("Oui").tag(true)
Text("Non").tag(false)
}
}
HStack {
if wovm.workorder.similarpb == true {
Picker("Do you think they could be linked to this WO?", selection: $wovm.workorder.linked){
Text("Oui").tag(true)
Text("Non").tag(false)
}
}
}
HStack {
Picker("Have we already worked with you?", selection: $wovm.workorder.worked){
Text("Oui").tag(true)
Text("Non").tag(false)
}
}
HStack {
if wovm.workorder.worked == true {
TextField("Who serviced you?", text: $wovm.workorder.who)
}
}
}
}
.navigationBarTitle("Work Order", displayMode: .inline)
.navigationBarItems(leading:
Button(action: { self.presentationMode.wrappedValue.dismiss() }) {
Text("Cancel")
}, trailing: Button(action: {
$wovm.workorder.addwo(self.wovm.workorder)
self.presentationMode.wrappedValue.dismiss()
} ){Text("Done")})
}
}
Here's how it looks (in red, the blank spaces, that I don't want).
The white spaces are appearing because you are still creating a HStack even if wovm.workorder.firstrepair is false.
Instead of:
HStack {
if wovm.workorder.firstrepair == false {
}
else {
TextField("When was the last time it happened", text: $wovm.workorder.lasttime)
.multilineTextAlignment(.trailing)
}
}
}
Try this:
if wovm.workorder.firstrepair == true {
HStack {
TextField("When was the last time it happened", text: $wovm.workorder.lasttime)
.multilineTextAlignment(.trailing)
}
}
This way you're only creating the HStack if you need to based on the if condition.

How to toggle the visibility of the third pane of NavigationView?

Assuming the following NavigationView:
Struct ContentView: View {
#State var showRigthPane: Bool = true
var body: some View {
NavigationView {
Sidebar()
MiddlePane()
RightPane()
}.toolbar {
ToolbarItem(placement: .navigation) {
Button(action: toggleSidebar, label: {Image(systemName: "sidebar.left")})
}
ToolbarItem(placement: .primaryAction) {
Button(action: self.toggleRightPane, label: { Image() })
}
}
}
private func toggleRightPane() {
// ?
}
// collapsing sidebar - this works
private func toggleSidebar() {
NSApp.keyWindow?.initialFirstResponder?.tryToPerform(
#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
}
How can I implement the toggleRightPane() function to toggle the visibility of the right pane?
Updated to use a calculated property returning two different navigation views. Still odd behavior with sidebar, but with a work-around it is functional. Hopefully someone can figure out the sidebar behavior.
struct ToggleThirdPaneView: View {
#State var showRigthPane: Bool = true
var body: some View {
VStack {
navigationView
}
.navigationTitle("Show and Hide")
}
var navigationView : some View {
if showRigthPane {
return AnyView(NavigationView {
VStack {
Text("left")
}
.toolbar {
Button(action: { showRigthPane.toggle() }) {
Label("Add Item", systemImage: showRigthPane ? "rectangle.split.3x1" : "rectangle.split.2x1")
}
}
Text("middle")
}
)
} else {
return AnyView(NavigationView {
VStack {
Text("left")
}
.toolbar {
Button(action: { showRigthPane.toggle() }) {
Label("Add Item", systemImage: showRigthPane ? "rectangle.split.3x1" : "rectangle.split.2x1")
}
}
Text("middle")
Text("right")
})
}
}
}
Try the following (cannot test)
struct ContentView: View {
#State private var showRigthPane = true
var body: some View {
NavigationView {
Sidebar()
MiddlePane()
if showRigthPane { // << here !!
RightPane()
}
}.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: self.toggleRightPane, label: { Image() })
}
}
}
private func toggleRightPane() {
withAnimation {
self.showRigthPane.toggle() // << here !!
}
}
}

How do I enable the sort option with the Edit/Done Button in SwiftUI?

When I tap on the Edit button it functions correctly to change the list to an active state with a delete icon beside each item. However, the sort icon does not show on the right side of each item as expected.
This leads me to believe that I have overlooked a key element in the following code. What else is required to enable the sort option?
struct ContentView: View {
#Environment(\.managedObjectContext) var moc
#FetchRequest(entity: Task.entity(), sortDescriptors:[
NSSortDescriptor(keyPath: \Task.isComplete, ascending: true)
]) var tasks: FetchedResults<Task>
#State private var showingAddScreen = false
var body: some View {
NavigationView {
List {
ForEach(tasks, id: \.self) { task in
HStack {
Image(systemName: task.isComplete ? "square.fill" : "square")
.padding()
.onTapGesture {
task.isComplete.toggle()
try? self.moc.save()
print("Done button tapped")
}
Text(task.name ?? "Unknown Task")
Spacer()
Image("timer")
.onTapGesture {
print("Timer button tappped")
}
}
}
.onDelete(perform: deleteTask)
}
.navigationBarTitle("To Do List", displayMode: .inline)
.navigationBarItems(leading: EditButton(), trailing: Button(action: {
self.showingAddScreen.toggle()
}) {
Image(systemName: "plus")
})
.sheet(isPresented: $showingAddScreen) {
AddTaskView().environment(\.managedObjectContext, self.moc)
}
}
}
func deleteTask(at offsets: IndexSet) {
for offset in offsets {
let task = tasks[offset]
moc.delete(task)
}
try? moc.save()
}
}
What else is required to enable the sort option?
it appears whenever .onMove modifier is provided, ie. add
.onDelete(perform: deleteTask)
.onMove { sourceIndices, destinationIndex in
// << your code here
}

Simulate button click in macOS SwiftUI?

I’ve built a simple macOS modal dialog in SwiftUI that takes some text from the user:
struct
OpenLocationView : View
{
#State private var location: String = ""
var body: some View
{
VStack
{
HStack
{
Text("Location:")
TextField("https://", text: $location) { self.openLocation() }
}
HStack
{
Spacer()
Button("Cancel") { self.dismiss() }
Button("Open") { self.simulateClick() }
}
}
.padding()
.frame(minWidth: 500.0)
}
}
If the user presses enter or return, I’d like to briefly simulate a click on the default button before dismissing the dialog. How would I do this in SwiftUI?
Actually you've almost done it, see comments inline
...
HStack
{
Text("Location:")
TextField("https://", text: $location) {
// this is onCommit: called on Return or Enter
self.open()
}
}
HStack
{
Spacer()
Button("Cancel") { self.dismiss() }
Button("Open") { self.open() }
}
...
func open() {
self.openLocation()
self.dismiss()
}

Resources