Now we come to one of the nicest additions that the TouchUI bring to the table - the animated navigation. This is, as so many other things in modern mobile user experience design, inspired by the way things work on the iPhone.
When the user select an item in a list (in a dialog), the following code is run in the main form:
private void navigateForward()
{
Common.Instance.PaintCopyGraphics.DrawImage
(Common.Instance.PaintBitmap, 0, 0);
if(dialogStack.Last() is MainDialog)
{
MainDialog mainDialog = (MainDialog)dialogStack.Last();
DetailDialog detailDialog = new DetailDialog(Common.Instance.ScreenFactor,
Common.Instance.ClientRectangle, mainDialog.SelectedLine + 1);
dialogStack.Add(detailDialog);
}
animationOffset = Common.Instance.ClientRectangle.Width / 4;
animationLeft = Common.Instance.ClientRectangle.Width;
}
As you may remember from the painting part of this series, the PaintBitmap (in the app's singleton class Common.Instance) is used to do all the painting in the app. Then, it is used in the OnPaint method to do the actual painting to the screen. The first thing that happen in the code above, is that a copy of the current screen is made (into the PaintCopyBitmap that is pointed to by PaintCopyGraphics). The navigation is done (the details form is added to the dialog stack), and then the animations horizontal start position (animationLeft) is set along with the offset to move the new screen into place for each frame (animationOffset, in this case it's in four steps making the animation take about a third of a second). The navigation backward (up the dialog stack) is done in a similar fashion, but then the animationLeft and animationOffset are both negative. Btw, the beautiful strawberry graphics is from a photo by Tina Phillips / FreeDigitalPhotos.net.
With this in place, the actual painting is done in the OnPaint method, and it looks like this:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
dialogStack.Last().Paint(Common.Instance.PaintGraphics);
Rectangle r = Common.Instance.ClientRectangle;
if(animationLeft != 0)
{
e.Graphics.DrawImage(Common.Instance.PaintCopyBitmap,
new Rectangle(animationLeft - r.Width * animationLeft.CompareTo(0),
0, r.Width, r.Height), r, GraphicsUnit.Pixel);
e.Graphics.DrawImage(Common.Instance.PaintBitmap,
new Rectangle(animationLeft, 0, r.Width, r.Height), r,
GraphicsUnit.Pixel);
animationLeft -= animationOffset;
if(Math.Abs(animationLeft) < Math.Abs(animationOffset))
animationLeft = 0;
}
else
e.Graphics.DrawImage(Common.Instance.PaintBitmap, r, r,
GraphicsUnit.Pixel);
}
First, the dialog is painted (updating the PaintBitmap with the new content), and then both the old and new bitmaps are painted according to the step in the animation (controlled by animationLeft). When the animation is complete (animationLeft is zero), only the new dialog is painted.
A similar approach is used for the switching of images in the detail dialog in the sample, so be sure to check that out as an example of responding to sweep gestures.