Pinch-to-Zoom — mobil uygulamalarda kıstırma hareketini anlama

Yazar: IT Sectr Yayınlanma: 2026-02-27 Okuma süresi: 8 dk
Pinch-to-Zoom (parmak kıstırma), kullanıcının içeriği küçültmek veya büyütmek için ekranda iki parmağını birbirine yaklaştırdığı veya uzaklaştırdığı çoklu dokunmatik yakınlaştırma hareketidir. Bu hareket, mobil cihazlarda görüntüleri, haritaları, web sayfalarını ve belgeleri görüntülemek için fiili standart haline gelmiştir. Apple HIG ve Google Material Design'a göre, Pinch-to-Zoom, kullanıcıların görsel içerikle çalışan tüm uygulamalarda beklediği temel bir harekettir.

Anahtar Noktalar

  • Pinch-to-Zoom, mobil cihazlarda içeriği ölçeklendirmek için iki parmaklı çoklu dokunmatik harekettir.
  • iOS'te, işleme .began → .changed → .ended'in sürekli izlenmesiyle UIPinchGestureRecognizer aracılığıyla yapılır.
  • Android, Matrix aracılığıyla yakınlaştırmayı güncellemek için onScale geri aramasıyla ScaleGestureDetector'u (Support Library'den) kullanır.
  • UIPinchGestureRecognizer, scale (önceki duruma göre oran) ve velocity (hız) özelliklerine sahiptir.
  • Yakınlaştırmayı sınırlamak için, belirtilen min/max değerleri (genellikle 0.5–3.0) arasında ölçek faktörünün bir kıskacı uygulanır.

Pinch-to-Zoom Nedir?

Pinch-to-Zoom (kıstırma), görüntülenen içeriğin ölçeğini değiştirmek için iki parmak kullanan çoklu dokunmatik bir harekettir. Parmaklar birbirine yaklaştırıldığında (pinch close), ölçek azalır; uzaklaştırıldığında (pinch open), artar. Hareket süreklidir: sistem, parmaklar arasındaki mesafeyi gerçek zamanlı olarak izler ve ara olaylar üreterek uygulamanın ölçeği sorunsuz bir şekilde güncellemesine olanak tanır.

Hareketin mekaniği, iki dokunma noktası arasındaki mesafenin hesaplanmasına dayanır. iOS ve Android, Öklid mesafesini kullanır: sqrt((x2−x1)² + (y2−y1)²). Geçerli ölçek, mevcut mesafenin başlangıç mesafesine oranı olarak hesaplanır. Başlangıç mesafesi 100px ise ve 150px olursa — ölçek = 1.5 (%50 artış). iOS, önceki duruma göre ölçeği (delta) iletir, Android ise ScaleGestureDetector aracılığıyla birikimli ölçeği iletir.

Google Material Design Guidelines'a göre, Pinch-to-Zoom, görüntü, harita veya belge görüntüleyen uygulamalar için zorunludur. IT Sectr'de, görsel içerikle çalışan tüm projelerde — galerilerden görüntü düzenleyicilere kadar — bu hareketi UIPinchGestureRecognizer ve ScaleGestureDetector ile uyguluyoruz.

iOS'te Pinch-to-Zoom: UIPinchGestureRecognizer

UIPinchGestureRecognizer, kıstırma hareketini tanımak için UIGestureRecognizer'ın sürekli bir alt sınıfıdır. Ayrık tanıyıcıların (UITapGestureRecognizer) aksine, bir olay dizisi üretir: .began (parmaklar ekrana dokunur), .changed (parmakların her hareketi), .ended (parmaklar kaldırılır).

Temel özellikler: scale (CGFloat) — hareketin başlangıcından bu yana parmaklar arasındaki mesafedeki göreceli değişim; velocity (CGFloat) — saniye başına ölçek değişim oranı. Başlangıç ölçeği = 1.0. Parmaklar uzaklaştırıldığında, ölçek artar (1.0 → 1.5 → 2.0); yaklaştırıldığında azalır (1.0 → 0.8 → 0.5). velocity özelliği atalet için kullanılır: .ended'den sonra, yavaşlamayla birlikte sürekli ölçeklendirmeyi canlandırabilirsiniz.

