swift - 如何在 SwiftUI 中的动态可滚动路径中设置最后一个元素的偏移量
问题描述
我正在尝试构建一个具有连续路径的视图作为滚动视图中的图形。
我正在从 BLE 设备接收数据并将它们转换为基于时间戳的向量。虽然矢量在宽度上随时间增长,但我想在 scrollView 中跟随它。我厌倦了 ScrollViewReader 的实现,但没有运气,因为如果我理解得很好,我应该有我想要滚动到的元素的 id。据我所知,这是不可能的,因为整个信号是一次绘制的一条路径。
我试图根据最后一个元素宽度设置 uiScrollView 的偏移量,但我无法让 scrollView 增长,因为带有图表的路径是......
我使用了 uiScrollView 包装器的实现:https ://gist.github.com/jfuellert/67e91df63394d7c9b713419ed8e2beb7
在其中,我正在绘制基于值和常量值的路径作为 xStep
结构线图:形状{
let geoProxy: GeometryProxy
@Binding var lead: ECGLead
@Binding var timestamps: [Int]
var n: vDSP_Length{
return vDSP_Length(lead.channelVector.count)
}
let stride = vDSP_Stride(1)
var xPosition: Binding<CGFloat>
func path(in rect: CGRect) -> Path {
Path { path in
let xStep = 0.00015 * geoProxy.size.width
var currentX: CGFloat = xStep
let signal = transformIntoSignal(lead: lead , timestamps: timestamps)
path.move(to: .zero)
//if signal.count
signal.forEach{ signalValue in
//let yStep = CGFloat($0) * geoProxy.frame(in: .local).height
//print("X: \(currentX) Y: \($0)")
path.addLine(to: CGPoint(x: currentX, y: CGFloat(signalValue)))
currentX += xStep
print("Last x: \(currentX)")
//print("Checking xStep = \(currentX)")
}
}
}
func transformIntoSignal(lead: ECGLead, timestamps: [Int]) -> [Float] {
var outputSignal = [Float](repeating: 0,
count: Int(n))
let time = timestamps.map{Float($0)}
vDSP_vgenp(lead.channelVector, stride,
time, stride,
&outputSignal, stride,
vDSP_Length(lead.channelVector.count),
vDSP_Length(timestamps.count))
return outputSignal
}
}
有了这条路径,我试图给它 maxWidth = .inifity 以便能够在 scrollView 中增长
ZStack(){
RoundedRectangle(cornerRadius: 8)
.frame(minWidth: 120, idealWidth: 170, maxWidth: .infinity, minHeight: 60, idealHeight: 90, maxHeight: 90, alignment: .center)
.foregroundColor(.white)
.overlay(
ScrollableView($lineOffset, animationDuration: TimeInterval(1), content: {
//HStack{
LineChart(vector: animatableVector, geoProxy: geoProxy,lead: $ecgLead,timestamps: $timeStamps, xPosition: $lastPointX)
.stroke(appGreen, lineWidth: 1)
.frame(minWidth: 120, idealWidth: 170, maxWidth: .infinity, minHeight: 35, idealHeight: 40, maxHeight: 50,alignment: Alignment(horizontal: .leading, vertical: .center))
})//.frame(minWidth: 120, idealWidth: 170, maxWidth: .infinity, minHeight: 35, idealHeight: 50, maxHeight: 60,alignment: Alignment(horizontal: .leading, vertical: .center))
)
使用 uiScrollView 包装器,我尝试以编程方式滚动到内容偏移量,但每次我看到围绕某个中间值的跳转视图并连续结束。
这是上面提到的 UIkit 包装器的更新方法:
func updateUIViewController(_ viewController: UIViewControllerType, context: UIViewControllerRepresentableContext<Self>) {
viewController.scrollView.showsVerticalScrollIndicator = self.showsScrollIndicator
viewController.scrollView.showsHorizontalScrollIndicator = self.showsScrollIndicator
viewController.updateContent(self.content)
viewController.scrollView.invalidateIntrinsicContentSize()
let lastPoint = viewController.scrollView.contentSize.width
let lastPointOffset = viewController.scrollView.contentOffset.x
let tmp = viewController.scrollView.visibleSize.width
let contentWidth = viewController.scrollView.bounds.width
print("Check last point: \(lastPoint)")
print("Check last point offset: \(lastPointOffset)")
print("Check tmp: \(contentWidth)")
viewController.scrollView.setContentOffset(CGPoint(x: lastPoint, y: 0), animated: true)
viewController.scrollView.bounds.width
let duration: TimeInterval = self.duration(viewController)
let newValue: CGPoint = self.offset.wrappedValue
viewController.scrollView.isScrollEnabled = !self.disableScroll
if self.stopScrolling.wrappedValue {
viewController.scrollView.setContentOffset(viewController.scrollView.contentOffset, animated:true)
return
}
guard duration != .zero else {
viewController.scrollView.contentOffset = newValue
return
}
UIView.animate(withDuration: duration, delay: 0, options: [.allowUserInteraction, .curveEaseInOut, .beginFromCurrentState], animations: {
viewController.scrollView.contentOffset = newValue
}, completion: nil)
}
我的问题是如何使滚动始终专注于滚动视图中此信号的增长数组的最后一个元素。它不工作是因为某处宽度没有正确增长吗?还是我在某个地方误解了?现在我不知道从哪里继续
提前感谢您回答我的问题。任何帮助都会非常感激:)
解决方案
推荐阅读
- vba - 使用 VBA 更改 Word 文档中所有表格的文本样式
- pandas - 连接数据集的问题
- ubuntu - 防止超级键进入 Ubuntu 20 中的搜索栏
- azure-machine-learning-studio - Azure ML Studio Designer - 是否可以将管道或管道草稿从一个工作区复制到另一个工作区?
- typescript - 在 Typescript 中将语言代码 (ISO 639-1) 转换为国家代码 (ISO 3166-1 alpha-2)
- python - 在另一个文件中使用程序会给出不同的输出
- c++ - OpenCL clBuildProgram“无法打开文件:C:\Users\?”
- css - 使 Bulma 中的表单字段具有响应性?
- python - Flask、flask_login、pytest:如何设置flask_login 的current_user?
- r - 加载命名空间中的错误(i,c(lib.loc,.libPaths()),