Eseguire gli aggiornamenti dell'interfaccia utente in un ciclo
Domanda
Sto lavorando a un'interfaccia utente di applicazione mobile che ha un pannello con slancio (per scorrimento fluido) e attualmente sto aggiornando l'interfaccia utente che si esegue a uno scorrimento regolare utilizzando il seguente codice:
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();
}
}
Come potete vedere, Application.DoEvents();
sta allevando la sua brutta testa! Voglio sbarazzarmi di esso, ma non riesco a pensare a un modo per eseguire il loop e aggiornare l'interfaccia utente. Qualsiasi aiuto/idee sarebbe eccellente!
Lo sto facendo su .NET CF, ma penso che sia un problema di progettazione, quindi non penso che la piattaforma avrà importanza troppo.
Soluzione 2
Potresti provare a rimuovere il loop (e tutte le chiamate App.DoEvent), effettuare una chiamata a KineticsCroll nel metodo OnPaint () e quindi chiamare invalidate () nel tuo metodo KineticsCroll.
Vedo che hai una sorta di monitoraggio dello stato, quindi puoi dire qualcosa del tipo:
if(_curState == States.KineticScroll)
KineticScroll();
Nel tuo metodo OnPaint (), in questo modo lo chiami solo quando il tuo stato è appropriato.
Fondamentalmente, il tuo ciclo passa da un locale durante: OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc
In questo modo ottieni lo stesso ciclo, senza fare una chiamata a Doevents!
Altri suggerimenti
Creerei un timer che si comporterebbe come un "loop di gioco" - eseguire X volte al secondo.
Vorrei anche tenere traccia di quanto tempo trascorso dall'ultima chiamata in modo da poter calcolare quanto spostarsi in base a quel tempo trascorso. Per prestazioni aggiuntive, il timer potrebbe essere avviato e fermato solo se c'è un movimento.
A seconda del tipo di timer che usi, potrebbe essere necessario fare il marshall di aggiornamento dell'interfaccia utente al thread dell'interfaccia utente.