SwiftUI 列表在任何视图更改时重置滚动

2024-01-11

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

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]
     }
}

看来要去掉

.id(UUID()) // 无动画

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI 列表在任何视图更改时重置滚动 的相关文章

  • 在一个 SwiftUI 视图中相同的 ForEach 循环两次

    当我在视图中对数组使用 ForEach 循环两次时 我在运行时收到以下警告 LazyVGridLayout the ID 84308994 9D16 48D2 975E DC40C5F9EFFF is used by multiple ch
  • 如何在 macOS 上的 SwiftUI 中设置拖动图像

    我正在尝试更改 GridView 的默认拖放预览图像 该图像似乎包含网格中的所有可见项目 据我了解 我应该能够设置NSItemProvider previewImageHandler块来自定义所使用的图像 我似乎找不到任何关于返回自定义图像
  • 如何加快列表理解速度

    以下是我的清单 col red yellow blue red green yellow pink orange brown pink brown 我的目标是消除每个列表中出现一次的项目 这是我的代码 eliminate w for w i
  • Java 阻止列表实现

    我在 SO 和 Google 上搜索了这个问题的答案 但到目前为止找不到合适的解决方案 我目前正在研究图形路由问题中的 LayerManager 管理器负责提供和重置一组固定的层 我想使用阻止列表来实现消费者 生产者模式 以便只要没有可用的
  • 使用 sapply 的列表和矩阵

    我有一个也许是基本的问题 我在网上搜索过 我在读取文件时遇到问题 尽管如此 我还是按照 Konrad的建议设法读取了我的文件 我很欣赏这一点 How to get R to read in files from multiple subdi
  • 使用 Linq 返回具有最大计数的列表

    使用 C 和 Linq 如何返回具有最大大小 计数的 List 我假设您有一个名为的列表集合lists并且您想要返回此集合中元素最多的列表 如果是这样 请尝试以下操作 var listWithLargestCount lists Order
  • 以特定方式填充列表

    我需要填充一个包含 5 个位置的列表 new list 我收到 2 个列表 并且有一个默认值来填充新列表 现在开始解决问题 好的方式是 我从列表中接收 2 个值 从列表中接收 2 个值并添加默认值 A1 A2 DEFAULT B1 B2 但
  • 在 SwiftUI App 中实现深色模式切换

    我目前正在我的应用程序中研究深色模式 虽然由于我的 SwiftUI 基础 深色模式本身并不困难 但我正在努力选择将 ColorScheme 设置为独立于系统 ColorScheme 的选项 我在苹果人机界面指南中找到了这一点 https i
  • 如何在 Haskell 中向右或向左移动列表的 1 个元素?

    嗨 我一直在寻找答案 但找不到 假设我们有一个像这样的列表 1 10 4 5 3 我怎样才能将 5 向左移动 使这个列表变成 1 10 5 4 3 我尝试过了swapElementsAt通过找到该元素的索引 但它看起来非常不足 swapEl
  • Python-使用元组作为列表索引[重复]

    这个问题在这里已经有答案了 我有一个元组列表 tuples list 1 0 2 3 3 2 2 0 我想访问二维数组的元素a例如 使用其中一些元组 for i in range 3 print a tuples list i 应该输出的值
  • 当我尝试从列表中删除元素时,如何忽略 ValueError?

    如果我打电话 如何忽略 不在列表中 错误消息a remove x when x不在列表中a 这是我的情况 gt gt gt a range 10 gt gt gt a 0 1 2 3 4 5 6 7 8 9 gt gt gt a remov
  • 在 ARKit 和 RealityKit 中使用 Raycast 的真正好处是什么?

    RealityKit 和 ARKit 中的光线投射有何用途 我什么时候需要使用makeRaycast查询 https developer apple com documentation realitykit arview 3255315 m
  • python中的列表列表的集合

    我有一个列表列表 mat 1 2 3 4 5 6 1 2 3 7 8 9 4 5 6 我想转换成set即删除重复列表并从中创建一个新列表 其中仅包含unique lists 在上述情况下 所需的答案将是 1 2 3 4 5 6 7 8 9
  • 按多个键分组并对字典列表的值进行汇总/平均值

    在Python中按多个键进行分组并对字典列表进行汇总 平均值的最Pythonic方法是什么 假设我有一个字典列表 如下所示 input dept 001 sku foo transId uniqueId1 qty 100 dept 001
  • 重置 MySQL root 密码不起作用

    我花了很多时间阅读并尝试了数十种重置 root 密码的方法 但我一无所获 我发现 并尝试过 的最完整的说明如下 顺便说一句 我在 Win7 32 位上运行 MySQL 5 5 我创建了一个文件 c mysqlinit txt 其中包含两行
  • .send() 和 .sink() 似乎不再适用于 Xcode 11 Beta 5 中的 PassthroughSubject

    在下面的代码中 当按下按钮时 Test 应该打印在控制台中 但事实并非如此 该事件不是通过发布者发送的 知道 Xcode 11 Beta 5 中的 PassthroughSubject 发生了什么吗 在 Xcode 11 Beta 4 中效
  • Collections.sort(list) 和 list.sort(Comparator) 之间的区别

    有什么理由让我应该选择Collections sort list 方法而不是简单地调用list sort 内部Collections sort只是调用sort的方法List无论如何 上课 令人惊讶的是几乎每个人都告诉我使用Collectio
  • 如何检测 swiftui 中是否存在键盘

    我想知道按下按钮时键盘是否存在 我该怎么做 我已经尝试过 但我没有任何运气 谢谢 使用该协议 KeyboardReadable 你可以符合任何View并从中获取键盘更新 KeyboardReadable协议 import Combine i
  • scala 返回列表中的第一个 Some

    我有一个清单l List T1 目前我正在执行以下操作 myfun T1 gt Option T2 val x Option T2 l map myfun l flatten find gt true The myfun函数返回 None
  • 将字符串连接到python列表中所有元素的末尾

    我想知道如何将字符串连接到列表中所有元素的末尾 例如 List1 1 2 3 string a output 1a 2a 3a 在列表理解和使用中重建列表str format在两个参数上 gt gt gt string a gt gt gt

