Porting the User Interface from an iOS* Basic App to Windows* 8

Introduction

Windows* 8 is a great platform for writing apps with increased productivity, easy deployment, and natural human interactions. This article shows you how to port the basic UI design of an application from iOS* to Windows 8 on devices with a variety of form-factors like tablets and Ultrabook™ devices. The content of the article will be based on a case study on a healthcare app created for clinic/hospital physicians with patient electronic medical records (EMR).

Basic UI Navigation and Layout

We use a healthcare app as a case study. The healthcare app allows physicians to view patient EMRs. Windows 8 provides designs with fluid and flexible user experiences on a variety of devices. We discuss the navigation hierarchy and the layout designs and use the case study to illustrate how to port from iOS to Microsoft* Store apps.

Navigation Hierarchy

The navigation design directly impacts users’ interactions with the app. On iOS, the storyboard is recommended for navigation design. For Microsoft Store apps, extensible application markup language (XAML) pages with navigation methods are recommended for C# developers. We discuss how to port the storyboard design to the XAML page designs.

Storyboard Design of iOS App

In our case study app, the storyboard is designed with a split-view with a master-view controller and a detail-view controller.

main page of healthcare I O S app
Figure 1. Main page of the healthcare iOS app (Note that names and SSNs shown in the figure are not real.)

To design the UI in Figure 1, the storyboard is laid out with split-views with a master-view controller and a detail-view controller. The master-view controller is connected to a navigation controller that can navigate to a table view with a list of patients. The detail view controller is connected to a navigation controller that can navigate to a detail view with static images, text boxes, and a container with static table views.

storyboard design of the main page
Figure 2. Storyboard design of the main page of the healthcare iOS app1

Hierarchy System of Microsoft* Store App

To provide a similar or better user experience on Windows 8, we port the split-view design from iOS to a hierarchy system on Windows 8 with XAML pages. We also follow the Microsoft Store app design guidelines from Microsoft.

Hierarchical System

The two kinds of navigation designs for Microsoft Store apps are: the flat system and the hierarchical system. The flat system design is best usually when the core scenarios involve rapid switching between a small number of pages and all the pages belong to the same hierarchical level. The hierarchical system applies to the scenario of the separation of content into different sections and different levels of details. The hub page will have multiple group entries and each group includes pages with items that belong to this group. For some apps, the UI design could be a mixture of the hierarchical and flat systems.

To port the iOS split-view storyboard design to Windows 8, we chose the hierarchical system as the major navigation design for the Microsoft Store app. For the pages within one group, we use the flat system to navigate between the related pages. Figure 3 is the navigation design of the healthcare app, which is a mixture of both systems. The main design is the hierarchical system, and the design for pages within a group is a flat system. Because many Microsoft Store apps are designed with large tiles due to the larger area for displaying key information, we design the pages with tiles.

navigation design healthcare app

Figure 3. Navigation design of the Microsoft* Store healthcare app

Users also have a search option from the Charm* menu to search for a particular patient. The page includes the abstract information of the patient with groups. This is the hub page for the next level of pages with detailed items in each group.

the patient entry page
Figure 4. Patient entry page of the healthcare app on Windows 8

main page of the healthcare I O S
Figure 5. screenshot of the main page of the healthcare iOS app

Basic UI Layout

For a Microsoft Store app, we need to design a layout for each page in XAML format. In iOS, components are utilized for the layout of a page. In Windows 8, templates with specific layouts are typically used.

Choose a Layout

Microsoft Store app developers have many options of layout templates to choose from for the most flexible and adaptable user interface. Flexible box layout, grid alignment, multi-column layout, and regions layout are available depending on the context and user needs of the app. For the healthcare app, we want to present the physician clear information for a specific patient with divided groups like personal profile, notes, lab results, vitals, and X-ray images. We choose the grid alignment layout as it can divide available space into columns and rows to show user information clearly. Multiple grid layout templates can be selected in Visual Studio*.

