Опубликован: 01.11.2011 | Доступ: свободный | Студентов: 1424 / 63 | Оценка: 3.84 / 3.44 | Длительность: 15:38:00
Специальности: Программист
Практическая работа 12:

Обработка простого касания в Silverlight

Аннотация: Как и XNA, Silverlight поддерживает два разных программных интерфейса для работы с мультисенсорным вводом, которые можно описать как интерфейс обработки простого и сложного касания. Интерфейс обработки простого касания построен на событии Touch.FrameReported, схожем с XNA-классом TouchPanel. Целью данного занятия является разработка обработчика простого касания в Silverlight.

Дополнительные материалы к занятию можно скачать здесь.

Как и XNA, Silverlight поддерживает два разных программных интерфейса для работы с мультисенсорным вводом, которые можно категоризировать как интерфейс обработки простого и интерфейс обработки сложного касания. Интерфейс обработки простого касания построен на событии Touch.FrameReported, которое очень похоже на XNA-класс TouchPanel. Отличается оно лишь тем, что это событие, и оно не включает обработку жестов.Интерфейс обработки сложного касания включает три события, определяемые классом UIElement: ManipulationStarted (Обработка началась), ManipulationDelta (Приращение в ходе обработки) и ManipulationCompleted (Обработка завершилась). События Manipulation, как их обобщенно называют, консолидируют взаимодействие множества касаний в движение и коэффициенты масштабирования [25].

Ядром интерфейса обработки простого касания в Silverlight является класс TouchPoint (Точка касания), экземпляр которого представляет отдельное касание экрана. TouchPoint имеет четыре свойства только для чтения:

  • Action (Действие) типа TouchAction (Действие касания) - перечисление с элементами Down (Вниз), Move (Перемещение) и Up (Вверх) [25].
  • Position типа Point (Точка), значение которого определяется относительно верхнего левого угла конкретного элемента. Будем называть этот элемент опорным.
  • Size типа Size. Это свойство должно представлять область касания (и, следовательно, давление, создаваемое пальцем, в некотором роде), но эмулятор Windows Phone 7 не возвращает полезных значений [25].
  • TouchDevice типа TouchDevice. Объект TouchDevice имеет два свойства только для чтения:
    • Id типа int, используется для идентификации касаний. Каждое отдельное касание ассоциировано с уникальным Id на протяжении всех событий, начиная от Down и до Up DirectlyOver (Непосредственно над) типа UIElement - самый верхний элемент, расположенный прямо под пальцем [25].

Как видите, Silverlight-объекты TouchPoint и TouchDevice предоставляют преимущественно те же сведения, что и XNA-объект TouchLocation. Свойство DirectlyOver объекта TouchDevice часто очень полезно для определения, какого элемента пользователь касается [25].

Для использования интерфейса обработки простого касания необходимо установить обработчик статического события Touch.FrameReported:

Touch.FrameReported += OnTouchFrameReported;
    

Метод OnTouchFrameReported выглядит следующим образом:

void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
{
    …
}
    

Этот обработчик события принимает все события касания в ходе выполнения приложения. Объект TouchFrameEventArgs (Аргументы события касания рамки) имеет свойство TimeStamp (Отметка времени) типа int и три метода:

  • GetTouchPoints(refElement) (Получить точки касания) возвращает TouchPointCollection (Коллекция точек касания)
  • GetPrimaryTouchPoint(refElement) (Получить основную точку касания) возвращает один TouchPoint
  • SuspendMousePromotionUntilTouchUp() (Приостановить перемещения мыши до завершения касания.

В общем случае вызывается метод GetTouchPoints и в него передается опорный элемент. Значения свойств Position объектов TouchPoint в возвращенной коллекции определяются относительно этого элемента. Если передать null в GetTouchPoints, значения свойств Position будут установлены относительно верхнего левого угла окна просмотра приложения [25].

Между опорным элементом и элементом DirectlyOver нет никакой связи. Событие всегда обрабатывает все касания приложения в целом. Вызов GetTouchPoints или GetPrimaryTouchPoints для конкретного элемента не означает, что будут обрабатываться касания только этого элемента, это означает лишь то, что значение свойства Position будет определяться относительно этого элемента. (Поэтому координаты Position вполне могут быть отрицательными, если место касания находится слева или над опорным элементом.) Элемент DirectlyOver определяет элемент, находящийся непосредственно под пальцем [25].

Для разговора о втором и третьем методах необходимо сделать небольшое вступление. Событие Touch.FrameReported появилось в Silverlight для настольных приложений, в которых для логики обработки событий мыши существующих элементов управления удобно автоматически использовать сенсорный ввод. По этой причине события касания приравнены к событиям мыши [25].

Но это распространяется только на "первую" точку касания, т.е. на действия пальца, коснувшегося экрана первым, когда ни один другой палец его не касается. Если вы не хотите, чтобы действия этого касания трактовались как события мыши, обработчик события должен начинаться так:

void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
{
    TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);
    if (primaryTouchPoint != null && primaryTouchPoint.Action == TouchAction.Down)
    {
        args.SuspendMousePromotionUntilTouchUp();
    }
…            
}
    

Метод SuspendMousePromotionUntilTouchUp может вызываться только в момент первого касания первым пальцем, когда все остальные пальцы еще не коснулись экрана [25].

Для Windows Phone 7 такая логика представляет некоторые проблемы. Как сказано выше, по сути, происходит отключение обработки событий мыши для всего приложения. Если приложение для телефона включает элементы управления Silverlight, изначально написанные для ввода с помощью мыши и не обновленные для приема сенсорного ввода, эти элементы управления фактически будут деактивированы [25].

В предлагаемой работе мы взяли за основу пример, описанный в книге Ч. Петзольда (2010).

Создаем новый проект Silverlight Windows Phone 7. Назовем его p12.

Содержимое файла MainPage.xaml:

<phone:PhoneApplicationPage 
    x:Class="p12.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    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="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Отработка" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Нажатия" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBlock Name="txtblk" FontSize="48"
Text="Нажмите!" HorizontalAlignment="Center"
VerticalAlignment="Center" />
        </Grid>
    </Grid>
 

</phone:PhoneApplicationPage>
    
Листинг .

Введем следующий код в файл MainPage.xaml.cs:

using System;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Phone.Controls;
namespace p12
{
    public partial class MainPage : PhoneApplicationPage
    {

        public MainPage()
        {
            InitializeComponent();
            Touch.FrameReported += OnTouchFrameReported;
        }
        void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
        {
            TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);
            if (primaryTouchPoint != null && primaryTouchPoint.Action ==
            TouchAction.Down)
            {
                if (primaryTouchPoint.TouchDevice.DirectlyOver == txtblk)
                {
                    txtblk.Text = "Вы нажали!";
                }
               
            }
        }
    }
}
    

Результат после нажатия мышью на надпись.