我知道如何在UIScrollView移动时获取contentOffset,能否有人解释一下如何在UIScrollView跟踪或减速时获取表示当前速度的实际数字?
我知道如何在UIScrollView移动时获取contentOffset,能否有人解释一下如何在UIScrollView跟踪或减速时获取表示当前速度的实际数字?
有一种更简单的方法:检查UISCrollview的pan手势识别器。使用它,您可以这样获取速度:
CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self];
scrollVelocity
立即变为 0.0f。因此,它是在拖动 scrollview 时测量速度的好方法,但在进行轻弹操作时无效。 - Kyle FoxscrollViewWillEndDragging:withVelocity:targetContentOffset:
来处理当前触摸事件结束后的速度或偏移条件。 - Will Von UllrichCGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;
那么你可以在scrollViewDidScroll中添加以下代码:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint currentOffset = scrollView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - lastOffsetCapture;
if(timeDiff > 0.1) {
CGFloat distance = currentOffset.y - lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
CGFloat scrollSpeedNotAbs = (distance * 10) / 1000; //in pixels per millisecond
CGFloat scrollSpeed = fabsf(scrollSpeedNotAbs);
if (scrollSpeed > 0.5) {
isScrollingFast = YES;
NSLog(@"Fast");
} else {
isScrollingFast = NO;
NSLog(@"Slow");
}
lastOffset = currentOffset;
lastOffsetCapture = currentTime;
}
}
我得到了每毫秒的像素数,如果大于0.5,就标记为快速,小于0.5则标记为慢速。
我使用这个方法来加载一个表格视图上的一些单元格动画。如果在用户快速滚动时加载它们,则滚动效果不太好。
captureInterval
常量,并且在计算scrollSpeedNotAbs
时也使用它,以增加算法的可读性(因为大脑会停留在* 10
,因为速度的一般公式是距离/时间)。 - zubko将@bandejapaisa的答案转换为Swift 5:
UIScrollViewDelegate使用的属性:
var lastOffset: CGPoint = .zero
var lastOffsetCapture: TimeInterval = .zero
var isScrollingFast: Bool = false
还有scrollViewDidScroll函数:
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentOffset = scrollView.contentOffset
let currentTime = Date.timeIntervalSinceReferenceDate
let timeDiff = currentTime - lastOffsetCapture
let captureInterval = 0.1
if timeDiff > captureInterval {
let distance = currentOffset.y - lastOffset.y // calc distance
let scrollSpeedNotAbs = (distance * 10) / 1000 // pixels per ms*10
let scrollSpeed = fabsf(Float(scrollSpeedNotAbs)) // absolute value
if scrollSpeed > 0.5 {
isScrollingFast = true
print("Fast")
} else {
isScrollingFast = false
print("Slow")
}
lastOffset = currentOffset
lastOffsetCapture = currentTime
}
}
对于简单的速度计算(所有其他答案都更加复杂):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
previousTableViewYOffset = scrollView.contentOffset.y;
}
使用现代的Swift/iOS很容易实现这个目标:
var previousScrollMoment: Date = Date()
var previousScrollX: CGFloat = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let d = Date()
let x = scrollView.contentOffset.x
let elapsed = Date().timeIntervalSince(previousScrollMoment)
let distance = (x - previousScrollX)
let velocity = (elapsed == 0) ? 0 : fabs(distance / CGFloat(elapsed))
previousScrollMoment = d
previousScrollX = x
print("vel \(velocity)")
当然,你想要以每秒点数为单位的速度,这就是它的含义。
人类在2017年的设备上拖动时速度大约为200-400个点每秒。
1000-3000是一个快速的投掷速度。
当它减速到停止时,20-30是很常见的。
因此,你经常会看到像这样的代码..
if velocity > 300 {
// the display is >skimming<
some_global_doNotMakeDatabaseCalls = true
some_global_doNotRenderDiagrams = true
}
else {
// we are not skimming, ok to do calculations
some_global_doNotMakeDatabaseCalls = false
some_global_doNotRenderDiagrams = false
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
(0.0,-5.35356)
。在y轴上滚动,每次调用scrollViewDidScroll
大约需要15个点 :) 因此,5就非常快了。 - Dima DeplovscrollView.contentOffset
来从UIScrollViewDelegate
方法中获取contentOffset
。当前速度可以通过delta_offset和delta_time计算。
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if velocity.y > 1.0 || velocity.y < -1.0 && self.sendMessageView.isFirstResponder() {
// Somthing you want to do when scrollin fast.
// Generally fast Vertical scrolling.
}
}
如果您是垂直滚动,应使用velocity.y;如果您是水平滚动,则应使用velocity.x。通常,如果值大于1且小于-1,则表示快速滚动。因此,您可以根据需要更改速度。+值表示向上滚动,-值表示向下滚动。