blog.reis.se

It's all about looks

The other day I was designing a dark static theme for Windows Phone. As I know it will be a dark theme, no matter if the user selects light or dark theme, I wanted to make sure the SystemTray was visible at all times. In this case I sat the opacity to 0 so that the background would be completely transparent. Then foreground was set to the theme foreground like this (that happened to be an all white theme):

shell:SystemTray.IsVisible="True"
shell:SystemTray.Opacity="0"
shell:SystemTray.ForegroundColor="{StaticResource CustomForegroundColor}" 

All seem ok until I did what every solid developer should do, take a light day - Once a week you should set your phone to use a light theme to see what damage a poorly designed application can do to the users. Actually I never release a software without going through every screen with the white settings. Even if you use standard phone theme.

However, even if the CustomForegroundColor is correctly set to #FFFFFFFF the SystemTray went black as soon as I shifted to light them. So after a fun search and test session I stumbled upon the solution, actually it’s well documented in the MSDN documentation. As it happens you can’t set SystemTray to white, any other color will work but not white. So the solution, in this case, was to set the SystemTray to something close to white, like #FEFFFFFF.


While the first iteration of Windows Phone was based on Silverlight 3 the upcoming release, mango, is based on Silverlight 4. That means a lot of new functionality like implicit styling and and rich text controls. Especially the last was interesting as it gives you a lot more control over the displayed text. What I was looking for, was to place a link in the text and have it open a web page from the application. If you want to get to the core just jump to the end of the post but first a bit of background on the rich text box.

About the rich text box

In mango there is a control called RichTextBox, that boost a lot of functionality like right to left text and inline formatting. I’m going to focus on adding an inline link to an external web page, as for example in a tweet. Before mango this wasn’t possible to do in a text box. There was workarounds like using the wrap panel from the Silverlight for Windows Phone toolkit or write your own control and add the text word by word).

The RichTextBox consists of a bunch of child elements and a set of properties that handles text flow and overall style. In the textbox you will add Paragraphs of text that can be broken down into text parts with attributes like bold, italic, Inline images, etc. There is also the Run that can have it’s on style when it comes to font, size and so on. That way it’s quite easy to build up a complex text. However, there is no support for it in blend so you have to dig into the XAML or code to get what you want:

<RichTextBox>
    <Paragraph>
        The quick <Bold>brown</Bold> 
        fox <Italic>jumped</Italic> 
        over the <Underline>lazy</Underline> 
        dog.
    </Paragraph>
</RichTextBox>

And on the phone you will get a little line of text like this:

quick01

You could do a lot more with it with both fonts and colors but the problem comes when you want to bind to it. You could do this in a few ways as well, if the text use some kind of markup you could have a converter do the work for you and translate this to elements needed or you can do (as I will show) an injection directly into the textbox. The XAML for what I want is like this:

<RichTextBox>
    <Paragraph x:Name="TweetParagraph"/>
</RichTextBox>

So I the result I want is to inject links and accented text so that I can present a tweet to the user. This end result I want is something like this:

Capture

Mostly it just the matter of breaking down the text in words (just split on space) and then add them one by one in the rich text box. This is done in a loop for each word, added to a paragraph in the rich text box like this:

foreach (var tweetWord in tweetWords)
{
    if (tweetWord.StartsWith("http://"))
        TweetParagraph.Inlines.Add(GetAsLink(tweetWord + " "));
    else
        TweetParagraph.Inlines.Add(GetAsRun(tweetWord + " "));
}

I also identified words that start with # or @ and add these with accent color. You could of course add them with click functionality as well to handle things like navigating and showing a twitter user etc but I think you get the idea.

private Run GetAsRun(string tweetWord)
{
    if (tweetWord.StartsWith("#") || tweetWord.StartsWith("@"))
        return GetAsAccentedRun(tweetWord);

    return new Run { Text = tweetWord };
}

private Run GetAsAccentedRun(string tweetWord)
{
    return new Run
               {
                   Foreground = _accentColor,
                   Text = tweetWord
               };
}

But now for the actual link

At first I hade trouble with it, normally a link just points around in your application. It don’t target the browser and that goes for a hyperlink as well. So my first solution was to catch the click event and on that create a new browser task with the URL. But this seems a bit awkward for just a web link. And indeed there was a simple solution to make sure it opened in a browser window.

private Hyperlink GetAsLink(string tweetWord)
{
    var hl = new Hyperlink
    {
        NavigateUri = new Uri(tweetWord),
        TargetName = "_blank",
        Foreground = _accentColor
    };

    hl.Inlines.Add(tweetWord);

    return hl;
}

