Добавление распознавателя жестов сдвига

Жест сдвига используется для обнаружения перемещения пальцев по экрану и применения этого перемещения к содержимому и реализуется с PanGestureRecognizer помощью класса. Жест сдвига обычно используется для смещения изображения по горизонтали или вертикали, когда оно не помещается полностью в окне просмотра. Для этого изображение перемещается в пределах окна просмотра, как показано в этой статье.

Чтобы элемент пользовательского интерфейса можно было перемещать жестом сдвига, необходимо создать экземпляр PanGestureRecognizer, реализовать обработку события PanUpdated и добавить новый распознаватель жестов в коллекцию GestureRecognizers элемента пользовательского интерфейса. В следующем примере кода показан распознаватель PanGestureRecognizer, присоединенный к элементу Image:

var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => {
  // Handle the pan
};
image.GestureRecognizers.Add(panGesture);

Реализация в XAML показана в следующем примере кода:

<Image Source="MonoMonkey.jpg">
  <Image.GestureRecognizers>
    <PanGestureRecognizer PanUpdated="OnPanUpdated" />
  </Image.GestureRecognizers>
</Image>

Затем код обработчика событий OnPanUpdated добавляется в файл кода программной части:

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  // Handle the pan
}

Создание контейнера сдвига

В этом разделе представлен универсальный вспомогательный класс для произвольного сдвига. Он обычно подходит для навигации по изображениям и картам. Для выполнения преобразований в пользовательском интерфейсе в ответ на жест сдвига требуется ряд математических операций. Они используются только для сдвига в пределах границ элемента пользовательского интерфейса, заключенного в оболочку. Следующий пример кода демонстрирует класс PanContainer:

public class PanContainer : ContentView
{
  double x, y;

  public PanContainer ()
  {
    // Set PanGestureRecognizer.TouchPoints to control the
    // number of touch points needed to pan
    var panGesture = new PanGestureRecognizer ();
    panGesture.PanUpdated += OnPanUpdated;
    GestureRecognizers.Add (panGesture);
  }

  void OnPanUpdated (object sender, PanUpdatedEventArgs e)
  {
    ...
  }
}

Этот класс может служить оболочкой для элемента пользовательского интерфейса, содержимое которого сдвигается в ответ на жест. В следующем примере кода XAML показан контейнер PanContainer, содержащий элемент Image.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PanGesture"
             x:Class="PanGesture.HomePage">
    <ContentPage.Content>
        <AbsoluteLayout>
            <local:PanContainer>
                <Image Source="MonoMonkey.jpg" WidthRequest="1024" HeightRequest="768" />
            </local:PanContainer>
        </AbsoluteLayout>
    </ContentPage.Content>
</ContentPage>

В следующем примере кода показано, как элемент Image заключается в контейнер PanContainer на странице C#.

public class HomePageCS : ContentPage
{
  public HomePageCS ()
  {
    Content = new AbsoluteLayout {
      Padding = new Thickness (20),
      Children = {
        new PanContainer {
          Content = new Image {
            Source = ImageSource.FromFile ("MonoMonkey.jpg"),
            WidthRequest = 1024,
            HeightRequest = 768
          }
        }
      }
    };
  }
}

В обоих примерах свойствам WidthRequest и HeightRequest присваиваются значения ширины и высоты отображаемого изображения.

Когда для элемента Image выполняется жест сдвига, отображаемое изображение смещается. Сдвиг осуществляется с помощью метода PanContainer.OnPanUpdated, который показан в следующем примере кода.

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  switch (e.StatusType) {
  case GestureStatus.Running:
    // Translate and ensure we don't pan beyond the wrapped user interface element bounds.
    Content.TranslationX =
      Math.Max (Math.Min (0, x + e.TotalX), -Math.Abs (Content.Width - App.ScreenWidth));
    Content.TranslationY =
      Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight));
    break;

  case GestureStatus.Completed:
    // Store the translation applied during the pan
    x = Content.TranslationX;
    y = Content.TranslationY;
    break;
  }
}

Этот метод обновляет видимое содержимое заключенного в оболочку элемента пользовательского интерфейса в соответствии с жестом сдвига пользователя. Направление и расстояние сдвига рассчитываются исходя из значений свойств TotalX и TotalY экземпляра PanUpdatedEventArgs. Свойства App.ScreenWidth и App.ScreenHeight содержат высоту и ширину окна просмотра. В качестве их значений задаются высота и ширина экрана устройства в зависимости от платформы. После этого заключенный в оболочку элемент интерфейса сдвигается путем присвоения свойствам TranslationX и TranslationY вычисленных значений.

Когда содержимое сдвигается внутри элемента, который занимает не весь экран, высоту и ширину окна просмотра можно получить из свойств Height и Width элемента.

Примечание.

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