The code bellow shows the grid alignment layout template, LayoutRootStyle, used in our case study.

   <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Style="{StaticResource LayoutRootStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Horizontal scrolling grid used in most view states -->
        <GridView
            x:Name="itemGridView"
            AutomationProperties.AutomationId="ItemsGridView"
            AutomationProperties.Name="Items"
            TabIndex="1"
            Grid.RowSpan="2"
            Padding="116,136,116,46"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            ItemTemplate="{StaticResource PatientsItemStyle1}"
            SelectionMode="None"
            IsSwipeEnabled="false" IsItemClickEnabled="True" ItemClick="ClickItem"/>

        <!-- Vertical scrolling list only used when snapped -->
        <ListView
            x:Name="itemListView"
            AutomationProperties.AutomationId="ItemsListView"
            AutomationProperties.Name="Items"
            TabIndex="1"
            Grid.Row="2"
            Visibility="Collapsed"
            Margin="0,-10,0,0"
            Padding="10,0,0,60"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            ItemTemplate="{StaticResource Standard80ItemTemplate}"
            SelectionMode="None"
            IsSwipeEnabled="false" IsItemClickEnabled="True" ItemClick="ClickItem"/>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="pageTitle" Grid.Column="1" Text="Patients" IsHitTestVisible="false" Style="{StaticResource PageHeaderTextStyle}"/>            
        </Grid>
        <StackPanel Margin="10" Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right">
            <TextBlock Grid.Row="1" Text="LoginUser:"/>
            <TextBlock x:Name="loginUser" Grid.Row="1" Text="" Margin="5,0"/>

        </StackPanel>
</Grid>

Provide Adaptive Layouts

As users rotate their devices, Windows* provides adaptive layouts for orientations and views. Figure 5 shows screenshots of a layout in different orientations and views.

layout of the healthcare I O S app
layout of the healthcare I O S app
Figure 6. Screenshots of layouts for the healthcare iOS app

The following code is the XAML code of a page with different layouts in our case study. This is auto-generated code when you choose a template page to start with in Visual Studio.

<VisualStateManager.VisualStateGroups>
    <!-- Visual states reflect the application's view state -->
        <VisualStateGroup x:Name="ApplicationViewStates">
                <VisualState x:Name="FullScreenLandscape"/>
                <VisualState x:Name="Filled"/>

                <!-- The entire page respects the narrower 100-pixel 
                   margin convention for portrait -->
                <VisualState x:Name="FullScreenPortrait">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames 
                         Storyboard.TargetName="backButton" 
                         Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                    Value="{StaticResource PortraitBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="itemGridView" 
                        Storyboard.TargetProperty="Padding">
                            <DiscreteObjectKeyFrame KeyTime="0"                       
                     Value="96,136,86,56"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>

                <!--
                    The back button and title have different styles 
              when snapped, and the list representation is substituted
                    for the grid displayed in all other view states
                -->
                <VisualState x:Name="Snapped">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="backButton" 
                        Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0"  
                    Value="{StaticResource SnappedBackButtonStyle}"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="pageTitle"               
                        Storyboard.TargetProperty="Style">
                            <DiscreteObjectKeyFrame KeyTime="0" 
               Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                        </ObjectAnimationUsingKeyFrames>

                        <ObjectAnimationUsingKeyFrames                
                         Storyboard.TargetName="itemListView" 
                         Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" 
                          Value="Visible"/>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames 
                          Storyboard.TargetName="itemGridView" 
                          Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" 
                             Value="Collapsed"/>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

Basic Component/Layout Design of a View/Page

In this section, we discuss how to port the basic component/layout of a page from iOS to Windows 8. On iOS, we design a page with components chosen from an object library. For Microsoft Store apps, we have XAML format descriptions and templates for basic component/layout designs.

Button Design