UIPinchGestureRecognizer, diğer tanıyıcılarla (haritada pan + pinch gibi) eşzamanlı tanıma için delegate özelliğini destekler. gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) yöntemi true döndürür ve her iki hareket paralel olarak çalışır. Apple, tek tek öğeler yerine kapsayıcı görünüme UIPinchGestureRecognizer eklenmesini önerir — bu, ölçeklendirme pivot noktasının hesaplanmasını basitleştirir.

Android'de Pinch-to-Zoom: ScaleGestureDetector

ScaleGestureDetector, çoklu dokunmatik ölçeklendirmeyi tanımak için tasarlanmış Android Support Library (android.view) sınıfıdır. GestureDetector.onFling'in aksine, ScaleGestureDetector özellikle iki parmaklı yakınlaştırma için oluşturulmuştur ve otomatik olarak focusX, focusY (parmaklar arasındaki merkez noktası) ve scaleFactor'u (önceki olaydan ölçek deltası) hesaplar.

ScaleGestureDetector, üç yöntemi olan OnScaleGestureListener arayüzü aracılığıyla çalışır: onScaleBegin(detector) (.began'a benzer), onScale(detector) (.changed'a benzer, boolean döndürür — ölçek kabul edilirse true), onScaleEnd(detector) (.ended'e benzer). Özellikler: scaleFactor — önceki olaya göre ölçek çarpanı (yavaş uzaklaştırma için ~1.01), focusX/focusY — parmaklar arasındaki merkez noktasının koordinatları.

Bir View'a ölçeklendirme uygulamak için genellikle Matrix kullanılır: view.imageMatrix.postScale(scaleFactor, scaleFactor, focusX, focusY). Matrix, dönüşümlerin birikimini destekler — her postScale çağrısı, mevcut dönüşüme yeni bir dönüşüm ekler. Hatırlanması önemlidir: ScaleGestureDetector, minimum/maksimum ölçeği sınırlamaz — bu geliştiricinin sorumluluğudur. IT Sectr'de, özel ölçek sınırları (0.5–3.0) ve aşılması durumunda geri dönüş animasyonu ile ScaleGestureDetector kullanıyoruz.

Yakınlaştırma Sınırlaması ve Pivot Noktası

Pinch-to-Zoom uygulanırken, minimum ve maksimum ölçeği sınırlamak son derece önemlidir — bu olmadan, kullanıcı sonsuza kadar yakınlaştırabilir veya görünmez olana kadar uzaklaştırabilir. Standart değerler: min = 0.5 (orijinal boyutun %50'si), max = 3.0 (%300). iOS'te, sınırlama kıskaç yoluyla yapılır: newScale = min(max(currentScale * gesture.scale, minScale), maxScale). Android'de — postScale'den sonra kontrol yoluyla.

Pivot noktası, ölçeklendirmenin gerçekleştirildiği parmaklar arasındaki merkez noktasıdır. iOS, iki dokunuşun ağırlık merkezini otomatik olarak hesaplar ve location(in:) aracılığıyla iletir — geliştiricinin pivotu manuel olarak hesaplaması gerekmez. Android, ScaleGestureDetector'da focusX/focusY sağlar, ancak Matrix aracılığıyla uygulanırken pivot, postScale(scaleFactor, scaleFactor, focusX, focusY) içinde üçüncü ve dördüncü argüman olarak iletilir. Pivot noktası olmadan, ölçeklendirme sol üst köşeye (0,0) göre gerçekleştirilir ve bu da yakınlaştırma sırasında içeriğin kaymasına neden olur.

IT Sectr'ın deneyimine göre, doğru pivot noktası hesaplaması, Pinch-to-Zoom uygulanırken en yaygın hata kaynağıdır. Vakaların %90'ında, GestureRecognizer ve ScaleGestureDetector'ın yerleşik koordinatlarını kullanmak yeterlidir — pivotu manuel olarak hesaplamaya gerek yoktur. Ölçeklendirme sırasında içerik kayıyorsa, focusX/focusY'yi matrix.postScale()'a ilettiğinizi kontrol edin.

Yakınlaştırmadan Sonra Atalet

Hareket sona erdikten sonra sorunsuz bir kullanıcı deneyimi için atalet ekleyebilirsiniz: iOS'te — UIView.animate ve yay parametreleriyle UIPinchGestureRecognizer'dan velocity kullanın; Android'de — OverScroller veya ValueAnimator. Atalet, min/max ölçek sınırlarını aşmamalıdır — sınır aşıldığında nihai değer, yay dönüş animasyonuyla kesilir.

Swift ve Kotlin'de Kod Örnekleri

Örnek 1: iOS'te Pinch-to-Zoom (Swift)

0.5 ila 3.0 arasında ölçek sınırlamasıyla UIImageView'a UIPinchGestureRecognizer ekler. Birikimli ölçeği koruyan minimum bir uygulama gösterir.

swift
import UIKit

class ZoomableImageViewController: UIViewController {

    @IBOutlet private var imageView: UIImageView!
    private var currentScale: CGFloat = 1.0
    private let minScale: CGFloat = 0.5
    private let maxScale: CGFloat = 3.0

    override func viewDidLoad() {
        super.viewDidLoad()

        let pinch = UIPinchGestureRecognizer(
            target: self,
            action: #selector(handlePinch(_:))
        )
        imageView.addGestureRecognizer(pinch)
        imageView.isUserInteractionEnabled = true
    }

    @objc private func handlePinch(_: UIPinchGestureRecognizer) {
        if gestureRecognizer.state == .began
            || gestureRecognizer.state == .changed {

            let newScale = currentScale * gestureRecognizer.scale
            imageView.transform = CGAffineTransform(
                scaleX: min(max(newScale, minScale), maxScale),
                y: min(max(newScale, minScale), maxScale)
            )
        }
        if gestureRecognizer.state == .ended {
            currentScale = min(max(
                currentScale * gestureRecognizer.scale,
                minScale
            ), maxScale)
            gestureRecognizer.scale = 1.0
        }
    }
}

Mantık: .began/.changed'te, ölçek kıskaçlı CGAffineTransform aracılığıyla uygulanır. .ended'te, ölçek 1.0'a sıfırlanır ve birikimli değer currentScale'de saklanır. Bu, tekrarlanan hareketler sırasında ölçek kaymasını önler — her yeni hareket mevcut durumdan başlar. Görüntüler için, CGAffineTransform yerine minimumZoomScale/maximumZoomScale ile UIScrollView önerilir.

Örnek 2: Android'de Pinch-to-Zoom (Kotlin)

Matrix ile ScaleGestureDetector aracılığıyla ImageView ölçeklendirmesini uygular. Doğru pivot noktası işlemesini ve ölçek sınırlamasını gösterir.

kotlin
import android.content.Context
import android.graphics.Matrix
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.widget.ImageView

class PinchZoomImageView(context: Context) : ImageView(context) {

    private val matrix = Matrix()
    private var currentScale = 1f
    private val minScale = 0.5f
    private val maxScale = 3.0f

    private val scaleDetector =
        ScaleGestureDetector(context, ScaleListener())

    private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            currentScale = (currentScale * detector.scaleFactor)
                .coerceIn(minScale, maxScale)
            matrix.postScale(
                currentScale,
                currentScale,
                detector.focusX,
                detector.focusY
            )
            imageMatrix = matrix
            return true
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        scaleDetector.onTouchEvent(event)
        return true
    }
}

Özel ImageView, onTouchEvent'i geçersiz kılar ve olayları ScaleGestureDetector'a iletir. OnScaleListener.onScale(), her parmak hareketinde çağrılır. detector.scaleFactor deltadır (yavaş uzaklaştırma için 1.01). currentScale, kıskaçlama için coerceIn ile birikir. focusX/focusY — parmaklar arasındaki merkez noktası, doğru pivot ölçeklendirmesi için postScale'e iletilir.

Örnek 3: Yakınlaştırma Destekli UIScrollView (iOS)

UIScrollView, temsilcisi aracılığıyla yerleşik Pinch-to-Zoom desteğine sahiptir. Bu, görüntüler ve belgeler için tercih edilen yaklaşımdır — ScrollView, ölçeği, ataleti ve kaydırmayı otomatik olarak yönetir.

swift
class ScrollableImageViewController: UIViewController,
                                    UIScrollViewDelegate {

    @IBOutlet private var scrollView: UIScrollView!
    @IBOutlet private var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.minimumZoomScale = 0.5
        scrollView.maximumZoomScale = 3.0
        scrollView.delegate = self
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imageView
    }
}

