Transparent Live Tile For Windows Phone 8.1

Transparent Live Tile For Windows Phone 8.1

Windows Phone 8.1 Dev Preview

Windows Phone 8.1 developer preview is totally awesome. So what is one of the most important things app devs can do right away, without much fuss, to make their apps look great with Windows Phone 8.1? Revisit your app’s Live Tile images. Why? In 8.1, Start screen is mesmerizing with the parallax effect and Live Tile with background overlay. Dev preview users are going crazy with new Start experience, and I am sure, with public release, end users are going to love to have background image as well. Take a look at this awesome Nokia Lumia 925 Start screen:

wp_ss_20140416_0015[1]

When users have a background image, they might not like to have solid Live Tiles block their beautiful background. So, revisit your app’s Live Tile images – all of them! Check if they are transparent or not? If they are like Cortana, Avirall Time Suite, etc. in the image above, you are all set. You can safely ignore this article and find some other awesome way to improve your app for WP8.1 (think Cortana). If they are not, I suggest to update ‘em ASAP. And it’s easy, too. Let’s see how you can create transparent Live Tile images with Open Source Inkscape. You could choose to use Paint.NET (not MS Paint), Photoshop, GIMP, or any other tool which allows you to export image with transparency. Though I prefer GIMP for image editing but I chose Inkscape for this demo. Let’s go.

Step 1: Setup the page

InkScape01

  1. Open Inkscape and create a new document and Open Document Properties from file menu.
  2. In most cases app icons are solid white, if yours is one too, change the background color of the page, temporarily, to light yellow. This is while working only so that you can see white color. Before exporting we will reset this to transparent (this is very important).
  3. This example is for 336 X 336 medium tile. So set the custom size to 336 X 336.
  4. Make sure Units is “px”.

Step 2: Setup the drawing

InkScape02

Windows Phone 8 Asset Template Guide suggests a 336 X 336 tile to have 110px margin on all sides. Create 110px margin guides on all the sides. To create margin guides click and drag from the horizontal ruler on the top and from the vertical ruler on the left.

Step 3: Create Live Tile image of your app

InkScape03

The center part between the margins is the space where your tile image will go. Create your image here. For this example I simply dragged the box from tool box and made a hole in it :D

Step 4: Set background to transparent

InkScape03a

To create a transparent Live Tile image we would like to have a transparent background. Go back in document properties and set Background to transparent by resetting “A” to 0. If your image is solid white, you might not see anything after making the background transparent. Don’t worry, your image is there (maybe somebody can tell how working space (not document background) in Inkscape can be made a different color than white).

Step 5: Export

InkScape04

  1. Open Export dialog from File > Export Bitmap…
  2. Set X0, X1, Y0, Y1 as shown in the image above.
  3. Browse for the image location, and make sure you give “PNG” as the extension of the image, NOT JPG or BMP.
  4. Export. (Alternatively, as suggested by Austin Andrews, you could export as SVG, and use his awesome service!)

Step 6: Check Final Image

WindowsPhotoViewer05

Notice that your final image does not have a white background. Windows Photo Viewers’s light blue background is your image’s background.

You are done. You would want to change all Live Tile images of your app in the same way. A transparent Live Tile image will encourage users to have your app pinned to Start screen without obstructing their beautiful background images.

Respect your users!

Cortana Talking To An Indian

Here is a quick trial of Cortana on WP8.1 dev preview on my Nokia Lumia 925. The funniest one is:
Me: “Sing me a song”
Cortana: “O Danny Boy the pipes are pipes are calling” :D

See for yourself some fantastic capabilities of Cortana along with some funny takes, 0_0 :

App Marketing: Panorama Image Template

Be Awesome by eskimo_jo, on Flickr
Be Awesome, a photo by eskimo_jo on Flickr.

If your app has a panorama hub, an image showing all the pano items with device could be a very impressive marketing image. I have created this template which makes your life a bit easier, if you want to create such image. You can download the template XCF image file here (yes this is a GIMP template 0_0. I may create PSD edition if you insist). Currently the device image in this template is Microsoft Windows Phone stock emulator image, Nokia Lumia device images could also come in future. When you open this XCF in GIMP you get something like this:

