Making Tip Calculator for Window Phone 7

TL;DR To try out WP7 tools I made Tip Calcuator

The so-called business logic is very simple and is not very different among various versions of Tip Calcs out there. Yet, what I would like to show is my way of Metro UX which I do believe is still a part of family.

A few interesting bits: When Textboxes are pressed, they move up and down.

<Storyboard  x:Name="mainInAnimation">
  <DoubleAnimation Storyboard.TargetName="ContentPanel"
   Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
    Duration="0:0:1" To="-20" >
    <DoubleAnimation.EasingFunction>
      <ExponentialEase  EasingMode="EaseOut"  />
    </DoubleAnimation.EasingFunction>
  </DoubleAnimation>
 <DoubleAnimation Storyboard.TargetName="TitlePanel"
   Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
   Duration="0:0:1" To="-20" >
   <DoubleAnimation.EasingFunction>
     <ExponentialEase  EasingMode="EaseOut"  />
    </DoubleAnimation.EasingFunction>
 </DoubleAnimation>
 <DoubleAnimation Storyboard.TargetName="ContentPanel"
    Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" To="1">
    <DoubleAnimation.EasingFunction>
      <QuadraticEase EasingMode="EaseOut"  />
     </DoubleAnimation.EasingFunction>
    </DoubleAnimation>
</Storyboard>

Styling

I have made a few changes to the default style.

  • opacity of TexBox is 0.7
  • different margins (careful with that and bear in mind the rule of thumb - 0.9mm
  • alignment
  • theme aware styles (like PhoneTextLargeStyle)

That is all about XAML, now C#.

public MainPage()
{
   InitializeComponent();
   this.LayoutUpdated += new EventHandler(MainPage_LayoutUpdated);
}

The ctor is kept light-weight for faster start of the app. All the details are handled by MainPage_LayoutUpdated event handler.

private void MainPage_LayoutUpdated(object sender, EventArgs e)
{
    if (m_onNavigatedToCalled)
    {
        m_onNavigatedToCalled = false;
        Dispatcher.BeginInvoke(() =>
        {
                Random random = new Random();
                var number = random.Next(1, 3);
                string fileName = String.Format(@"Images\background{0}.jpg", number);
                backgroundBrush.ImageSource = new BitmapImage(new Uri(fileName, UriKind.Relative));
                radioButton3.IsChecked = true;
                mainInAnimation.Begin();
        });
     }
}

Since we need to prepare things when everything is loaded MainPage_LayoutUpdated is a proper event, but it’s called every time when layout has been updated, hence m_onNavigatedToCalled flag is set to true and after first call it’s set to false. Dispatcher.BeginInvoke is a thread-safe asynchronous method for UI changes (mainly). In lambda expression the random background is picked and animation begins (I prefer do it in code).

Orientation.

private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
    if ((e.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
    {
        Grid.SetRow(bottom, 1);
        Grid.SetColumn(bottom, 0);
        sumStackPanel.Margin = new Thickness(35, 30, 0, 0);
    }
    else
    {
        Grid.SetRow(bottom, 0);
        Grid.SetColumn(bottom, 1);
        sumStackPanel.Margin = new Thickness(-5, 30, 0, 0);
    }
}

To keep UI concise I have divided main Grid into 2 columns and 2 rows. After OrientationChanged event occurs bottom grid is set to next column. For the orientation changes the Hybrid animation do a nice job.

And here is a demo. (animations are a bit choppy because of emulator + recording software) ;)

Feedback and comments are welcome.

Written on November 2, 2010