Buttons are described in an XAML page with a format. The code snippet below shows an example of a button design. The click is associated with a function named GoBack, which is already defined in LayoutAwarePage class. Whenever the button is clicked, the GoBack function in the class is executed. The style of the button follows the template as BackButtonStyle.

<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}"
Style="{StaticResource BackButtonStyle}"/>

Text Box

Text boxes are described in an XAML2 page with a format. The following code snippet shows an example of a text box design. It includes multiple properties with specific values. The style of the text box also follows a template as PageHeaderTextStyle.

<TextBlock x:Name="pageTitle" 
    Grid.Column="1"
    Text="Patient Medical Record"
    IsHitTestVisible="false"
    Style="{StaticResource PageHeaderTextStyle}"   
    Grid.ColumnSpan="2"/>

Grid View

Grid views describe the layout of an XAML page with grids. The following code is an example of a grid view in landscape layout. The data source is bound to the specified static resource patientgroupedItemsViewSourceList. Please refer to this section The source list is defined in C# code for the page. The item grid template uses the Stand250x250ItemTemplate. Also, in the C# file for the page, we need to define the function ItemView_ItemClick so users can click on items in the grid.

 <!—Horizontal scrolling grid used in most view states -->
 <GridView
      x:Name="itemGridView"
      AutomationProperties.AutomationId="ItemGridView"
      AutomationProperties.Name="Grouped Items"
      Grid.Row="1"
      Margin="0,-3,0,0"
      Padding="116,0,40,46"
      ItemsSource="{Binding Source=
      {StaticResource patientgroupedItemsViewSourceList}}"
      ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
      SelectionMode="None"
      IsItemClickEnabled="True"
      ItemClick="ItemView_ItemClick"              
      >

      <GridView.ItemsPanel>
          <ItemsPanelTemplate>                        
             <VirtualizingStackPanel  Orientation="Horizontal"/>
          </ItemsPanelTemplate>
      </GridView.ItemsPanel>
      <GridView.GroupStyle>
          <GroupStyle>
             <GroupStyle.HeaderTemplate>
                 <DataTemplate>
                    <Grid Margin="1,0,0,6">
                       <Button
                        AutomationProperties.Name="Group Title"
                       Content="{Binding Title}"
                       Click="Header_Click"
                       Style="{StaticResource TextButtonStyle}"/>
                    </Grid>
                  </DataTemplate>
             </GroupStyle.HeaderTemplate>
             <GroupStyle.Panel>
                <ItemsPanelTemplate>
      <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
                </ItemsPanelTemplate>
             </GroupStyle.Panel>
         </GroupStyle>
      </GridView.GroupStyle>
     </GridView>

Group Grid View

When we have multiple grids to be organized into different groups, we can group them into different categories.

XAML Page

First, we need to specify the data source to bind for the grid view for groups in XAML file. The code bellow shows the binding of the data source in our case study. Here patientgroupedItemsViewSourceList is the group source for the grid view.

    <Page.Resources>

        <!--
            Collection of grouped items displayed by this page, bound  
            to a subset of the complete item list because items in 
            groups cannot be virtualized
        -->

       <CollectionViewSource
            x:Name="patientgroupedItemsViewSource"
            Source="{Binding MedicalRecordGroups}"
            IsSourceGrouped="true"
           />    

        <CollectionViewSource   
            x:Name="patientgroupedItemsViewSourceList" 
            IsSourceGrouped="True" 
            ItemsPath="MedicalRecordItems"/>

    </Page.Resources>

Use Grouped Data Source

Next we need to use the grouped data source for the grid view. The following code provides an example on how to provide the grouped data source. The function should be called when the page is loaded.