MarketingCompInGiMP

Take snapshots of your app’s pano items from emulator and replace screen 1, 2, 3, and 4 in GIMP with respective images. Once you are satisfied with the image, export it to JPG/PNG with File > Export option. You might want to scale the image down before you send it out. Open the exported JPG in GIMP and use Image > Scale option to scale the image to desired scale.

Notes:

  • This is 1080P edition (480X800 version is on its way, see below), so your emulator/device screen shots should also be 1080P.
  • If your pano has BG image, disable it before you take screen shots and give it a plain #00ff00 color. After copying the screens in GIMP, select #00ff00 color in layer and replace it with alpha. Repeat for all pano items. In the end have a stitched, single background image, and copy it on the background layer in GIMP. You are doomed if you have #00ff00 color in other parts of your pano images, other than BG :-D. (Just kidding, choose some other color for BG which is unique).
  • Because of parallax effect in panorama, you will get repetitive panorama title in your app’s screen shots. Initially, copy the screen as they are. Then, in GIMP, with Rectangle selection tool (R), select the title part, Ctrl+X and Ctrl+V to make another layer. Do same with all the pano items. Select Move tool (M) and move pano item 2, 3, 4’s title sections to left to adjust with pano item 1.
  • Watch this space for a 480X800 version. Or follow me on Twitter @sanjayAtPilcrow.

C#|.NET : Size String, Truncate Lines

Swiss Crop Circle 2009 Aerial by Kecko, on Flickr
Swiss Crop Circle 2009 Aerial, a photo by Kecko on Flickr.

I needed to truncate lines from CSV string prepared for export through mail in my app. Windows Phone mail restricts text size to 1MB. In my app’s case some CSV reports could go beyond 1MB. To make sure that the CSV report does not exceed a desired size in bytes, I created this extension method – SizeIt. SizeIt can truncate lines (and characters if required) from a given string from beginning or from end and also inserts information text line (how many lines and characters removed) in the resulting string. Following is the test form created to show what the method does to a string. In this example a 300 byte 10 line string is given as input and asked to reduce it to <200 bytes, first from beginning, and then from end.

SizeTail

SizeFront

