Giới thiệu
Bài viết này hướng dẫn cách triển khai chức năng zoom ảnh (pinch-to-zoom) trên Android sử dụng ScaleGestureDetector. Đây là cách cơ bản, phù hợp cho zoom đơn giản. Đối với ứng dụng thực tế (xem ảnh lớn, pan/zoom mượt), nên dùng thư viện như PhotoView hoặc TouchImageView.
Các bước thực hiện
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.
Bước 2: Thiết kế giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="@drawable/your_image"
android:contentDescription="Zoomable image" />
</FrameLayout>
Bước 3: Viết code zoom (src/MainActivity.java)
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Matrix;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private ScaleGestureDetector scaleGestureDetector;
private Matrix matrix = new Matrix();
private float scaleFactor = 1f;
private float minScale = 1f;
private float maxScale = 10f;
private float focusX, focusY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.imageView);
imageView.setScaleType(ImageView.ScaleType.MATRIX);
scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Để pan (kéo) hoạt động, cần xử lý touchevent phức tạp hơn
// Ở đây chỉ demo zoom đơn giản
scaleGestureDetector.onTouchEvent(event);
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(minScale, Math.min(scaleFactor, maxScale));
// Zoom tại điểm giữa hai ngón tay (focus point)
focusX = detector.getFocusX();
focusY = detector.getFocusY();
matrix.setScale(scaleFactor, scaleFactor, focusX, focusY);
imageView.setImageMatrix(matrix);
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true; // Bắt đầu gesture zoom
}
}
}
Bước 4: Cấu hình Manifest (androidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Chạm hai ngón tay vào ảnh và pinch (thu/phóng) để zoom.
Hạn chế của cách này
- Chỉ hỗ trợ zoom, không hỗ trợ pan (kéo di chuyển ảnh khi đã zoom).
- Không giới hạn biên (ảnh có thể zoom ra khỏi màn hình).
- Không có animation mượt mà khi double-tap zoom.
- Xử lý touch event phức tạp khi kết hợp pan + zoom.
Giải pháp hoàn chỉnh: Custom TouchImageView
public class TouchImageView extends AppCompatImageView {
// ... implementation đầy đủ: pan, zoom, double-tap, fling, bounds checking ...
// Xem thư viện: https://github.com/MikeOrtiz/TouchImageView
}
Thư viện khuyên dùng (Production-ready)
| Thư viện | Tính năng chính | Dependency |
|---|---|---|
| PhotoView (Chris Banes) | Zoom, pan, double-tap, fling, animation, transition | implementation 'com.github.chrisbanes:PhotoView:2.3.0' |
| TouchImageView (Mike Ortiz) | Single file, nhẹ, pan/zoom/double-tap cơ bản | Copy file java vào project |
| ImageViewer | Full-screen image viewer với zoom, share, download | implementation 'com.github.siyamed:android-shape-imageview:0.9.3@aar' |
Ví dụ dùng PhotoView
<!-- Layout -->
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/photoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
// Code
PhotoView photoView = findViewById(R.id.photoView);
photoView.setImageResource(R.drawable.your_image);
// Tự động hỗ trợ pinch-zoom, double-tap, pan, fling
Lưu ý quan trọng
android:scaleType="matrix"bắt buộc để Matrix transform hoạt động.- Đối với ảnh lớn (high-res), cân nhắc dùng
BitmapRegionDecoderhoặcSubsamplingScaleImageView(Dave Morrissey) để tránh OOM. - Luôn test trên thiết bị thật - emulator multi-touch محدود.
- Xử lý orientation change: lưu/restore matrix state.