private void PopulateGroups(PatientsViewModel patient)
{
        List<MedicalRecordCategory> MedicalRecordCategories = new 
                          List<MedicalRecordCategory>();
            int count = 0;

            MedicalRecordCategory newMedicalRecordCategory = new 
                                  MedicalRecordCategory();
            newMedicalRecordCategory.Title = "Patient Profile";
            newMedicalRecordCategory.MedicalRecordItems.Add(new 
                MedicalRecordItem() {
                Title = "Patient Information",
                Complete = true,
                Subtitle = patient.Firstname + " " + patient.Lastname,
                Image = patient.Image,
                MedicalRecordCategoryId = 1,
                MedicalRecordItemId = 1
            });
            newMedicalRecordCategory.MedicalRecordItems.Add(new 
                MedicalRecordItem() {
                Title = "Family History ",
                Complete = true,
                Subtitle = patient.Insurance,
                Image = "Assets/history.jpg",
                MedicalRecordCategoryId = 1,
                MedicalRecordItemId = 2

            });
            newMedicalRecordCategory.MedicalRecordItems.Add(new  
                MedicalRecordItem() { 
                Title = "Billing ", Complete = false, Subtitle = 
                patient.Lastvisit,
                Image = "Assets/billing.jpg",
                MedicalRecordCategoryId = 1,
                MedicalRecordItemId = 3
            });
            MedicalRecordCategories.Add(newMedicalRecordCategory);

            if (patient_note_count == 0)
            {
                newMedicalRecordCategory = new MedicalRecordCategory();
                newMedicalRecordCategory.Title = "Notes";
                newMedicalRecordCategory.MedicalRecordItems.Add(new 
                MedicalRecordItem()
                {
                    Title = "No notes",
                    Complete = true,
                    Subtitle = "",
                    Image = "Assets/notes.jpg",
                    MedicalRecordCategoryId = 2,
                    MedicalRecordItemId = 0
                });
                MedicalRecordCategories.Add(newMedicalRecordCategory);
            }
            else 
            {
                newMedicalRecordCategory = new MedicalRecordCategory();
                newMedicalRecordCategory.Title = "Notes";
                for (count = 0; count < patient_note_count; count++)                               
                {

                newMedicalRecordCategory.MedicalRecordItems.Add(new 
                MedicalRecordItem()
                {
                    Title = 
                    PatientNotesArray[count].creatorid.ToString(),
                    Complete = true,
                    Subtitle = PatientNotesArray[count].note,
                    Image = "Assets/notes.jpg",
                    MedicalRecordCategoryId = 2,
                    MedicalRecordItemId = count+1
                });
                }                
                MedicalRecordCategories.Add(newMedicalRecordCategory);
            }……
            // Add source to the grid view groups
            patientgroupedItemsViewSourceList.Source = 
            MedicalRecordCategories;
        }

}

    public class MedicalRecordCategory
    {
        public MedicalRecordCategory()
        {
            MedicalRecordItems = new 
            ObservableCollection<MedicalRecordItem>();
        }
        public string Title { get; set; }
        public ObservableCollection<MedicalRecordItem> 
                MedicalRecordItems { get; private set; }      
    }

    public class MedicalRecordItem
    {
        public int MedicalRecordCategoryId { get; set; }
        public int MedicalRecordItemId { get; set; }
        public string Title { get; set; }
        public string Subtitle { get; set; }
        public string Image { get; set; }
        public bool Complete { get; set; }
        public string MedicalRecordCategory { get; set; }
    }

The main hub page for a patient becomes a page with several categories. Each category includes multiple items if they exist.See figure 5.

Main Entry Point Design

For iOS apps, a logo is the main entry point of an app. Microsoft Store apps have two options: either a logo or a tile window with key messages to users.

Logo

The logo design is similar to iOS apps. Microsoft Store apps have a manifest file for defining some properties of the app including the logo specification. A developer only needs to specify the logo images for the general logo, wide logo, and small logo with different required sizes. Figure 6 is the screenshot of the manifest values for logo entries.

manifest file for logo specifications
Figure 7. screenshot of manifest file for logo specification

We have specified the wide logo as shown in Figure 8.

logo of the healthcare app
Figure 8. Logo of the healthcare app

Tile