Here is the code for the extension method:

    public static class StringBuilderExtensions
    {
        /// <summary>
        /// Sizes StringBuilder to given size
        /// </summary>
        /// <param name="sb">StringBuilder</param>
        /// <param name="bytes">Maximum Size of resultant string. Mostly the size of string will be less than max size</param>
        /// <param name="removeLinesFromBeginning">Pass true, if clipping has to happen in the beginning</param>
        public static void SizeIt(this StringBuilder sb, int bytes, bool removeLinesFromBeginning)
        {
            bool _stringReplacementHappened = false;
            bool _maxBytesAdjusted_for_lines = false;
            bool _maxBytesAdjusted_for_chars = false;
            string _insertThismessage = "";
            int _linesRemoved = 0;
            int _charsRemoved = 0;
            //try removing lines.
            while (System.Text.Encoding.Unicode.GetByteCount(sb.ToString()) > bytes)
            {
                char _alternateNewLine = '\r';
                string _workingString = sb.ToString();
                if (!_workingString.Contains(Environment.NewLine) && !_workingString.Contains(_alternateNewLine))
                {
                    break;
                }
                int _newlinelocation = sb.ToString().IndexOf(Environment.NewLine);
                int _lastNewlinelocation = sb.ToString().LastIndexOf(Environment.NewLine);
                if (_newlinelocation <= 0)
                {
                    _newlinelocation = sb.ToString().IndexOf(_alternateNewLine);
                }
                if (_lastNewlinelocation <= 0)
                {
                    _lastNewlinelocation = sb.ToString().LastIndexOf(_alternateNewLine);
                }

                if (removeLinesFromBeginning)
                {
                    sb = sb.Remove(0, _newlinelocation + 1);
                    _linesRemoved++;
                    _stringReplacementHappened = true;
                    _insertThismessage = string.Format("... {0} lines removed{1}", _linesRemoved, Environment.NewLine);
                }
                else
                {
                    int _lastReturnAt = _lastNewlinelocation;
                    int _charsInLastLine = sb.Length - _lastNewlinelocation;
                    sb = sb.Remove(_lastReturnAt, _charsInLastLine);
                    _linesRemoved++;
                    _stringReplacementHappened = true;
                    _insertThismessage = string.Format("{1}{0} lines removed...", _linesRemoved, Environment.NewLine);
                }
                if (!_maxBytesAdjusted_for_lines)
                {
                    bytes -= 50; //40 extra bytes for information text
                    _maxBytesAdjusted_for_lines = true;
                }
            }
            //if it's still more than the desired size
            if (System.Text.Encoding.Unicode.GetByteCount(sb.ToString()) > bytes)
            {
                int _currentBytes = System.Text.Encoding.Unicode.GetByteCount(sb.ToString());
                if (!_maxBytesAdjusted_for_lines)
                {
                    bytes -= 100;
                    _maxBytesAdjusted_for_lines = true;
                    _maxBytesAdjusted_for_chars = true;
                }
                else if (!_maxBytesAdjusted_for_chars)
                {
                    bytes -= 50;
                    _maxBytesAdjusted_for_chars = true;
                }
                int _removeChars = (_currentBytes - bytes) / 2;
                if (removeLinesFromBeginning)
                {
                    sb = sb.Remove(0, _removeChars);
                    _stringReplacementHappened = true;
                    _insertThismessage = string.Format("... {0} lines and {1} chars removed{2}", _linesRemoved, _removeChars, Environment.NewLine);
                }
                else
                {
                    sb = sb.Remove(sb.Length - _removeChars, _removeChars);
                    _stringReplacementHappened = true;
                    _insertThismessage = string.Format("{2}{0} lines and {1} chars removed...", _linesRemoved, _removeChars, Environment.NewLine);
                }
            }
            if (_stringReplacementHappened)
            {
                if (removeLinesFromBeginning)
                {
                    sb.Insert(0, _insertThismessage);
                }
                else
                {
                    sb.Append(_insertThismessage);
                }
            }
        }
    }

You may extend SizeIt to make it even smarter because it has following shortcomings in current version:

  • Does not truncate very closely to Max size. Will always be less than 50 bytes from max.
  • If there are only two lines and line of truncating side is huge, even a slight reduction in size will remove the complete content of the huge line, meaning loosing most of the text. This could be taken care of by firsts analyzing the string and then truncating line/character, as required
  • The logic inherently tries to remove lines first, should intelligently decide whether to remove line or chars.

Hi, I’m Cortana.

It’s thrilling to hear Jen Taylor speak through the speakers of your Windows Phone – “Hi. I’m Cortana.” The personal digital assistant in the latest update of Windows Phone, could have been some other name, but Microsoft was forced by a petition to stick to “Cortana”, a name casually given by Robert Howard as a codename. So there are so many things Cortana can do.
ImCortana
The most important thing for developers is that the natural speech recognition services of Cortana will be available to developers. They can integrate VR in their code and need not bother about complex natural language grammar. I am hoping for apps with capabilities to listen to your commands (no special training required for individual apps) and act accordingly. “Cortana, ask ‘XYZ app’ to draw a circle and fill it with red color”! “Cortana, ask Avirall to create and start a 3 hour timer”. I am still not sure when Cortana will be available globally (currently it will be available in US only), and also it’s not clear how Cortana will be opened up for third party developers. So, keep in touch!

Navigation Hierarchy

Avirall Time Suite is an extensive app with 60,000+ working LOC in .cs files. I have not calculated the lines of code in XAML because a major portion of them are auto-generated. Still, there is about same number of lines in XAML files, as well. Avirall has 15 pages and 3 of them have about 5 types, so in all about 30 pages show up in Avirall. During documentation I created a high level diagram of navigation hierarchy in the app. I think it gives a bird’s eye view of how the app’s control flow, kind of circulatory system. This is how it looks like :

MTTHNavigation