blog.reis.se

It's all about looks

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.


One of the major complaints on the Windows Phone 7 platform is that you can’t run third party applications in the background. I had the same complaint on iPhone for a long time but over the time I have started to think about the problem and I’m not sure background operation for third party application is the only way to solve all the problems.

Let’s look at two scenarios that I think are the most common for background operation: Music player services like Spotify or Last.fm and GPS related applications like the RunKeeper GPS tracker. In these two main scenarios I think a richer and more service oriented API within the phone could take care of the problem instead of background execution.

Lets focus on the audio service first

No doubt that you need it to continue playing music while you work on other stuff. That’s not what I suggest but instead I want you to think of the application that is native in the phone, 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, in the Spotify case it would be possible to:

  • Plug in the codec + DRM that’s used in Spotify
  • Create and use playlists from either streamed material or locally stored material – or both
  • Update the background image and access to all the data that is visible in the player
  • Add the playlists as your own into the Zune player and for example mark them with a Spotify icon fro branding

The benefit with this would be many: Apart from not taking up precious development resources for cloning the Zune player over and over, you could let Microsoft take care of creating the most effective background enabled audio/video player.

To the user there is also the benefit of using the familiar way of navigating the audio as always instead of a new one for each application.

Now over to the GPS application

Why do you need to run this in the background? Well there are lots of reasons, but mostly it’s to be able to track and later plot your location from the track you are currently running. This functionality could also be handled with a service similar to the audio service. Why not trigger the GPS service to start tracking and storing the points. This would actually give even more advantages. This way two GPS enable applications could be using the same GPS track store and bring up the points. Again this would let the developer focusing on delivering an awesome application and not how to handle the GPS API effective enough not to drain the battery.

Moving on to task scheduling

There are of course situations where this approach won’t solve your issue but it’s good start to think in other directions when it comes background execution. Why not support some kind of task scheduling instead of true background operation. Here’s an example of what I mean:

In the GPS tracker situation there is an other issue that should be solved. The RunKeeper application vocally reports information on speed, average speed, distance, etc. This would normally be handled with an application running in the background. But it would also be possible to let simple tasks or code snippets be triggered with a set of rules based on the GPS tracker, like time, speed or distance.

I wouldn’t call it multitasking as the application isn’t really running in the background. It is just providing the code that should be brought back to life on certain points and then go to rest again, it can even be fully exited instead of suspended. To the user it would be of no difference if the application is running, suspended or exited as long as it behaves as if it was running in the background.

Conclusion

I think that in many situations we tend to take the obvious solution. While an alternative and for the user actually better way can be achieved if you think twice about it.

And there is an embryo to this in the Zune application, you can let your application launch the Zune player with a URL (either a net stream or locally stored) and it works great. But the API needs to be richer as I would want to insert Metadata and create lists for this as well as be able to provide a codec for handling media streams that Zune cannot play out of the box.

The market will continue to demand background enabling, and Microsoft will probably support that sooner rather than later but I really think we would all benefit from this thinking, both as developers and users.


Building an audio application this weekend I ran into a problem; where do you place the media element when you have more than one page, and you want the audio to continue playing when you navigate between pages. I will get to the solution later on in the post but first some background.

During the weekend our .NET team spent two days with Windows Phone 7. A few weeks ago we brainstormed around a few application ideas. The ultimate goal from the weekend was to se how far we could get in about a day of coding. To get us all kick started we were happy to have Dag König with us to talk about windows phone 7 development and support us during the weekend with ideas and hardware.

We split into several groups and my group focused on an audio application with streaming media, based on listings from an XML source. The available streams were presented in a list and selecting one navigated us to another page where the player was located. Of course there was a lot of different problems solved during this session but one of them was as follows:

We wanted the stream to start playing when we navigated to the Player Page and continue to play in the background when we returned to the stream list in the Panorama Page. It shouldn’t stop until we directly stopped it or a new stream was selected.

After some thinking it was obvious that we needed place that’s globally accessible for the media element responsible for the sound. One such place is the application level, and it turned out to be the way to solve this. But you can’t just drop element in the xaml and be done, that would be too simple. However, the solution wasn’t that far away. I placed it in the common resources instead and used a property to expose it globally for the pages. So the first code part is from the app.xaml file:


  ...
  
    
    
      
      
      
      
      
        
      
    
  

And in the code behind you find the properties parts to make it accessible from the pages in the application (through App.GlobalMediaElement). The property is set the first time the media element is loaded (via the Loaded event) and then it’s just returning the original media element on reoccurring calls:

private static MediaElement _globalAudioElement = null;

public static MediaElement GlobalAudioElement 
{
  get { return _globalAudioElement;  }
}
        
private void OnMediaLoaded(object sender, RoutedEventArgs e)
{
  if (_globalAudioElement == null)
    _globalAudioElement = sender as MediaElement;
}

Finally in the end of app.xaml.cs there is the initialization section and here I injected the global media element in the system with the template from the resource:

private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
  if (RootVisual != RootFrame)
    RootVisual = RootFrame;
  
  RootFrame.Navigated -= CompleteInitializePhoneApplication;
  
  // Add this to inject the media element Control template          
  RootFrame.Template = App.Current.Resources["AudioContentTemplate"] as ControlTemplate;
}

And now you can access the MediaElement form any page and do your stuff almost as if it was added the the page itself with:

App.GlobalAudioElement.Source = streamUri;
App.GlobalAudioElement.Play();

That’s all there is to it, hope it helps someone out with the same problem we had. There is actually another solution but that one includes a bit of XNA coding, for this scenario it was enough with the above solution but if you need a more detailed and advanced control over the audio in your application I recommend looking into XNA.

// Håkan Reis


Untitled-2Today the Smooth Streaming Client was updated to also work for the Windows Phone 7 and looking in to video streaming for an upcoming project this was indeed very good news. (Lets just hope the Silverlight Media Framework will be upgraded as well!) The first test I did was to check how easy it would be to at least add and view a streaming file in Windows Phone 7.

In my case I wanted to check if it was possible to play in a mixed view, not only a full screen video view. So I created a simple application with both a video and some surrounding text. Looking something like the image to the right, with live video in the small player.

First things first, download the client software from the above link and install it. After that add a reference to Microsoft.Web.Media.SmoothStreaming and add the reference in the XAML as well:

xmlns:ss="clr-namespace:Microsoft.Web.Media.SmoothStreaming;
assembly=Microsoft.Web.Media.SmoothStreaming"

The its just a matter of adding the SmoothStreamingMediaElement in the code and point the SmoothStreamingSource to a smooth streaming video source. However, here comes a little problem (that a proper prototype would have solved, hrm, Microsoft). The emulator doesn't support that many codecs, even if the phones will support a lot. But a normal SD quality VMA encoded smooth streaming source did the trick for me. The MSDN documentation has most of the information needed to get it right. My final bits an pieces for the smooth streaming media element lookes like this:

<ss:SmoothStreamingMediaElement 
  AutoPlay="True" 
  SmoothStreamingSource="http://<server>/<file>.ism/Manifest"
  Height="98" />

Of course the [server] and [file] content should be set to something you have access to. The biggest problem for me was to get hold of an appropriate stream source, luckily for me (as I didn’t have the time to set one up myself nut it shouldn’t be that hard) I was able to use a stream from an internal project just to test things out.


As soon as I get my hands on the real hardware I will try it with Big Buck Bunny

// Håkan Reis


JayPokerI was trying out a few things on the windows phone 7 platform and wanted to come up with a simple application idea. There are numerous of simple list application examples out there like twitter and RSS readers but I wanted to try something different, something both useful and a bit more playful. And with a limited time.

So why not a planning poker application? Most of the graphics was already there like the coffee cup, infinity mark and the logo so it was simple to whip it together. But I still think there are a few interesting parts in this.

As it’s static data, there are no more than the numbers, coffee cup, question mark and the infinity sign.  I didn’t bother with any complicated view model, just went along with static buttons. And one big button as the currently selected card. I re-styled the button to make it look like a card and added the graphics and text. The big card is normally hidden but when I select a card it is populated with the selected cards content and the popped up.

The trick here is that if the selected card is an Image the I create a new image and assign it to the content and if its text I assign that directly to the content.

if (_currentCard.Content is Image)
  BigButton.Content = new Image
    {
      Source = ((Image)_currentCard.Content).Source, 
      Height = 234, 
      Width = 202
    };
else
  BigButton.Content = _currentCard.Content;

Next up is the animation. I wanted the card to flip over while I tuned up the dark overlay. The basic animation was easy to set, I just used a combination of scale and plane transforms to get the big card from the small size and up to the full screen view with a flip. It was a bit trickier to get the card to start and end the animation on the right spot. A little calculation together with naming of the places where I should modify the animation, with  an “x:Name” property, did the trick. Now I was able to modify it from code using the following to set the position:

int xValue = -180 + 120 * 
    int.Parse(_currentCard.GetValue(Grid.ColumnProperty)
     .ToString());
int yValue = -260 + 190 * 
    (int.Parse(_currentCard.GetValue(Grid.RowProperty)
     .ToString()) - 1);

((EasingDoubleKeyFrame)FindName("startX")).Value = xValue;
((SplineDoubleKeyFrame)FindName("endX")).Value = xValue;
((EasingDoubleKeyFrame)FindName("startY")).Value = yValue;
((SplineDoubleKeyFrame)FindName("endY")).Value = yValue;

It's not the most elegant code, with no safeguards when I cast between stuff, but I whipped it together during an afternoon and it was rewarding to see what could be accomplished with some 50 lines of code and a little blend. And who knows I might clean it up and publish it as soon as the devices are out and the market place is up.

Time to plan the next sprint // Håkan Reis