How to improve graphical UI of simple UbiqMobile application

In two previous posts related to UbiqMobile applications development we showed how to create a simple UbiqMobile application. We developed a single-screen app with a numeric counter in the center and two buttons below – for increasing and decreasing the counter. Now it’s time to make our application more nice-looking and show how one can build graphical user interfaces in UbiqMobile applications.

Our goal is to make our increase-decrease example looking as follows:

1

First of all, we have to figure out the structure of our control tree. Our UI will be based on vertical stack panel with a background set to “cheese-like” image; the counter will be placed in the center of the upper half of the panel. For representing counter, we use overlay panel containing two overlapping controls: a circle (ellipse inscribed in the square) with thick border and solid color background, and a text label containing counter itself.

The lower half of vertical stack panel contains horizontal stack panel divided into two sections where increase and decrease buttons are placed, each button with its specific alignment. There are basically two ways of representing custom buttons: either through ImageButton control, or using Selectable container wrapping appropriate internal control. In this example we use the second way.

Like in previous example, we use Standalone App Template for building “skeleton” of our application. For building graphical UI, we need to include cheese-looking background image (file Cheese.png) into the application C# project as a resource. For his purpose, just copy Cheese.png file into the project folder and include it into the project through Add->Existing Item item of project context menu. It is important to set Build Action property value to Embedded Resource – otherwise your image will be unavailable from UbiqMobile applications.

2

Now we can start to build our UI. Invoke Visual UI designer by double-click on UbiqDesign.ubiqml file that is containing in Standalone App template. By default, this UI file contains the only control – empty stack panel.

First of all, we have to set Cheese.png image as a background for the stack panel. Click on panel to select it, then choose “Background” on the properties pane. After pressing “…” button, brush selection window appears. Choose Image brush tab:

3

In Images pane, list of all images available as embedded resources, is displayed. In our case, it contains just one element – our Cheese.png image. Choose this image and set Mode property to Scale. Then press OK button.

We can see changes in UI designer window:

4

After setting a background, let’s mark up space for counter and two buttons. Counter will be placed in the center of the upper half of main stack panel, while two buttons – in the horizontal stack panel occupying lower half. To reserve space for counter, drag Cell element from the toolbox onto main vertical stack panel. Then drag Stack Panel horizontal element from the toolbox onto a lower part of main vertical stack panel.

For better look, the lower half should be a little bit smaller than the upper half. In Properties pane, set Height property value to 0.4 * ScreenHeight.

Our manipulations result in the following layout:

5

Now it’s time to insert a counter. Drag OverlayPanel element from the toolbox onto the cell that occupies upper half of the stack panel (cell acts as placeholder here); then drag Ellipse element onto the overlay panel. Set fixed dimensions for the ellipse in relative units (Breadth) – both width and height should be equal to 8*Large (See description of relative units and Breadth type in Graphics interface document). Set both horizontal and vertical alignment for the ellipse to Center. Set StrokeThickness property to 5 and Foreground – to white color.

Background of the ellipse should be set to a solid color #FF80A2A5. It can be done through the same brush selection window that we used for setting image background. But in this case, you should choose Solid Color pane, then enter hexadecimal ARGB color value in the appropriate field and press OK:

6

OK, our circle is ready. Let’s insert counter itself into the circle. Drag TextLabel onto overlay panel, set its name to Counter, Text property – to “0”, Font Size – to 3.5 * Large, Foreground – to white color. WrapContent flag should be set to true and both alignment properties (horizontal and vertical) – to Center.

Now our UI looks like follows:

7

The next step is to add two buttons – for increasing and decreasing counter. We’ll place buttons in horizontal stack panel inside lower half of main stack panel. For achieving effect of irregular layout of buttons, we’ll use alignment properties and margins.

Each button will be represented as overlay panel containing two children – circle and text label – just like it was done with counter. However, unlike counter, overlay panel should be wrapped in Selectable element – to make our “button” clickable. And, to be able to locate them in proper place, we need to set sizing type for overlay panels and selectables as WrapContent, and additionally wrap each Selectable element into Cell container that has FillParent sizing type.

Let’s start to build this structure. Drag Cell element from the toolbox and drop it on the left half of horizontal stack panel. Drag another Cell and drop it onto the right half of the stack panel. As a result, the horizontal stack panel will be divided into two equal areas:

8

