在 SwiftUI 中标记列表项时,如何将列表项移动到顶部?

How can I move list item to top when we mark the list item in SwiftUI?

我在 SwiftUI 中有列表项,当我用星形图标设置最喜欢的项目时,我想将项目移到顶部,我想再次重复第二个项目,可以吗?我知道有移动行的例子,但我不明白我将如何做。

型号:

struct Restaurant: Identifiable {
    var id = UUID()
    var name: String
    var image: String
    var isFavorite: Bool = false
  
}

基本图像行:

    struct BasicImageRow: View {

    var restaurant: Restaurant
    
    var body: some View {
        HStack {
            Image(restaurant.image)
                .resizable()
                .frame(width: 40, height: 40)
                .cornerRadius(5)
            Text(restaurant.name)
          
            if restaurant.isFavorite {
                Spacer()
                
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }
        }
    }
}

查看:

import SwiftUI

struct ContentView: View {
    
  
    @State private var selectedRestaurant: Restaurant?
    
  @State private  var restaurants = [ Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
                  Restaurant(name: "Homei", image: "homei"),
                  Restaurant(name: "Teakha", image: "teakha"),
                  Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
                  Restaurant(name: "Petite Oyster", image: "petiteoyster"),
                  Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant"),

            ]

 
    var body: some View {
        List {
            ForEach(restaurants) { restaurant in
                BasicImageRow(restaurant: restaurant)
                    .contextMenu {
                        
                        Button(action: {
                            // mark the selected restaurant as check-in
                            self.checkIn(item: restaurant)
                        }) {
                            HStack {
                                Text("Check-in")
                                Image(systemName: "checkmark.seal.fill")
                            }
                        }
                        
                        Button(action: {
                            // delete the selected restaurant
                            self.delete(item: restaurant)
                        }) {
                            HStack {
                                Text("Delete")
                                Image(systemName: "trash")
                            }
                        }
                        
                        Button(action: {
                            // mark the selected restaurant as favorite
                            self.setFavorite(item: restaurant)
                        }) {
                            HStack {
                                Text("Favorite")
                                Image(systemName: "star")
                            }
                        }
                    }
                    .onTapGesture {
                        self.selectedRestaurant = restaurant
                    }
                    .actionSheet(item: self.$selectedRestaurant) { restaurant in
                        
                        ActionSheet(title: Text("What do you want to do"), message: nil, buttons: [
                            
                            .default(Text("Mark as Favorite"), action: {
                                self.setFavorite(item: restaurant)
                            }),
                            
                            .destructive(Text("Delete"), action: {
                                self.delete(item: restaurant)
                            }),
                            
                            .cancel()
                        ])
                    }
            }
           
        }
    }
   
    
    private func setFavorite(item restaurant: Restaurant) {
        if let index = self.restaurants.firstIndex(where: { [=12=].id == restaurant.id }) {
            self.restaurants[index].isFavorite.toggle()
        }
    }
   
}

已更新:喜爱切换的 Amination 位置更改

你只需要更新 withAnimation 块内的餐厅,SwiftUI 将知道如何使用它们的 id 为它们设置动画

ForEach(restaurants) { restaurant in
    Button(action: {
        withAnimation {
            var selectedRestaurant = restaurant
            selectedRestaurant.isFavorite.toggle()
            restaurants = restaurants.filter { [=10=].id != restaurant.id }
            let index = selectedRestaurant.isFavorite ? 0 : restaurants.firstIndex { [=10=].isFavorite == false }
            restaurants.insert(selectedRestaurant, at: index ?? 0)
        }
    }) {
        BasicImageRow(restaurant: restaurant)
    }.buttonStyle(.automatic)
}

这是完整的示例代码(您可以在预览版上试用)

struct Restaurant: Identifiable {
    var id = UUID()
    var name: String
    var image: String
    var isFavorite: Bool = false
}

extension Restaurant: Equatable {}

struct BasicImageRow: View {
    var restaurant: Restaurant
    var body: some View {
        HStack {
            Text(restaurant.name)
            if restaurant.isFavorite {
                Spacer()
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }
        }
    }
}

struct ContentView: View {
    @State private var restaurants = [
        Restaurant(name: "Cafe Deadend", image: "cafedeadend"),
        Restaurant(name: "Homei", image: "homei"),
        Restaurant(name: "Teakha", image: "teakha"),
        Restaurant(name: "Cafe Loisl", image: "cafeloisl"),
        Restaurant(name: "Petite Oyster", image: "petiteoyster"),
        Restaurant(name: "For Kee Restaurant", image: "forkeerestaurant"),
    ]

    var body: some View {
        List {
            ForEach(restaurants) { restaurant in
                Button(action: {
                    withAnimation {
                        var selectedRestaurant = restaurant
                        selectedRestaurant.isFavorite.toggle()
                        restaurants = restaurants.filter { [=11=].id != restaurant.id }
                        let index = selectedRestaurant.isFavorite ? 0 : restaurants.firstIndex { [=11=].isFavorite == false }
                        restaurants.insert(selectedRestaurant, at: index ?? 0)
                    }
                }) {
                    BasicImageRow(restaurant: restaurant)
                }.buttonStyle(.automatic)
            }
        }
    }
}