Panning and Zooming Images with CenterCrop in Android

41 Views Asked by At

I'm trying to implement a feature in my Android app where users can pan and zoom images within an ImageView that has its scaleType set to centerCrop and loading image by Glide into ImageView. The goal is to allow users to view the entire image, even though it may be larger than the ImageView itself. When the user lifts their finger, the image should smoothly snap back to its original position.

I've provided the XML code for the ImageView and the Java code for handling touch events, but the image is not moving or zooming. Can anyone help me fix the code so that the user can move image inside imageview to view complete center-crop image?

XML Code:

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:fillViewport="true"
    android:clickable="true"
    android:focusable="true"
    android:layout_height="match_parent"
    android:layout_width="match_parent">




<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/newPost_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="10dp"
    android:clickable="true"
    android:fitsSystemWindows="true"
    android:focusable="true"
    android:focusableInTouchMode="true">


    <ImageView
        android:id="@+id/newPost_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:minHeight="300dp"
        android:scaleType="centerCrop"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/newPost_statusText"

        />

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

Java Code:

preview.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                // Switch based on the touch event action
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN: // When finger is pressed down
                        // Save the current image transformation matrix
                        matrix.set(preview.getImageMatrix());
                        // Record the touch position for later calculation
                        lastTouchX = event.getX();
                        lastTouchY = event.getY();

                        // Set the active pointer ID for tracking subsequent moves
                        activePointerId = event.getPointerId(0);
                        break;

                    case MotionEvent.ACTION_MOVE: // When finger is moving
                        // Find the index of the active pointer
                        int pointerIndex = event.findPointerIndex(activePointerId);

                        // Check if the active pointer is still valid
                        if (pointerIndex != -1) {
                            // Calculate the difference between the current touch position and the previous touch position
                            float dx = event.getX(pointerIndex) - lastTouchX;
                            float dy = event.getY(pointerIndex) - lastTouchY;

                            // Apply the translation to the image transformation matrix
                            matrix.postTranslate(dx, dy);

                            // Update the image view with the transformed matrix
                            preview.setImageMatrix(matrix);

                            // Update the last touch position for the next move
                            lastTouchX = event.getX(pointerIndex);
                            lastTouchY = event.getY(pointerIndex);
                        }
                        break;

                    case MotionEvent.ACTION_UP: // When finger is lifted up
                        // Reset the active pointer ID
                        activePointerId = INVALID_POINTER_ID;

                        // Apply any remaining translation to the image view
                        preview.setImageMatrix(matrix);

                        break;

                    case MotionEvent.ACTION_POINTER_UP: // When a second finger is lifted up
                        // Find the index of the pointer that was lifted up
                        int pointerIndexUP = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                        int pointerId = event.getPointerId(pointerIndexUP);

                        // Check if the lifted pointer is the active pointer
                        if (pointerId == activePointerId) {
                            // Update the active pointer ID to the remaining finger
                            int newPointerIndex = pointerIndexUP == 0 ? 1 : 0;
                            lastTouchX = event.getX(newPointerIndex);
                            lastTouchY = event.getY(newPointerIndex);
                            activePointerId = event.getPointerId(newPointerIndex);
                        }
                        break;
                }

                return true;
            }
        });
0

There are 0 best solutions below