Drag Overlay Panel from the toolbox and drop it onto left cell. Do the same thing for the right cell. After that drag Circle elements from the toolbox both to the left and right cells. For both circles, set StrokeThickness property to 4, Height and Width –  to 4 * Large, and Stroke – to white color. Then for the left circle, set Background property to #FFE88B0B, and for the right circle – to #FFD84425.

Now we need to adjust layout of our circles. Set both HorizontalSizeComputing and VerticalSizeComputing properties of both overlay panels to WrapContent. Do the same thing for both selectable elements. For left selectable, set its Margin property to (1*Large, 1*Large, 0 0). The default alignment attributes (top-left) are just what we need.

For right selectable, set HorizontalAlignment property to Right, VerticalAlignment – to Bottom, and Margin – to (0, 0, 1*Large, 1*Large).

Finally, both circles are placed properly:

9

The last step in building out UI is adding text to two buttons. Drag TextLabel element from the toolbox and drop it onto left overlay panel. Set both HorizontalAlignment  and VerticalAlignment properties to Center, and Text property “+1”. Change Name property to “btnPlus”.

Do similar things for the right button, but Text property value should be “-1”, and Name – “btnMinus”.

10

That’s almost all! Now we need to make minor changes in the automatically generated C# source code.

When building the project, UbiqMobile SDK autonatically generates two source files:  CounterUI.cs and UserSection.cs. The first file contains standard initialization code and descriptions of program interfaces. It cam be re-generated by SDK at any moment and so must not be modified by the programmer. The UserSection.cs file is specially purposed for including of user-defined code, so we’ll modify this file.

First of all, let’s include definitions of integer variable for the counter, text block for displaying counter on the screen and two buttons for increasing and decreasing counter:

        private int _counter;
        TextBlock counterText;
        SelectableArea plusButton;
        SelectableArea minusButton;

Then we need to initialize our counter with zero value and load UI controls (including Screen as a whole) from .ubiqml resources:

        
            _counter = 0;
	    Screen.Content = _ubiqDesign;
            counterText = _ubiqDesign.GetChildByName("tbNumber") as TextBlock;
            minusButton = _ubiqDesign.GetChildByName("btMinus") as SelectableArea;
            plusButton = _ubiqDesign.GetChildByName("btPlus") as SelectableArea;

The next step – defining two methods for handling buttobs events and add them for two buttons:


void plusButton_Clicked(SelectableArea sender, EventArgs e)
        {
            _counter++;
            counterText.Text = _counter.ToString();
        }
void minusButton_Clicked(SelectableArea sender, EventArgs e)
        {
            _counter--;
            counterText.Text = _counter.ToString();
        }
        .
        .
        .
  minusButton.Clicked += minusButton_Clicked;
  plusButton.Clicked += plusButton_Clicked;

Finally, we have the following code in UserSection.cs file:

//-----------------------------User-section----------------------------------------------------
//  
//
//      This is partial class that can be invoked from main entry point
//      This class is purposed for user-defined bussines logic of the application
//      The user should add proprietary code.
//      All modifications will be preserved during all automatic re-generations of the project
//  
//----------------------------------------------------------------------------------------------


using System;
using Ubiq.Graphics;
using System.Threading.Tasks;

namespace CounterUI
{
    partial class CounterUI
    {
        private int _counter;

        TextBlock counterText;
        SelectableArea plusButton;
        SelectableArea minusButton;

        //User section for bussines logic
	    //Your code should be inserted here
        protected async Task UserSection()
        {
            _counter = 0;

			Screen.Content = _ubiqDesign;
            counterText = _ubiqDesign.GetChildByName("tbNumber") as TextBlock;
            minusButton = _ubiqDesign.GetChildByName("btMinus") as SelectableArea;
            plusButton = _ubiqDesign.GetChildByName("btPlus") as SelectableArea;

            minusButton.Clicked += minusButton_Clicked;
            plusButton.Clicked += plusButton_Clicked;

            for (; ; )
            {
                await Wait();
            }
        }

        void plusButton_Clicked(SelectableArea sender, EventArgs e)
        {
            _counter++;
            counterText.Text = _counter.ToString();
        }

        void minusButton_Clicked(SelectableArea sender, EventArgs e)
        {
            _counter--;
            counterText.Text = _counter.ToString();
        }
	}
}

The example is available at https://github.com/UbiqMobile/Samples/tree/master/Counter/CounterUI