swiftui_swiftui将列表滚动到底部

swiftui

Using a SwiftUI list is a convenient way to use all the auto-mechanisms to insert, remove, or move rows.

使用SwiftUI列表是使用所有自动机制插入,删除或移动行的便捷方法。

However, if you add a new entry, there is no official way to scroll to the bottom of the list where the new entry was added. So, I tried to find a solution. You’ll find a couple of questions on Stack Overflow but no real nice solution (I did not want to replace the list with a wrapped UITableView).

但是,如果添加新条目,则没有官方方法滚动到添加新条目的列表底部。 因此,我试图找到一种解决方案。 您会在Stack Overflow上找到几个问题,但没有一个真正好的解决方案(我不想用包装好的UITableView替换列表)。

By chance, I found a library called Introspect that gives access to most of the UIKit stuff behind the SwiftUI elements.

偶然地,我发现了一个名为Introspect的库,该库可以访问SwiftUI元素后面的大多数UIKit内容。

My idea was now to get access to the UITableView behind a list and then to just use a custom function named scrollToBottom.

我的想法是现在可以访问列表后面的UITableView,然后仅使用一个名为scrollToBottom的自定义函数。

幸福之路 (The Way to Happiness)

  • Add Introspect to your project’s package list.

    将Introspect添加到项目的软件包列表中。
  • Import Introspect to your custom ContentView.

    将Introspect导入您的自定义ContentView。
  • Add this to the action of your Add button:

    将此添加到“ Add按钮的操作中:

self.tableView?.scrollToBottom(animated: true, yOffset: self.$yOffset)
  • To have the compiler accept this, we need a state variable:

    为了使编译器接受此条件,我们需要一个状态变量:
@State var yOffset: CGFloat = 0
  • And another one:

    还有一个:
@State var tableView: UITableView?
  • Add this modifier to your list:

    将此修饰符添加到您的列表中:
.introspectTableView(customize: { tableView in
if self.tableView == nil { self.tableView = tableView }
else { self.tableView?.setContentOffset(CGPoint(x: 0, y: self.yOffset + 60), animated: true) } })
  • Add this extension:

    添加此扩展名:
extension UITableView {
func scrollToBottom(animated: Bool, yOffset: Binding<CGFloat>) {
let y = contentSize.height — frame.size.height
if y < 0 { return }
yOffset.wrappedValue = y
}}

一些注意事项 (Some notes)

  • The addition in the third bullet triggers the scrolling to the current yOffset.

    第三个项目符号中的添加触发滚动到当前yOffset

  • The variable in the fifth bullet is needed to make the tableView available throughout the CustomView, as it seems to stay constant during its lifetime.

    需要使用第五个项目符号中的变量,以使tableView在整个CustomView可用,因为它在其生命周期内似乎保持不变。

  • The modifier in the sixth bullet is the magic sauce. Through Introspect, we get access to the UITableView behind the list. We use the yOffset to adjust the content offset. For whatever reason, it’s necessary to add some offset to the offset (here: 60) because — at least in my environment — the last row is otherwise not visible or fully visible.

    第六个项目符号中的修饰符是魔术酱。 通过Introspect,我们可以访问列表后面的UITableView。 我们使用yOffset来调整内容偏移量。 无论出于何种原因,都必须在偏移量上添加一些偏移量(此处为60),因为至少在我的环境中,否则最后一行不可见或完全不可见。

  • In the seventh bullet, the new yOffset is set. Because of the @State property wrapper, the view updates according to the new offset.

    在第七个项目符号中,设置了新的yOffset 。 由于@State属性包装器,该视图根据新的偏移量进行更新。

Now, everything’s working pretty smoothly (not perfectly, but in an acceptable way). Well, not everything: If you remove a row, the positioning goes wonky (i.e. to the last save position in yOffset).

现在,一切工作都非常顺利(不是很完美,但是可以接受)。 好吧,不是所有内容:如果删除一行,则定位yOffset (即到yOffset的最后一个保存位置)。

What shall we do now?

我们现在干什么?

  • Let’s change the yOffset declaration to a CGFLoat? (an optional).

    让我们将yOffset声明更改为CGFLoat? (可选)。

  • In the .onDelete(perform:) event of the list, add a self.yOffset = nil after the removal operation.

    在列表的.onDelete(perform:)事件中,在删除操作之后添加self.yOffset = nil

  • In the .introspectTableView view modifier, add a guard let yOffset = self.yOffset else { return } before the call of setContentOffset.

    .introspectTableView视图修饰符中,在调用setContentOffset之前添加一个guard let yOffset = self.yOffset else { return }guard let yOffset = self.yOffset else { return }

Now, things are going smoothly.

现在,一切进展顺利。

结论 (Conclusion)

I added a gist on GitHub where you can check out the full code of the view. It refers to some model-related protocols that are not provided. You can just replace the model-related calls with your code.

在GitHub上添加了要点 ,您可以其中查看视图的完整代码。 它指的是一些未提供的与模型相关的协议。 您可以只用代码替换与模型相关的调用。

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/better-programming/swiftui-scrolling-a-list-to-the-bottom-68337e4d8db0

swiftui

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值