A unique UI feature of Microsoft Store apps is a tile with key messages for users as the main entry. Here, we discuss how to develop a tile for the healthcare app. We want to design the tile as shown in Figure 9. When not in use, the logo appears as shown in the left image. After a user logs in, the logo changes to show the users’ name and the number of appointments for the day. After a time interval, the tile switches to a peek message window with more detailed information. This new Windows UI gives users a way to quickly check key information.

tile design of healthcare app
Figure 9. Tile design of the healthcare app

The UpdateTileWithImageText should be called in the page after the user is logged in. The function utilizes a template for the tile design. This template comes from the NotificationsExtensions library. Please refer to the website on how to use this library for different styles of tiles.

void UpdateTileWithImageText(int numofpatients)
      {
            // Note: This sample contains an additional project, 
             NotificationsExtensions.
            // NotificationsExtensions exposes an object model for 
            creating notifications, but you can also modify the xml
            // of the notification directly using 
             TileUpdateManager.GetTemplateContent(TileTemplateType)

            // Create notification content based on a visual template.
            ITileWidePeekImageAndText02 tileContent = 
            TileContentFactory.CreateTileWidePeekImageAndText02();

            tileContent.TextBody1.Text = loginUser.Text;
            tileContent.TextBody2.Text = "     5 appointments today";
            tileContent.TextBody3.Text = "    " + 
                 numofpatients.ToString() + " patients in records";
            tileContent.TextBody4.Text = "    " + "20 new patients";
            tileContent.TextBody5.Text = "    " + 
                                   DateTime.Today.ToString();
            //tileContent.TextCaption2.Text =  " more patients";
            tileContent.Image.Src = "images/LogoBlueWide.png";
            tileContent.Image.Alt = "Logo image";

            // Users can resize tiles to square or wide.
            // Apps can choose to include only square assets (meaning 
            //   the app's tile can never be wide), or
            // include both wide and square assets (the user can resize 
            //   the tile to square or wide).
            // Apps should not include only wide assets.

            // Apps that support being wide should include square tile 
            //    notifications since users
            // determine the size of the tile.

            // create the square template and attach it to the wide 
            // template
            ITileSquareImage squareContent = 
            TileContentFactory.CreateTileSquareImage();
            squareContent.Image.Src = "images/graySquare.png";
            squareContent.Image.Alt = "Gray image";
            tileContent.SquareContent = squareContent;

            // Send the notification to the app's application tile.
            TileUpdateManager.CreateTileUpdaterForApplication()
                    .Update(tileContent.CreateNotification());

        }

        private void ClearTile()
        { 
           TileUpdateManager.CreateTileUpdaterForApplication().Clear();
        }

Conclusion

In the article we discuss how to port the basic UI design from an iOS app to a Microsoft Store app. We study a healthcare app and discuss some implementation experiences on the navigation and layout design, basic UI component design, and main entry point design. We expect our case study can give developers a quick start on porting apps from iOS to Windows 8.

About the Author

Sushu Zhang Sushu Zhang is a software engineer in Intel's Software and Services Group. She is working on ISV scale enabling for Intel-based platforms with Android* / Windows* OS. Most recently, Sushu has been involved with several energy-efficiency projects at Intel. Prior to joining Intel, Sushu worked at Microsoft on Windows energy efficiency. Sushu earned a PhD in Computer Science at the Arizona State University. Her research area was system-level power and thermal management.

Intel, the Intel logo, and Ultrabook are trademarks of Intel Corporation in the U.S. and other countries.

*Other names and brands may be claimed as the property of others

1. This sample figure is released under the Intel OBL Sample Source Code License (MS-LPL Compatible) and Xcode* License (PDF). Copyright© 2012 Intel Corporation. All rights reserved.

2. This sample source code is released under the Intel® OBL Sample Source Code License (MS-LPL Compatible) , Microsoft Limited Public License and Visual Studio 2012 License. Copyright© 2012 Intel Corporation. All rights reserved.

Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.