随机推荐

  • 对于实体框架来说,具有相同键的两个不同对象不起作用

    我试图在我的主对象中插入对象引用 但如果我不使用其以前管理的对象 EntityFramework 会抱怨 我只是想在创建对象时避免对 dbContext 的依赖 简化示例 class Movie public ApplicationUser
  • Javascript 中用于异或门的简单感知器

    我尝试使用单个感知器来预测异或门 然而 结果似乎完全是随机的 我找不到错误 我在这里做错了什么 是我的训练方法不对吗 或者感知器模型中是否存在任何错误 或者单个感知器不能用于解决这个问题 class Perceptron construct
  • Android:如何将 imageView 设置为谷歌地图 API android 中的标记?

    到目前为止 我一直在使用可绘制对象来填充地图上的标记 现在我想知道如果我可以将自定义图像视图显示为地图中的标记 那会很酷 直到现在我都这样做 itemized new Itemazide drawable mContext 我想实现类似的目
  • 打开、拆分 iTerm2 窗口并在每个窗格中执行命令

    我正在尝试创建一个脚本来打开iTerm2窗口 将其垂直分成 3 个窗格 并在每个窗格中运行一些命令 到目前为止 这是我的尝试 tell application iTerm2 activate Create main window creat
  • 需要帮助调试旨在更新 Google 云端硬盘中数百个文件的 Google Apps 脚本代码

    我工作的公司刚刚更新了其品牌 影响了保存到共享 Google 云端硬盘的数百个 Excel 和 PowerPoint 文件 有一个团队正在努力更新文件 我的挑战是找到一种有效的方法来添加新文件并删除 Google 云端硬盘中的旧文件 我创建
  • 实现一个简单的 Dagger2 示例

    我是 Dagger2 的新手 我一直使用 Koin 我正在尝试实现一个简单的示例 但我真的不知道我缺少什么 这是我到目前为止所得到的 应用程序 gradle ext daggerVersion 2 23 2 implementation c
  • “插入”和“删除”表是否保证在 AFTER UPDATE 触发器中以相同的顺序返回其记录?

    如果我有一个 AFTER UPDATE 触发器 将会 SELECT FROM inserted and SELECT FROM deleted 按同样的顺序把他们的记录还给我吗 IE 假设我能够索引到他们的结果集 将 del 5 和 ins
  • 将 CSV 文件导入 C#

    我正在构建一个网站 要求之一是用户从电子邮件客户端导出联系人 然后将其导入到网站中 因为每个电子邮件客户端以稍微不同的格式导出他们的联系人 这让我摸不着头脑 必须找到处理它的最佳方法 因为我不知道字段是什么 也不知道分隔符是什么 我只想瞄准
  • 获取字体支持的字符 - 在 C# 中

    我有一个支持日语字符的第三方字体 我需要将其用于应用程序 每当该字体不支持某个字符时 就会绘制常见的矩形 默认字符 显然 并非所有日语字符都受支持 因为如果我尝试绘制翻译办公室给我们的翻译 就会发现有很多矩形 每当使用不支持的字符时 我都需
  • 如何将 JS 对象集合发送到 ASP.NET API 服务?

    我正在尝试将 JavaScript 对象集合发送到我的 API 服务 但服务器收到空对象列表
  • 如何同时部署两个 ClickOnce 版本?

    我希望能够为我的应用程序提供一个测试 ClickOnce 服务器 用户可以在其中并行运行生产版本和测试版本 这可能吗 我首先尝试使用以下内容AssemblyInfo cs并且还更改了 ClickOnce 部署中的名称 尽管所实现的所有这些都
  • 何时将 volatile 与寄存器/局部变量一起使用

    在 CUDA 中使用 volatile 限定符声明寄存器数组的含义是什么 当我尝试使用 volatile 关键字和寄存器数组时 它删除了溢出寄存器内存到本地内存的数量 即强制 CUDA 使用寄存器而不是本地内存 这是预期的行为吗 我在 CU
  • 访问 BeanFactoryPostProcessor 中的属性

    我正在尝试创建一些东西 它将根据可配置的属性自动创建bean 来自application yml等 因为我不能像通常那样访问属性组件BeanFactoryPostProcessor 我有点困惑如何访问它们 如何访问应用程序属性BeanFac
  • 如何在 .NET 交互式笔记本中绘制图像(C#、VS Code)

    我正在尝试使用 C 在 NET 交互式笔记本中绘制简单的图形 有点像 Dr Racket 的 C 版本 到目前为止我见过的最简单的事情是using System Drawing SFML NET Raylib cs 也可以工作 但它们会打开
  • Python 中的 NoSql 注入

    当试图提出这个问题时 我得到了this one https stackoverflow com questions 4167077 mongodb injection它使用的是Java 并且在答案中给出了一个Ruby示例 并且似乎只有在使用
  • Vaadin 通过单击按钮重定向到 URL

    我已经搜索了很长时间 但我确实无法弄清楚这一点 如何将用户重定向到新的外部链接 例如www google com 当他们点击 Vaadin 中的按钮时 到目前为止我唯一能做的就是将链接放入链接中 Link link new Link lin
  • 如何构建没有版本后缀的ffmpeg共享库

    有没有一种方法可以配置为Android构建没有版本号后缀的ffmpeg共享库 我能够使用不同的选项进行构建 但总是得到像 libavcodec so 57 这样的文件 我需要没有后缀的库 例如 libavcodec so 我认为选项 dis
  • 为什么 UDP 在其数据包中有两次“UDP 长度”字段?

    为什么 UDP 在其数据包中有两次 UDP 长度 字段 这不是多余的吗 如果需要进行某种错误检查 请提供示例 你的观察是正确的 长度字段是多余的 因为IP头和UDP头都有长度字段 我对这种冗余原因的唯一猜测是 它发生是因为 UDP 是在当时
  • 部分 .csproj 文件

    是否可以将 csproj 中的信息拆分到多个文件中 有点像项目版本partial class特征 您不能拥有多个主 csproj 但因为 csproj 的底层接线是使用 msbuild 完成的 所以您可以简单地拥有多个相互导入的部分 csp
  • SwiftUI 列表在任何视图更改时重置滚动

    我有一个非常简单的列表 其中有一些部分 在同一视图中 我还有一个按钮 当选择任何列表项时 该按钮将被启用 这是由状态变量控制的 当发生这种情况时 如果列表向下滚动 状态变量将发生变化 以启用按钮 并且所有视图将刷新 导致我的列表滚动到顶部