我正在开发一个移动应用程序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上这样做,但我认为这是一个设计问题,所以我认为平台不会太重要。
答案 0 :(得分:1)
我会创建一个像“游戏循环”一样的计时器 - 每秒执行x次 我还会记录自上次调用以来经过的时间,以便您可以根据经过的时间计算移动量。为了获得额外的性能,只有在有运动时才可以启动和停止计时器。
根据您使用的计时器类型,您可能需要将UI更新调用封送回UI线程。
答案 1 :(得分:1)
您可以尝试删除循环(以及所有App.DoEvent调用),在OnPaint()方法中调用KineticScroll,然后在KineticScroll方法中调用Invalidate()。
我看到你有某种状态跟踪,所以你可以这样说:
if(_curState == States.KineticScroll)
KineticScroll();
在你的OnPaint()方法中,只有当你的状态合适时你才会调用它。
基本上,你的循环从本地while循环变为:OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc
,这样你得到相同的循环,没有调用DoEvents!