4

我正在使用加速度计滚动 UIScrollVIew 中的多个子视图。我希望当用户将 iPhone 向右滑动时视图(纵向)向右滚动,当设备向左滑动时向左滚动。

我认为我可以通过记录正或负 x 加速度值来做到这一点,但我发现这些值通常是正值和负值的混合。我已将地板设置为 1.5g 以消除非抖动运动,并在 0.5 秒的时间内查看 x 值。

我确信有一种三角方法可以确定轻弹的整体方向,并且您必须在轻弹运动的持续时间内测量值。我也确信有人已经弄清楚了这一点。

有什么想法吗?

谢谢

4

2 回答 2

8

我开发了一个解决方案,它比建议的解决方案给我更好的反馈(仅适用于左右摇晃)。我在这里做的方式非常敏感(识别出轻微的震动),但是可以通过更改 tresholdFirstMove 和 tresholdBackMove 来调整灵敏度(增加以降低灵敏度)

在 Swift 中:(在您的 viewController 中。并添加“import CoreMotion”)

var startedLeftTilt = false
var startedRightTilt = false
var dateLastShake = NSDate(timeIntervalSinceNow: -2)
var dateStartedTilt = NSDate(timeIntervalSinceNow: -2)
var motionManager = CMMotionManager()
let tresholdFirstMove = 3.0
let tresholdBackMove = 0.5

override func viewDidLoad() {
    // your code

    motionManager.gyroUpdateInterval = 0.01
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: { (gyroData, error) -> Void in
        self.handleGyroData(gyroData.rotationRate)
    })

}

private func handleGyroData(rotation: CMRotationRate) {

    if fabs(rotation.z) > tresholdFirstMove && fabs(dateLastShake.timeIntervalSinceNow) > 0.3
    {
        if !startedRightTilt && !startedLeftTilt
        {
            dateStartedTilt = NSDate()
            if (rotation.z > 0)
            {
                startedLeftTilt = true
                startedRightTilt = false
            }
            else
            {
                startedRightTilt = true
                startedLeftTilt = false
            }
        }
    }

    if fabs(dateStartedTilt.timeIntervalSinceNow) >= 0.3
    {
        startedRightTilt = false
        startedLeftTilt = false
    }
    else
    {
        if (fabs(rotation.z) > tresholdBackMove)
        {
            if startedLeftTilt && rotation.z < 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked left\n/")
            }
            else if startedRightTilt && rotation.z > 0
            {
                dateLastShake = NSDate()
                startedRightTilt = false
                startedLeftTilt = false

                println("\\\n Shaked right\n/")
            }
        }
    }

}
于 2015-03-13T11:24:42.443 回答
5

好的,想出了一个解决方案。当我检测到抖动运动(x 轴上的加速度大于 1.5)时,我启动一个计时器并将 BOOL 设置为 true。虽然 BOOL 为真,但我添加了加速度值。当计时器到期时,我停止添加加速度值并通过总加速度的符号确定震动的方向。


- (void)accelerometer:(UIAccelerometer *)acel didAccelerate:(UIAcceleration *)aceler {

    if (fabsf(aceler.x) > 1.5)
    {
        shake = YES;
        NSTimeInterval myInterval = .75;
        [NSTimer scheduledTimerWithTimeInterval:myInterval target:self selector:@selector(endShake) userInfo:nil repeats:NO];
        return;
    }

    if(shake)
    {
        totalG += aceler.x;
    }
}

- (void) endShake {
    shake = NO;
    int direction;
    if (totalG isLessThan 0) direction = 1;
    if(totalG isGreaterThan 0) direction = -1;
    [self changePageByShake:direction];
    totalG = 0;
}

注意:我无法在上面的代码块中正确格式化 < 和 > 符号,因此我用 isLessThan 和 isGreaterThan 替换了这些符号。

于 2009-06-19T17:19:42.153 回答