Ввод информации в приложениях Windows Phone 7

Активные пользователи мобильных устройств очень хорошо знают, что одной из главных проблем при использовании устройства является ввод информации. Для ввода информации используется реальная или виртуальная клавиатуры. Более того, зачастую используется именно привычная QWERTY-раскладка клавиатуры. Проблема заключается в размерах.

Физические размеры устройств достаточно малы и разместить на экране таких аппаратов несколько десятков кнопок достаточно сложно, если оставлять кнопки большого размера. Поэтому зачастую кнопки остаются небольшими и ввод информации не такой удобный, как на настольных компьютерах или ноутбуках. С аппаратной выдвижной клавиатурой работать более удобно, но упомянутая выше проблема сохраняется – размеры кнопок невелики. Поэтому ввод информации при использовании мобильных устройств – одна из наиболее сложных проблем в удобстве пользования этих устройств.

Однако, недостаток в виде небольших размеров одновременно является и преимуществом данного вида устройств. Именно благодаря небольшим размерам мы имеем возможность использовать эти устройства в тех случаях, когда использование, например, ноутбука невозможно. Например, бывает очень сложно достать ноутбук и просмотреть содержимое своего электронного ящика, когда гуляешь по супермаркету, однако, это вполне реально сделать при использовании мобильного устройства. Именно поэтому эта проблема будет жить еще долго в мобильных устройствах и разработчики вряд ли что-то с этим смогут поделать. На самом деле, кое-что разработчики все-таки могут сделать. А именно, сделать работу с виртуальной клавиатурой более удобной.

Каким образом мы, как разработчики мобильных приложений можем упростить жизнь пользователям? Некоторое время назад я писал о контекстно-зависимых приложениях. На самом деле тот же самый контекстно-зависимый подход мы можем использовать при вводе информации пользователем в мобильное устройство. Необходимо только понять, на какие условия необходимо реагировать.

Если рассмотреть наиболее типичные для пользователя сценарии, то можно понять, что в большинстве случаев они повторяются. Так, например, клавиатура обычно используется для ввода номера телефона, имени контакта, ввода текстовой информации (например, сообщения электронной почты или SMS), ввода адреса электронной почты, адреса веб-ресурса и т.д. Сейчас не так важно понять все сценарии, сколько важно понять, что они есть и они действительно зачастую повторяются. При этом в каждом конкретном случае от клавиатуры необходима разная функциональность. Например, при вводе адреса электронной почты нам наверняка потребуются знаки @ и точка, а при вводе телефонного номера скорее всего нужны будут только цифры. Все эти варианты специфичны для каждого случая.

Мы плавно подошли к тому, что приложение способно помочь пользователю с вводом информации, адаптируя вид виртуальной клавиатуры в соответствии с его потребностями. Основная проблема в том, как определить что пользователь собирается вводить в данный момент. Если попробовать решить эту задачу в общем, то операционная система может только в ряде случае с трудом догадаться какую именно информацию собирается вводить пользователь. Поэтому, если бы проблема решалась именно таким образом, то вряд ли бы можно было рассчитывать на что-то эффективное.

Давайте посмотрим на это с другой стороны. Каждый разработчик при разработке своего приложения с большой вероятностью может знать для чего предназначено то или иное поле. Другими словами, когда разработчик размещает на форме очередное поле ввода, он, скорее всего, точно представляет для чего оно нужно и какая информация там будет. Поэтому наиболее правильным способом является дать разработчику приложения возможность определить поведение виртуальной клавиатуры для каждого элемента управления. Такой подход, одной стороны не сильно затруднит разработчика, а другой – сильно упростит жизнь обычному пользователю. Именно такой подход используется в Windows Phone 7 для ввода информации. Для этих целей для элементов управления WIndows Phone 7 существует свойство InputScope. Давайте посмотрим как оно работает.

Для начала создадим пустое Windows Phone 7 приложение на основе Silverlight и добавим на форму поле ввода (TextBox).

<phoneNavigation:PhoneApplicationPage 
    x:Class="InputScope.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" 
                       Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="page title" x:Name="textBlockListTitle" 
                       Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>

        <!--ContentGrid is empty. Place new content here-->
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <TextBox Height="31" HorizontalAlignment="Left"
                     Margin="6,29,0,0" Name="textBox1" Text="TextBox" 
                     VerticalAlignment="Top" Width="446" />
        </Grid>
    </Grid>
    
</phoneNavigation:PhoneApplicationPage>

Как видно, это совершенно обычное приложение. При запуске этого приложения и переключения фокуса на поле ввода мы увидим стандартную виртуальную клавиатуру Windows Phone 7.

Давайте теперь поработаем с полем ввода и определим, что это поле предназначено для ввода телефонного номера. Для этого определим свойство InpuScope для поля ввода, указав ему значение TelephoneNumber. Свойство InputScope принимает значения из перечисления InputScopeNameValue. Значение TelephoneNumber как раз является одним из значений перечисления InputScopeNameValue.

