Cacher automatiquement la systray dans windows phone 7

Cacher automatiquement la systray dans windows phone 7

Problématique

Lorsque l’on code une application en silverlight sous windows phone 7, nous avons la possibilité de laissé afficher ou de cacher la barre système en haut de l’écran.

La plupart des applications cachent cette barre, surement pour deux raisons :
– gagner de la place (32 pixels en mode portrait, 72 en mode paysage)
– cohérence graphique : si notre interface dispose d’une image de fond, une barre blanche ou noir en haut de l’écran peut être gênant

Néanmoins cette barre est indispensable à l’utilisateur, afin de connaitre l’heure, la disponibilité réseau, etc… Si l’utilisateur fait une recherche et que votre application n’affiche pas de résultats, sans cette barre, il ne va pas forcément penser à qu’il ne capte pas bien la 3G et dans sa tête, c’est votre application qui sera lente/bogué.

Pour conclure, les informations dans cette barre sont indispensables pour l’utilisateur et son expérience, mais peu m’embêter pour mon UI.

L’idée

Afin d’avoir le meilleur des deux mondes, l’idée est de cacher la systray par défaut, mais de laisser la possibilité à l’utilisateur de l’afficher lorsqu’il clique en haut de l’écran

 


A noter, on souhaite utiliser la vrai barre système, pas une fausse barre avec l’heure. De plus nous ne souhaitons pas que l’interface de l’application se décale lorsque la barre s’affiche.

La solution

Pour répondre à notre soucis, nous allons coder un behavior directement sur la PhoneApplicationPage.

public class SystrayBehavior : Behavior<PhoneApplicationPage>    {

...

}

et nous allons nous enregistrer sur l’évènement MouseLeftButtonUp de la page associé à notre behavior, tout en faisant attention de supprimer l’enregistrement dans la méthode appropriée.

protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonUp;
}

protected override void OnDetaching()
{
AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonUp;
base.OnDetaching();
}

nous allons donc écrire la méthode AssociatedObject_MouseLeftButtonUp qui va surveiller les évènements ‘touch’ et si un clic a lieu dans la zone supérieur de l’écran (32 pixels), on affiche la barre.

void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.GetPosition((UIElement)sender).Y <= 32)             {                 Microsoft.Phone.Shell.SystemTray.IsVisible = true;             }         } 	

Ceci dit, nous souhaitons qu’au bout de 3 secondes d’inactivité, la barre disparaisse. C’est à dire que si l’utilisateur clique plusieurs fois (par exemple pour faire un slide vers le bas pour afficher plus d’information sur la barre, on ne prend en compte que le dernier ‘clic’. On aurait pu utiliser RX pour cela, mais je utiliser le moins de dépendance possible, je me contenterais donc t’un dispatchTimer

                 DispatcherTimer tim = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(3) };                 tim.Tick += (senderr, er) =>
{
tim.Stop();
Microsoft.Phone.Shell.SystemTray.IsVisible = false;

};
tim.Start();

Si on lance notre application, voici le résultat :

 

Notre interface se décale lorsque la barre apparaît. En effet, la taille disponible pour l’affiche de la page diminue. Pour corriger cela, il faut trouver le bon moment pour décaler manuellement négativement notre page afin de compenser ce décalage.

Pour solutionner ce problème, on aurait tendance à modifier margin-top ou utiliser un translateTransform juste après ‘Microsoft.Phone.Shell.SystemTray.IsVisible = true;’ Cette solution n’est pas viable car il y a un delai entre l’affectation et le décalage effectif. Ceci va se traduire par des artefact, le page sera décalé vers le haut pendant quelques millisecondes et se remettra à sa place après.

Il faut donc utiliser un event afin de savoir que le décalage vient/va se faire.  Nous utiliserons donc l’évènement SizeChanged pour cela.

bool previousState;
void Associated_ObjectSizeChanged(object sender, SizeChangedEventArgs e)
{
if (previousState == Microsoft.Phone.Shell.SystemTray.IsVisible)
return;
previousState = Microsoft.Phone.Shell.SystemTray.IsVisible;
if (Microsoft.Phone.Shell.SystemTray.IsVisible)
AssociatedObject.Margin = new Thickness(0, -32, 0, 0);
else
AssociatedObject.Margin = new Thickness(0, 0, 0, 0);

}

On utilise une variable afin de garder en mémoire l’ancien état, on verifie si cet état a changé, si c’est le cas, on change la margin de notre page (on pourrait très bien utiliser un rendertransform aussi mais il peut y avoir des soucis si vous avez déjà des transformation dessus).

L’utiliser

 

Pour utiliser mon behavior, c’est assez simple, ajoutez une référence vers Huyn.Systray.dll, et dans votre Expression Blend, il suffit de glisser le composant ‘SystrayBehavior’ sur votre page. Il faudra aussi décocher “Show SystemTray” dans les propriétés de votre page.

Le futur

Actuellement le behavior ne prend en compte que le mode portrait, je suis en train de terminer un Toolkit avec d’autres contrôles tirés de TVShow, Fuse et mes autres applications. Le SystrayBehavior inclut prendra en compte le mode paysage.

Télécharger

 

La DLL ‘Huyn.Systray’

Le code source avec un exemple

 

Comments are closed.