The trick here is in the TargetName using the _blank as you do in a normal HTML link ensures that you open a new browser window, even if the link is placed in you Windows Phone application. And if you want that directly in XAML then it will look like this:

<Paragraph>
    <Hyperlink NavigateUri="http://jayway.com" 
               TargetName="_blank">jayway.com</Hyperlink>
</Paragraph>

Neat!


The dust from what was presented at Mix11 has long settled and the mango released had been packaged. The tools are with us and we are just waiting for the update to officially reach the phones. So I will do a quick view on background execution in the light of a post I did a few months ago: WP7: Background execution – really?

As it turns out I wasn’t that far from what was presented. Lets go through each point.

The audio service first

What I said around audio service was to make use of:

…the Zune media player. Why would I want to create a new player over and over again? Wouldn’t it be better to integrate with the current? If the API was richer…

It’s just what they provided for us. They call it the Zune service and it’s very easy to use as well. You need of course create a background player agent that is entitled to continue feeding the audio service with tracks to play. The metadata is fully controllable as well using the AudioTrack class that holds lots of information like:

  • Title
  • Artist
  • Album       
  • Tag
  • Duration
  • AlbumArt
  • Source
  • PlayerControls

And as an added bonus it can even be controlled from the web. It will be possible to build an audio player in HTML5 that continues to play the music in the background. Nicely done!

GPS application

My suggestion was to just start the GPS service and start tracking the point in a cache so that not only the current application would access the GPS but also let other application using it at the same time. Also there should be a possibility to trigger a background task on events like each kilometer or every 5 minutes. As we know now, these ideas wasn’t realized in the current version so for RunKeeper and applications like it. It’s still run under screen lock that is the solution.

There are some traces of tracking if you look a bit deeper and do a few undocumented calls. But it’s nothing that is official and an application using it probably wont make it through to marketplace. However, it might very well hint on upcoming functionality and official APIs.

Task scheduling

I also suggested something along these lines of operation:

Why not support some kind of task scheduling instead of true background operation.

Well I missed the naming of this functionality, I should call the code snippets brought back to life agents and I would be spot on. The only exception is the rate of how the agents are run.

Conclusion

In all I think they mostly managed to live up to the users and developers needs here. And now with the mango release fully on its way to the windows phone out there and upcoming models it will certainly be a a lot of fun. 


no_batteryThe last couple of days the battery life on my Windows Phone Mango has been catastrophic. I wasn’t able to last more than 3-4 hours, tops. Then the battery saver icon appeared (battery with a little heart over it) and gave me a couple extra hours, it really is a saver. The only thing that I could think of, that I had changed, was that shuffling the images used as background in pictures hub. So I began to restart, charge, changed settings, disconnected Wi-Fi. I tried all kind of tricks that affects battery life. No luck.

Then I thought that maybe I should stop syncing mail so often and se what effect that would have. When I tried to change my settings I saw how it was syncing mail, lots of mail in my account. It never seem to stop and suddenly it hit me:

