I've recently started working with SwiftUI. Let me explain my idea: I have a view that allows me to add items to a list. This list should be displayed inside a view. The problem is that I can display it inside, but I can't scroll it or perform a swipe to trigger the .onDelete action. How can I achieve this?
Here is the View with the list:
import SwiftUI
struct ListInsideScontrino: View {
@State private var isAddFoodViewPresented = false
@EnvironmentObject var foodData: FoodData
var foodItems: [MyFoodItem] {
foodData.foodItems
}
var body: some View {
if foodItems.isEmpty {
VStack {
Text("Il riepilogo del tuo ordine apparirà qui una volta aggiunte le varie pietanze.")
.font(.callout)
.foregroundColor(.gray)
.multilineTextAlignment(.center)
.padding()
Text("Clicca il bottone in basso a destra ed inizia ad aggiungere il cibo!")
.font(.callout)
.foregroundColor(.gray)
}
.padding()
} else {
List {
ForEach(foodData.foodItems) { foodItem in
FoodItemRow(foodItem: foodItem)
.listRowSeparator(.hidden)
}
.onDelete(perform: deleteFoodItem)
}
.listStyle(InsetGroupedListStyle())
.background(Color.gray.opacity(0.100))
}
Color.gray.opacity(0.100)
}
private func deleteFoodItem(at offsets: IndexSet) {
foodData.foodItems.remove(atOffsets: offsets)
}
}
#Preview {
ListInsideScontrino()
}
This is the view where I want to show my List:
import SwiftUI
struct ScontrinoView: View {
var body: some View {
ZStack {
ListInsideScontrino()
}
.padding()
.mask(
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
for i in 0..<Int(UIScreen.main.bounds.height / 20) {
let x = CGFloat(i) * 20
path.addLine(to: CGPoint(x: x + 10, y: 30))
path.addLine(to: CGPoint(x: x + 20, y: 20))
}
path.addLine(to: CGPoint(x: UIScreen.main.bounds.width, y: UIScreen.main.bounds.height))
path.addLine(to: CGPoint(x: 0, y: UIScreen.main.bounds.height))
}
.scaleEffect(CGSize(width: 1.0, height: -1.0))
)
.shadow(radius: 5)
//.frame(maxWidth: .infinity, maxHeight: .infinity)
.cornerRadius(15)
.ignoresSafeArea()
}
}
I apologize for the errors, I am Italian, and I might have written something incorrectly.
Thank you all for the responses!
I tried to swap views between ScrollView, ZStack ecc.
Here is a solution without .mask
- just putting the scontrino path and the list in a ZStack
. You just have to make the list background invisible with .scrollContentBackground(.hidden)
Saluti a Italia
struct ListInsideScontrino: View {
@State private var isAddFoodViewPresented = false
// Test data
@State private var foodItems: [String] = [
"Insalata Mista", "Pasta Norcia", "Cotoletta Milanese", "Panna Cotta", "Café", "Gelato", "Digestivo"
]
var body: some View {
List {
ForEach(foodItems, id: \.self) { foodItem in
Text(foodItem)
.listRowSeparator(.hidden)
.listRowBackground(Color.clear) // remove list row background
}
.onDelete(perform: deleteFoodItem)
}
.listStyle(InsetGroupedListStyle())
.scrollContentBackground(.hidden) // hide overall list background
//.background(Color.gray.opacity(0.100)) // not needed
}
private func deleteFoodItem(at offsets: IndexSet) {
foodItems.remove(atOffsets: offsets)
}
}
struct ContentView: View {
var body: some View {
ZStack {
// first the scontrino
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
for i in 0..<Int(UIScreen.main.bounds.height / 20) {
let x = CGFloat(i) * 20
path.addLine(to: CGPoint(x: x + 10, y: 30))
path.addLine(to: CGPoint(x: x + 20, y: 20))
}
path.addLine(to: CGPoint(x: UIScreen.main.bounds.width, y: UIScreen.main.bounds.height))
path.addLine(to: CGPoint(x: 0, y: UIScreen.main.bounds.height))
}
.fill(Color.gray.opacity(0.2))
.scaleEffect(CGSize(width: 1.0, height: -1.0))
.shadow(radius: 5)
.cornerRadius(15)
.ignoresSafeArea()
// then the list
ListInsideScontrino()
}
.padding()
}
}