손가락 모으기 제스처 인식기 추가Adding a pinch gesture recognizer

샘플 다운로드 샘플 다운로드Download Sample Download the sample

손가락 모으기 제스처는 대화형 확대/축소 작업을 수행하는 데 사용되며 PinchGestureRecognizer 클래스로 구현됩니다. 손가락 모으기 제스처에 대한 일반적인 시나리오는 손가락 모으기 위치에서 이미지의 대화형 확대/축소를 수행하는 것입니다. 이는 뷰포트의 콘텐츠를 크기 조정하여 수행되며, 이 문서에서 설명됩니다.The pinch gesture is used for performing interactive zoom and is implemented with the PinchGestureRecognizer class. A common scenario for the pinch gesture is to perform interactive zoom of an image at the pinch location. This is accomplished by scaling the content of the viewport, and is demonstrated in this article.

손가락 모으기 제스처를 사용하여 사용자 인터페이스 요소를 확대/축소 가능하도록 만들려면 PinchGestureRecognizer 인스턴스를 만들고, PinchUpdated 이벤트를 처리하고, 사용자 인터페이스 요소의 GestureRecognizers 컬렉션에 새 제스처 인식기를 추가합니다.To make a user interface element zoomable with the pinch gesture, create a PinchGestureRecognizer instance, handle the PinchUpdated event, and add the new gesture recognizer to the GestureRecognizers collection on the user interface element. 다음 코드 예제에서는 Image 요소에 연결된 PinchGestureRecognizer를 보여줍니다.The following code example shows a PinchGestureRecognizer attached to an Image element:

var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += (s, e) => {
  // Handle the pinch
};
image.GestureRecognizers.Add(pinchGesture);

이 작업은 다음 코드 예제에 표시된 대로 XAML에서 수행할 수도 있습니다.This can also be achieved in XAML, as shown in the following code example:

<Image Source="waterfront.jpg">
  <Image.GestureRecognizers>
    <PinchGestureRecognizer PinchUpdated="OnPinchUpdated" />
  </Image.GestureRecognizers>
</Image>

OnPinchUpdated 이벤트 처리기의 코드가 코드 숨김 파일에 추가됩니다.The code for the OnPinchUpdated event handler is then added to the code-behind file:

void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
  // Handle the pinch
}

PinchToZoom 컨테이너 만들기Creating a PinchToZoom container

확대/축소 작업을 수행하기 위해 손가락 모으기 제스처를 처리하려면 사용자 인터페이스를 변환하는 일부 수학이 필요합니다.Handling the pinch gesture to perform a zoom operation requires some math to transform the user interface. 이 섹션에서는 모든 사용자 인터페이스 요소를 대화형으로 확대/축소하는 데 사용할 수 있는 수학을 수행하는 일반화된 도우미 클래스를 포함합니다.This section contains a generalized helper class to perform the math, which can be used to interactively zoom any user interface element. 다음 코드 예제는 PinchToZoomContainer 클래스를 보여줍니다.The following code example shows the PinchToZoomContainer class:

public class PinchToZoomContainer : ContentView
{
  ...

  public PinchToZoomContainer ()
  {
    var pinchGesture = new PinchGestureRecognizer ();
    pinchGesture.PinchUpdated += OnPinchUpdated;
    GestureRecognizers.Add (pinchGesture);
  }

  void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
  {
    ...
  }
}

손가락 모으기 제스처가 래핑된 사용자 인터페이스 요소를 확대/축소할 수 있도록 사용자 인터페이스 요소에서 이 클래스를 래핑할 수 있습니다.This class can be wrapped around a user interface element so that the pinch gesture will zoom the wrapped user interface element. 다음 XAML 코드 예제에서는 Image 요소 PinchToZoomContainer 래핑을 보여줍니다.The following XAML code example shows the PinchToZoomContainer wrapping an Image element:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PinchGesture;assembly=PinchGesture"
             x:Class="PinchGesture.HomePage">
    <ContentPage.Content>
        <Grid Padding="20">
            <local:PinchToZoomContainer>
                <local:PinchToZoomContainer.Content>
                    <Image Source="waterfront.jpg" />
                </local:PinchToZoomContainer.Content>
            </local:PinchToZoomContainer>
        </Grid>
    </ContentPage.Content>
</ContentPage>

다음 코드 예제에서는 PinchToZoomContainer가 C# 페이지에서 Image 요소를 래핑하는 방법을 보여줍니다.The following code example shows how the PinchToZoomContainer wraps an Image element in a C# page:

public class HomePageCS : ContentPage
{
  public HomePageCS ()
  {
    Content = new Grid {
      Padding = new Thickness (20),
      Children = {
        new PinchToZoomContainer {
          Content = new Image { Source = ImageSource.FromFile ("waterfront.jpg") }
        }
      }
    };
  }
}

Image 요소가 손가락 모으기 제스처를 수신하는 경우 표시된 이미지가 확대 또는 축소됩니다. 확대/축소는 PinchZoomContainer.OnPinchUpdated 메서드로 수행됩니다. 이는 다음 코드 예제에 나와 있습니다.When the Image element receives a pinch gesture, the displayed image will be zoomed-in or out. The zoom is performed by the PinchZoomContainer.OnPinchUpdated method, which is shown in the following code example:

void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
  if (e.Status == GestureStatus.Started) {
    // Store the current scale factor applied to the wrapped user interface element,
    // and zero the components for the center point of the translate transform.
    startScale = Content.Scale;
    Content.AnchorX = 0;
    Content.AnchorY = 0;
  }
  if (e.Status == GestureStatus.Running) {
    // Calculate the scale factor to be applied.
    currentScale += (e.Scale - 1) * startScale;
    currentScale = Math.Max (1, currentScale);

    // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
    // so get the X pixel coordinate.
    double renderedX = Content.X + xOffset;
    double deltaX = renderedX / Width;
    double deltaWidth = Width / (Content.Width * startScale);
    double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;

    // The ScaleOrigin is in relative coordinates to the wrapped user interface element,
    // so get the Y pixel coordinate.
    double renderedY = Content.Y + yOffset;
    double deltaY = renderedY / Height;
    double deltaHeight = Height / (Content.Height * startScale);
    double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;

    // Calculate the transformed element pixel coordinates.
    double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
    double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);

    // Apply translation based on the change in origin.
    Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
    Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0);

    // Apply scale factor.
    Content.Scale = currentScale;
  }
  if (e.Status == GestureStatus.Completed) {
    // Store the translation delta's of the wrapped user interface element.
    xOffset = Content.TranslationX;
    yOffset = Content.TranslationY;
  }
}

이 메서드는 사용자의 손가락 모으기 제스처에 따라 래핑된 사용자 인터페이스 요소의 확대/축소 수준을 업데이트합니다.This method updates the zoom level of the wrapped user interface element based on the user's pinch gesture. 손가락 모으기 제스처의 방향에서 적용되는 배율을 계산하도록 PinchGestureUpdatedEventArgs 인스턴스의 Scale, ScaleOriginStatus 속성의 값을 사용하여 수행됩니다.This is achieved by using the values of the Scale, ScaleOrigin and Status properties of the PinchGestureUpdatedEventArgs instance to calculate the scale factor to be applied at the origin of the pinch gesture. 그런 다음, 래핑된 사용자 요소는 손가락 모으기 제스처의 방향에서 해당 TranslationX, TranslationYScale 속성을 설정하여 계산된 값으로 확대/축소됩니다.The wrapped user element is then zoomed at the origin of the pinch gesture by setting its TranslationX, TranslationY, and Scale properties to the calculated values.