I might have set it to sync my All mails folder in my Google mail, and that isn’t a good thing. If it tries to sync all then there is 56 472 conversations dragging around in my Google account (I haven't thrown away any mail, except for spam mail and mailing list, the last 8 years). And even if I narrow this down to the last 7 days it’s a lot of mail to sync in the background. No wonder it was draining the battery. An I was right.

Actually here are a few areas that can improve in the user interface. Doing all this syncing was not good for the performance of the mail application either. I even had trouble to stop the sync of the All mails folder. And while the account was syncing I wasn’t able to remove it or change any settings on it.

In the end I figured that the easiest way to get rid of it all was to just go into flight mode, remove the account and then add it again (after going out of flight mode). This time I made sure it’s just the inbox that is synced. And now all is back to normal again or even better.

So be careful with what you sync or it may really kill the battery on your device.


We (Andreas Hammar and I) are just returning from Tech-Days 2011, we delivered a session on developing applications for Windows Phone 7 in Blend and code. While we were preparing for this session something stuck in our minds - when it comes to mobile applications the top priority is in design and performance.

Design and performance over architecture and frameworks

We have to focus our attention on the user experience, how the application is perceived and not what technology is used or how the application is built. The important thing is that the application is well designed and that it responds to the user. SO to be a WP7 developer there are two things you really have to study, and study hard:

Design
Performance

We're not suggesting that you throw out all the knowledge around architecture and framework. But, if it impacts design and performance you should think twice about why. Also, as Johan Lindfors said in his session – “stop building frameworks! Start building applications”

Slides and samples

Anyway, to sum this up we share the slides on slideshare as well as provide the code and slides as files below.

 

 

Windows Phone 7 in blend and code – code
Windows Phone 7 in blend and code - slides

Resources

Following is a collection of useful links to get started with real development - just promise you don’t build another framework.

Be creative! // Andreas Hammar & Håkan Reis 


Touch is great thing, suddenly you can touch, tap, double tap, flick, pinch and stretch to manipulate virtual object. It really revamped the whole mobile business mainly with the release of the iPhone and the capacitive touch screens, used in most smartphones today. But also in the stuff using infrared matrix screens like the Neonode back in 2004 that had quite good gesture control but never took off.

But let the touch stay there in a virtual interface on the screen. We all know and love what we got there. But if you have a real physical nice button DON'T MAKE IT A TOUCH BUTTON. Physical buttons should stay physical, a touch button is actually just an approximation to the real thing. That was cool in the 80-ties. If you really, really, can't help yourself, at least keep them safe from accidental touch. I’ll give you some example from bad to worse …

WP_000010
The new XBOX 360

This device uses touch to open the tray door and for the on/off switch. Its not a big problem here, the XBOX isn’t moved around much and mostly you don’t touch it by accident. But sometimes, you need to move it. I have it hidden away and I was opening the doors and accidently opened the tray. The sound it made when it hit the wall wasn’t too pleasing but it survived.

WP_000127
My stove

This one is even more annoying. The buttons are placed close to where you normally would have physical buttons and it works well when you and navigate them. But there are a few occasions… If you accidentally cover them they start to do all sorts of crazy stuff until the stove, as a security feature, shut down totally. Also, when you have a big handle cover one panel it reacts,  suddenly you wonder what happen until you realize that you have turned off the heat.

photo (1)
My Samsung Omnia 7

This is by far one of the worst examples of touch buttons. It doesn’t provide any functionality other than looks (and I think you could have gotten the same look with real buttons, with the right materials). It is constantly in the way and trying to play a game is almost impossible as you have your whole thumb over the buttons. I nearly thrown this out the window…

Are there any good versions?

Well I think my old Bang&Olufsen sound system from 1991 is ok, touch button is not a killer feature but adds coolness to this piece of machinery, not that I know what I’m going to use my CD-player or cassette deck for anymore Smile

WP_000008  WP_000012
B&O 4500 with the military grade remote - could easily take out any enemy

It’s also good in that it’s easy to keep clean, it does not produce any false taps or clicks (being placed on a wall and all). It’s only a design thing using touch here but it doesn’t make it worse, besides, it’s the massive one pound remote that is used to control this…

The stove, again, is actually also a good contender for touch buttons:

WP_000014
Easy to clean

There is one really good reasons for using touch here and it compensates for the problems. It’s so easy to keep clean.

So, a final plea!

I first thought of this when I moved in and started the fight with my stove. Then there was mockups leaks of the Windows Phone 7 HTC models. Then when I got my Samsung Omnia 7 in October. I think this is THE most annoying “feature” of the Omnia. But now there as a bigger threat - the mockups that Nokia made for the new Windows Phone 7 models. Look here:

ConceptNokiaWindowsPhones1

This is really scary, touch buttons, and even worse than the Samsung Omnia, the home button is also touch here. This is going to drive at least me crazy. So please forget about touch here!


officeAs you might have seen in the Windows Phone 7 Office application there are small round buttons in the panorama. As you should never use the application bar in the panorama it’s a good way to get some navigation points into the panorama. There are a few versions of this button out, ranging from styling a button and up to complete controls. However the ones I have found have things I don’t like, mostly they work with black and white images or with paths for the icon.

So I started out with a few basic specifications, I wanted:

  • A simple control to use, no special content
  • Only mage for the button (white with alpha channel)
  • To be able to easily add content next to the button
  • Ability to re-skin the button

The goal was to be able to define a button with just a simple:

<jc:RoundButton Image="/icons/refresh.png" Content="refresh" />

For those that don’t want to find out about my journey towards the RoundButton control there is a zip with the code and a sample project at the very bottom of the post…

When I first started out with the basic design the approach was the same as for others out there, two images that was swapped on light theme and shifted on pressed state. But I didn’t like it, I wanted the control to handle the image inversion stuff so my next thought was to create a new image with Writable bitmap and do some pixel magic, but before I got that far I stumbled on a blog post on displaying an image in the accent color. This was brilliant, using the image as a opacity mask, I could have whatever color I liked. So the core of the control got to be something like this:

<Rectangle x:Name="ImageForeground" Height="48" Width="48"
  Fill="with_whatever_color_or_template_color">
  <Rectangle.OpacityMask>
    <ImageBrush ImageSource="image.png" Stretch="Fill" />
  </Rectangle.OpacityMask>
</Rectangle>

The code

On to the control design, first of was to create the code behind for the button, creating the attached properties. This code ended up looking like this:

public class RoundButton : Button
{
    private object _layoutRoot; 
    public static readonly DependencyProperty ImageProperty  = DependencyProperty.Register("Image", typeof(ImageSource), typeof(RoundButton), null); 

    public RoundButton() : base()
    {
        DefaultStyleKey = typeof(RoundButton);
    }
    

    [Description("The image displayed by the button in dark theme (and in normal mode)"), Category("Common Properties")]
    public ImageSource Image
    {
        get { return (ImageSource)GetValue(ImageProperty); }
        set { SetValue(ImageProperty, value); }
     }

    public override void OnApplyTemplate()
    {
        _layoutRoot = GetTemplateChild( "LayoutRoot" ) as Border;
        Debug.Assert( _layoutRoot != null, "LayoutRoot is null" );
        base.OnApplyTemplate();
    }
}

Hurdles and solutions

So the template stuff should be easy now right? Just add the Image to ImageSource for the Brush like this:

<ImageBrush ImageSource="{TemplateBinding Image}" Stretch="Fill" />


Wrong! Turns out you can’t bind to an ImageSource in an ImageBrush, because ImageBrush don’t inherit from FrameworkElement, as BMiloshevska pointed out. Argh, so close. Back to the drawing board until Derek Lakin pointed me at an article about using a converter as a workaround. Here is the converter stuff:

public class ImageBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        BitmapImage image = (BitmapImage)value;
        ImageBrush imageBrush = new ImageBrush();
        if (image != null)
        {
            imageBrush.ImageSource = image;
        }
        return imageBrush;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


Getting closer, but still there are a few hurdles left as you will see. Now it seems you can bind the ImageBrush to the DependecyProperty with a Converter, like this:

<ImageBrush ImageSource="{TemplateBinding Image, Converter={StaticResource brushConverter}}" Stretch="Fill" />


Wrong again! You can’t use a converter on a TemplateBinding, sigh. Then a new angle: The DataContext. You can TemplateBind the image to the DataContext and then use a normal binding (with converter) for the brush. Success! The binding ended up looking like this:

<Rectangle x:Name="ImageForeground" Height="48" Width="48"
    Fill="{TemplateBinding Foreground}"
    DataContext="{TemplateBinding Image}"
    OpacityMask="{Binding Converter={StaticResource brushConverter}}" />

The template

So now it was the last part left, creating the template style with states for normal, pressed and disabled. The last one is a bonus, with the image approach you would now need three images, white, black and grey, no you can use whatever you like. The template was placed in Themes/generic.xaml and looks in part like this (the full xaml is included in the zip):

<Style TargetType="local:RoundButton">

  <!-- Basic template setters -->

  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="local:RoundButton">
        <Border x:Name="LayoutRoot" Background="Transparent" Padding="12" >
          <VisualStateManager.VisualStateGroups>

          <!-- The states Normal/Pressed/DIsabled/... -->

          </VisualStateManager.VisualStateGroups>

          <!-- The actual button template where the image and content goes -->
          <Grid>
            <StackPanel Orientation="Horizontal">
              <Border Height="48" Width="48" x:Name="ButtonBackground" BorderThickness="3" CornerRadius="24" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" >
                <Border.Resources>
                  <local:ImageBrushConverter x:Key="brushConverter"/>
                </Border.Resources>
                <Rectangle x:Name="ImageForeground" Height="48" Width="48" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}"
                    DataContext="{TemplateBinding Image}"
                    OpacityMask="{Binding Converter={StaticResource brushConverter}}" />
              </Border>
              <ContentControl VerticalAlignment="Center" Margin="0" HorizontalAlignment="Left" Padding="8,0,0,0" Content="{TemplateBinding Content}" />
            </StackPanel>
          </Grid>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

There, finally I reached my goal!

Improvements

So am I done now? Yes and no. The functionality is in place and the first four goals reached but there is more stuff I like to do:

  • I want to add some optional animation, for example the push behavior from the AppBar and the tilt effect (actually you can use the tilt effect that Peter Torr blogged about, as the control is based on a button)
  • I think there is a workaround to the Converter, I would like to eliminate that part.
  • Also create a round toggle button with two images (for example play/pause media button)

If anyone happen to have a solution or idea around those issues I would be happy to know.


The zip includes the control and a test project to try it out.