UIScrollView otomatik olarak bir UIPinchGestureRecognizer oluşturur, CALayer dönüşümü aracılığıyla ölçeklendirmeyi yönetir ve sınırlar aşıldığında sıçrama efekti ekler. Kod, min/maxZoomScale ayarlamaya ve viewForZooming döndürmeye indirgenir. IT Sectr'de, tüm tam ekran görüntüler için UIScrollView kullanıyoruz — bu, UIPinchGestureRecognizer aracılığıyla manuel uygulamaya kıyasla kod hacmini 5 kat azaltır.

Sıkça Sorulan Sorular

Parmak kıstırma, izleme dörtgenindeki kıstırmadan nasıl farklıdır?

Dokunmatik ekranda, kıstırma aralarındaki mesafe izlemesiyle iki parmak kullanır. MacBook izleme dörtgeninde, yakınlaştırma aynı durumlarla (.began → .changed → .ended) UIPinchGestureRecognizer aracılığıyla uygulanır, ancak dokunma kaynağı kapasitif bir ekran değil, Force Touch'lı bir izleme dörtgenidir. API aynıdır, mekanik aynıdır.

Minimum ve maksimum yakınlaştırma nasıl sınırlanır?

iOS'te: UIPinchGestureRecognizer'dan ölçeği aldıktan sonra currentScale ile çarpın ve clamp(min: 0.5, max: 3.0) uygulayın. Android'de: matrix.postScale()'den önce coerceIn(minScale, maxScale) kullanın. UIScrollView'de — minimumZoomScale ve maximumZoomScale özellikleri aracılığıyla. Sınırlama olmadan, ölçek sonsuza veya sıfıra gidebilir.

