List 任何视图更改上的快捷菜单列表重置滚动

List 任何视图更改上的快捷菜单列表重置滚动,list,scroll,swiftui,reset,List,Scroll,Swiftui,Reset,我有一个非常简单的列表,其中有一些部分,在同一视图中,我还有一个按钮,当选择任何列表项时,该按钮将被启用,这由状态变量控制,当发生这种情况时,如果向下滚动列表,状态变量将更改(以启用按钮),所有视图都将刷新,使我的列表在顶部滚动。如何避免这种滚动重置,我应该提到,如果元素被删除或添加到列表中,同样的情况也会发生,但是,我尝试尽可能地简化问题,下面是简化的代码片段 import SwiftUI enum FavoritesListActiveSheet: Identifiable { c

我有一个非常简单的列表,其中有一些部分,在同一视图中,我还有一个按钮,当选择任何列表项时,该按钮将被启用,这由状态变量控制,当发生这种情况时,如果向下滚动列表,状态变量将更改(以启用按钮),所有视图都将刷新,使我的列表在顶部滚动。如何避免这种滚动重置,我应该提到,如果元素被删除或添加到列表中,同样的情况也会发生,但是,我尝试尽可能地简化问题,下面是简化的代码片段

import SwiftUI

enum FavoritesListActiveSheet: Identifiable {
    case moveToSheet
    
    var id: Int { hashValue }
}

struct Category: Identifiable {
    var id: UUID = UUID()
    var name: String
}

extension Category {
    static var categories: [Category] {
        [
            Category(name: "category 1"),
            Category(name: "category 2")
        ]
    }
}

struct FavoriteItem: Identifiable {
    var id: UUID = UUID()
    var name: String
    var category: String
    var selected: Bool
}

extension FavoriteItem {
    static var favoriteItems: [FavoriteItem] {
        [
            FavoriteItem(name: "Item 1", category: "category 1", selected: false),
            FavoriteItem(name: "Item 2", category: "category 1", selected: false),
            FavoriteItem(name: "Item 3", category: "category 1", selected: false),
            FavoriteItem(name: "Item 4", category: "category 2", selected: false),
            FavoriteItem(name: "Item 5", category: "category 2", selected: false),
            FavoriteItem(name: "Item 6", category: "category 2", selected: false),
            FavoriteItem(name: "Item 7", category: "category 2", selected: false),
            FavoriteItem(name: "Item 8", category: "category 2", selected: false),
            FavoriteItem(name: "Item 9", category: "category 2", selected: false),
            FavoriteItem(name: "Item 10", category: "category 2", selected: false),
            FavoriteItem(name: "Item 11", category: "category 2", selected: false),
            FavoriteItem(name: "Item 12", category: "category 2", selected: false),
            FavoriteItem(name: "Item 13", category: "category 2", selected: false),
            FavoriteItem(name: "Item 14", category: "category 2", selected: false),
            FavoriteItem(name: "Item 15", category: "category 2", selected: false),
            FavoriteItem(name: "Item 16", category: "category 2", selected: false),
            FavoriteItem(name: "Item 17", category: "category 2", selected: false),
            FavoriteItem(name: "Item 18", category: "category 2", selected: false),
        ]
    }
}

struct FavoritesRaw: View {

    @Binding var item: FavoriteItem
    @State var refreshView: Bool = false

    let onItemToggle: () -> ()

    var body: some View {
        HStack {
            if (item.selected) {
                Image(systemName: "checkmark.circle")
            } else {
                Image(systemName: "circle")
            }

            Text (item.name)
        }
        .simultaneousGesture(TapGesture().onEnded {

            self.item.selected.toggle()

            refreshView.toggle()
            onItemToggle()
        })
        .contentShape(Rectangle())
    }
}

class FavoritesViewModel: ObservableObject {
    var favorite_items: [FavoriteItem] = FavoriteItem.favoriteItems
}

struct FavoritesListView: View {
    @StateObject var viewModel: FavoritesViewModel = FavoritesViewModel()

    @State var addtoButtonDisabled: Bool = true
    @State var sheetDisplayed: FavoritesListActiveSheet?

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach (Category.categories) { category in
                        Section (header: Text(category.name))
                        {
                            ForEach (self.viewModel.favorite_items.filter({$0.category == category.name})) { item in
                                FavoritesRaw(item: binding(for: item), onItemToggle: {
                                    addtoButtonDisabled = (self.viewModel.favorite_items.filter({$0.selected == true}).count == 0)
                                })
                            }
                        }
                        .textCase(nil)
                        
                    }
                }
                .listStyle(PlainListStyle())
                .id(UUID()) // no animation
            }
            .navigationBarTitle("Favorites", displayMode: .inline)
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarTrailing) {

                    Button(action: {
                        sheetDisplayed = .moveToSheet
                    }) {
                        Text("Add to...")
                    }.disabled(addtoButtonDisabled)
                }
            }
            .sheet(item: $sheetDisplayed) { item in
                // [Show a sheet then disable back the button]
            }
        }
        .onAppear
        {
            addtoButtonDisabled = (self.viewModel.favorite_items.filter({$0.selected == true}).count == 0)
        }
    }

    private func binding(for item: FavoriteItem) -> Binding<FavoriteItem> {
        guard let item_index = self.viewModel.favorite_items.firstIndex(where: { $0.id == item.id }) else {
             fatalError("Can't find item in array")
         }
        return $viewModel.favorite_items[item_index]
     }
}
导入快捷界面
枚举收藏夹StactiveSheet:可识别{
案例移动见
变量id:Int{hashValue}
}
结构类别:可识别{
变量id:UUID=UUID()
变量名称:String
}
扩展类别{
静态变量类别:[类别]{
[
类别(名称:“类别1”),
类别(名称:“类别2”)
]
}
}
结构FavoriteItem:可识别{
变量id:UUID=UUID()
变量名称:String
变量类别:字符串
所选变量:Bool
}
扩展偏好项{
静态变量favoriteItems:[FavoriteItem]{
[
FavoriteItem(名称:“Item 1”,类别:“category 1”,所选:false),
FavoriteItem(名称:“Item 2”,类别:“category 1”,所选:false),
FavoriteItem(名称:“Item 3”,类别:“category 1”,所选:false),
FavoriteItem(名称:“Item 4”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 5”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 6”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 7”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 8”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 9”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 10”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 11”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 12”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 13”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 14”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 15”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 16”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 17”,类别:“category 2”,所选:false),
FavoriteItem(名称:“Item 18”,类别:“category 2”,所选:false),
]
}
}
结构收藏夹raw:视图{
@绑定变量项:FavoriteItem
@状态变量刷新视图:Bool=false
让我说说:()->()
var body:一些观点{
HStack{
如果(选定项){
图像(系统名称:“选中标记.圆圈”)
}否则{
图像(系统名称:“圆圈”)
}
文本(项目名称)
}
.同时手势(轻触手势().ONENED{
self.item.selected.toggle()
refreshView.toggle()
onItemToggle()
})
.contentShape(矩形())
}
}
类FavoritesViewModel:ObservableObject{
var favorite\u items:[FavoriteItem]=FavoriteItem.favoriteItems
}
结构收藏夹列表视图:视图{
@StateObject变量viewModel:FavoritesViewModel=FavoritesViewModel()
@状态变量addtoButtonDisabled:Bool=true
@显示的状态变量表:FavoriteSStactiveSheet?
var body:一些观点{
导航视图{
VStack{
名单{
ForEach(Category.categories){categories in
节(标题:文本(类别名称))
{
ForEach(self.viewModel.favorite_items.filter({$0.category==category.name})){item in
FavoritesRaw(项目:绑定(针对:项目),onItemToggle:{
addtoButtonDisabled=(self.viewModel.favorite_items.filter({$0.selected==true})。计数==0)
})
}
}
.textCase(无)
}
}
.listStyle(PlainListStyle())
.id(UUID())//没有动画
}
.navigationBarTitle(“收藏夹”,显示模式:。内联)
.工具栏{
ToolbarItemGroup(位置:。导航栏栏栏){
按钮(操作:{
sheetDisplayed=.moveToSheet
}) {
文本(“添加到…”)
}.禁用(添加到禁用)
}
}
.sheet(项目:$sheetdisplated){item in
//[显示工作表,然后禁用后退按钮]
}
}
奥纳佩尔先生
{
addtoButtonDisabled=(self.viewModel.favorite_items.filter({$0.selected==true})。计数==0)
}
}
私有函数绑定(对于项:FavoriteItem)->绑定{
guard let item_index=self.viewModel.favorite_items.firstIndex(其中:{$0.id==item.id})else{
fatalError(“在数组中找不到项”)
}
返回$viewModel.favorite\u项目[项目索引]
}
}
似乎删除

.id(UUID())//没有动画

正在解决我的问题。然而,我添加了这个来摆脱丑陋的动画,SwiftUI提供了关于元素删除的功能