質問
私は、勢いのあるパネル(スムーズなスクロール用)を備えたモバイルアプリケーション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で行っていますが、それがデザインの問題だと思うので、プラットフォームがあまり重要ではないと思います。
解決 2
ループ(およびすべてのapp.doevent呼び出し)を削除して、onpaint()メソッドでkineticscrollに呼び出しを行い、kineticscrollメソッドでinvalidate()を呼び出すことができます。
ある種の状態追跡があることがわかりますので、次のようなことを言うことができます。
if(_curState == States.KineticScroll)
KineticScroll();
onpaint()メソッドでは、状態が適用されている場合にのみ呼び出します。
基本的に、ループはローカルのwhileループから以下に移動します。 OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc
そうすれば、同じループを取得します。
他のヒント
「ゲームループ」のように動作するタイマーを作成します。1秒あたりのX回を実行します。
また、最後の電話以来の時間が経過した時間を追跡し、その時間に基づいてどれだけ移動するかを計算できるようにします。追加のパフォーマンスのために、モーションがある場合にのみ、タイマーを開始および停止できます。
どの種類のタイマーを使用するかによっては、UIアップデートコールをUIスレッドに戻す必要がある場合があります。