<phoneNavigation:PhoneApplicationPage 
    x:Class="InputScope.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" 
                       Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="page title" x:Name="textBlockListTitle" 
                       Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>

        <!--ContentGrid is empty. Place new content here-->
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <TextBox Height="31" HorizontalAlignment="Left"
                     Margin="6,29,0,0" Name="textBox1" Text="TextBox" 
                     VerticalAlignment="Top" Width="446" >
                <TextBox.InputScope>
                    <InputScope Names="TelephoneNumber" />
                </TextBox.InputScope>
            </TextBox>
        </Grid>
    </Grid>
    
</phoneNavigation:PhoneApplicationPage>

При запуске приложения и установке фокуса на поле ввода мы также увидим виртуальную клавиатуру, но в этот раз она примет несколько иной вид.

Как видно, добавлением одной строчки кода в разметке мы добились того, что виртуальная клавиатура существенно изменила свой внешний вид и функциональность. На самом деле перечисление InputScopeNameValue имеет несколько десятков всевозможных значений, которые изменяют функциональность виртуальной клавиатуры.

Для того, чтобы увидеть каждый случай можно, конечно, изменять это значение и перезапускать приложение; однако, мы воспользуемся другим способом. Для начала с помощью Reflection получим всевозможные значения этого перечисления. После этого для каждого значения перечисления создадим новое поле ввода и определим для него соответствующее значение свойства InputScope. Разметка формы при этом изменится следующим образом.

<phoneNavigation:PhoneApplicationPage 
    x:Class="InputScope.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitleGrid is the name of the application and page title-->
        <Grid x:Name="TitleGrid" Grid.Row="0">
            <TextBlock Text="MY APPLICATION" x:Name="textBlockPageTitle" 
                       Style="{StaticResource PhoneTextPageTitle1Style}"/>
            <TextBlock Text="page title" x:Name="textBlockListTitle" 
                       Style="{StaticResource PhoneTextPageTitle2Style}"/>
        </Grid>

        <!--ContentGrid is empty. Place new content here-->
        <Grid x:Name="ContentGrid" Grid.Row="1">
            <ScrollViewer BorderThickness="0" Height="280" VerticalAlignment="Top">
                <StackPanel x:Name="Elements">
                    <StackPanel.Resources>
                        <Style TargetType="TextBox">
                            <Setter Property="Margin" Value="10"/>
                        </Style>
                    </StackPanel.Resources>
                </StackPanel>
            </ScrollViewer>
        </Grid>
    </Grid>
    
</phoneNavigation:PhoneApplicationPage>

При этом в момент создания и загрузки формы создадим следующий код. Здесь мы получаем все значения перечисления и для каждого значения создадим новое поле ввода и помещаем его на форму. При этом для каждого поля ввода задается текущее значение InputScope.

foreach (var inputName in typeof(InputScopeNameValue).
  GetFields(BindingFlags.Public | BindingFlags.Static).Select(t => t.Name))
{
    InputScopeNameValue val = (InputScopeNameValue)(Enum.Parse(typeof(InputScopeNameValue), inputName, true));

    if (val > 0)
    {
        Elements.Children.Add(new TextBox()
        {
            Text = inputName,
            InputScope = new System.Windows.Input.InputScope
            {
                Names = 
            { 
                new InputScopeName()
                    {
                        NameValue = val
                    }
            }
            }
        });
    }
}

При запуске приложения на форме будет созданы элементы управления. При установлении фокуса на каждое поле можно увидеть различные варианты виртуальной клавиатуры.

Наиболее интересные варианты виртуальной клавиатуры:

Url: адаптировано для ввода адреса интернет ресурса, характерно, что в нижней части есть кнопка для ввода домена (при нажатии и удержании можно увидеть другие домены) и кнопка перехода к ресурсу (справа снизу).

EmailSmtpAddress: адаптировано для ввода адреса электронной почты, характерно, что в нижней части вынесен символ @ и точка, а также есть отдельная кнопка для ввода домена.

PersonalFullName: адаптировано для ввода имени.

PostalCode: адаптировано для ввода кода города, характерно, что по умолчанию используется раскладка для цифр и знаков, но можно переключить в режим ввода букв. Аналогичная раскладка используется и для других способов ввода, использующих цифры.

TelephoneNumber: адаптировано для ввода номера телефона.

Text: адаптировано для ввода текста, характерно, что есть отдельная кнопка для ввода смайлов (которые зачастую используется в теле электронного письма или SMS).

Chat: адаптировано для использования в чатах, аналогично предыдущему способу, но здесь используются графические смайлы.

Кроме этих режимов, перечисление InputScopeNameValue содержит еще огромное количество значений. На данный момент для некоторых значений вид виртуальной клавиатуры совпадает. Как это будет выглядеть в финальной версии пока не понятно, но большое количество различных значений вызывает надежду на то, что различных режимов виртуальной клавиатуры будет еще больше.