1

我正在开发具有动量面板(用于平滑滚动)的移动应用程序 UI,我目前正在使用以下代码在平滑滚动期间更新 UI:

private void scrollKinetic()
{
    while (_curState == States.KineticScroll)
    {
        //  This gets how far the panel will move with the current velocity, then updates the velocity according to the current friction.
        var distY = GetDistance(scrVelocity.Y);
        var distX = GetDistance(scrVelocity.X);

        if (distY + distX <= 0)  //  Friction will eventually make distX and distY both 0
        {
            _curState = States.Idle;
            Invalidate();
            break;
        }

        //  CalculatePosition will move the panel accordingly.

        CalculatePosition(distY, scrVelocity.Y, false);
        CalculatePosition(distX, scrVelocity.X, true);

        Invalidate();
        friction++;
        Application.DoEvents();
    }
}

如您所见,Application.DoEvents();正在抬起丑陋的脑袋!我想摆脱它,但我想不出任何方法来循环和更新 UI。任何帮助/想法都会很棒!

我在.net CF 上这样做,但我认为这是一个设计问题,所以我认为平台不会太重要。

4

2 回答 2

1

您可以尝试删除循环(以及所有 App.DoEvent 调用),在 OnPaint() 方法中调用 KineticScroll,然后在 KineticScroll 方法中调用 Invalidate()。

我看到你有某种状态跟踪,所以你可以这样说:

if(_curState == States.KineticScroll)
    KineticScroll();

在您的 OnPaint() 方法中,只有在您的状态合适时才调用它。

基本上,您的循环从本地 while 循环转到:OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc这样您就可以得到相同的循环,而无需调用 DoEvents!

于 2011-03-24T14:50:46.317 回答
1

我会创建一个类似于“游戏循环”的计时器——每秒执行 x 次。
我还将跟踪自上次通话以来经过了多少时间,以便您可以根据经过的时间计算要移动多少。为了获得额外的性能,只有在有运动时才可以启动和停止计时器。

根据您使用的计时器类型,您可能需要将 UI 更新调用编组回 UI 线程。

于 2011-03-24T04:17:44.253 回答