Pinch-to-Zoom tek parmakla çalışır mı?

Hayır, kıstırma en az iki parmak gerektirir. Tek parmaklı yakınlaştırma için (çift dokunma + yukarı/aşağı sürükleme), UIPanGestureRecognizer veya GestureDetector.onScroll aracılığıyla özel bir uygulama gerekir. Bu, farklı mantığa sahip farklı bir harekettir — genellikle kamera veya haritalarda yakınlaştırma için kullanılır.

Özet

  • Pinch-to-Zoom, içeriği ölçeklendirmek için iki parmaklı çoklu dokunmatik harekettir, görüntüler, haritalar ve belgeler için standarttır.
  • iOS'te UIPinchGestureRecognizer, scale (delta) ve velocity (hız) ile sürekli bir tanıyıcıdır.
  • Android'de ScaleGestureDetector, pivot noktası için onScale(), focusX/focusY ile özelleşmiş bir dedektördür.
  • UIScrollView için yakınlaştırma, minimumZoomScale/maximumZoomScale aracılığıyla yerleşiktir — manuel uygulamadan daha basittir.
  • Ölçeği her zaman kıskaçla (0.5–3.0) sınırlayın — bu olmadan içerik görünmez hale gelebilir.
  • Ölçeklendirme pivot noktası parmaklar arasındaki merkezdir; bu olmadan içerik yakınlaştırma sırasında kayar.
  • IT Sectr'de, görüntüler için UIScrollView ve düzenleyiciler için özel ScaleGestureDetector kullanıyoruz — seçim, dönüşümlerin karmaşıklığına bağlıdır.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun