How to make zoomable scrollview?
Asked Answered
J

2

19

In my android application I need to create activities zoom able. I found useful code for zooming linear layout here . But in my application couple of activities start with scrollview and this code does not recognize scrollview. How can I make pinch zoom for scrollable activity? This is one of my layout.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scrollViewZoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" >

<LinearLayout
    android:id="@+id/wd_content"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:orientation="vertical" >

    <!-- Start Circle -->

    <TableRow
        android:id="@+id/row_circl1"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_marginTop="30dp"
        android:background="@color/purple_color" >

        <RelativeLayout
            android:id="@+id/circle_layout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_engin_circle1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_engin_bg"
                android:contentDescription="TODO" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/circle_layout2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_engin_circle2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_engin_bg"
                android:contentDescription="TODO" />
        </RelativeLayout>
    </TableRow>

    <TableRow
        android:id="@+id/row_name_circle"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_marginTop="30dp" >

        <RelativeLayout
            android:id="@+id/circle_name_layout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="-15dp"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_name_circle1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_gauge_name"
                android:contentDescription="TODO" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/circle_name_layout2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="-15dp"
            android:background="@color/white_color" >

            <ImageView
                android:id="@+id/img_name_circle2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="@drawable/circle_gauge_name"
                android:contentDescription="TODO" />
        </RelativeLayout>
    </TableRow>

    <!-- End Circle -->

</LinearLayout>

</ScrollView>

Any idea would help me. Thanks.

Jit answered 27/10, 2013 at 7:33 Comment(2)
Please check this link: [enabling-zoom-on-scroll-view][1] good luck. [1]: #18572514Dietsche
Thanks for reply @Dietsche but I found another solution.Jit
J
30

Ok. After plowing the net, finally found my answer. I found onTouchEvent() for scrollview does not work so I have to use dispatchTouchEvent() instead of onTouchEvent(). At the top you can see my xml code (in my question) an here is my Activity code of course with comments.

    // step 1: add some instance
private float mScale = 1f;
private ScaleGestureDetector mScaleDetector;
GestureDetector gestureDetector;

//step 2: create instance from GestureDetector(this step sholude be place into onCreate())
gestureDetector = new GestureDetector(this, new GestureListener());

// animation for scalling
mScaleDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener() 
    {                                   
        @Override
        public boolean onScale(ScaleGestureDetector detector) 
        {
            float scale = 1 - detector.getScaleFactor();

            float prevScale = mScale;
            mScale += scale;

            if (mScale < 0.1f) // Minimum scale condition:
                mScale = 0.1f;

            if (mScale > 10f) // Maximum scale condition:
                mScale = 10f;
            ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1f / prevScale, 1f / mScale, detector.getFocusX(), detector.getFocusY());
            scaleAnimation.setDuration(0);
            scaleAnimation.setFillAfter(true);
            ScrollView layout =(ScrollView) findViewById(R.id.scrollViewZoom);
            layout.startAnimation(scaleAnimation);
            return true;
        }
    });


// step 3: override dispatchTouchEvent()
 @Override
 public boolean dispatchTouchEvent(MotionEvent event) {
    super.dispatchTouchEvent(event);
    mScaleDetector.onTouchEvent(event);
    gestureDetector.onTouchEvent(event);
    return gestureDetector.onTouchEvent(event);
 }

//step 4: add private class GestureListener

private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        // double tap fired.
        return true;
    }
}

Thanks a lot.

Jit answered 28/10, 2013 at 6:12 Comment(9)
Another life saved ! Another beer guaranteed here in Brazi!Pinette
Its showing only the pinch zoom, not scrolling when i Implemented.Interstitial
Can you please explain where i need to use this? I create a custom class extending Scrollview and put above code in that class. but it is giving init exceptionThere
may be my life save tooTonguelash
Useful to an extent, but what's up with your onScale method? Why not just use the one described by the docs? Inverting the scale so that greater values are zoomed out is... weird. developer.android.com/training/gestures/scale.htmlMastitis
can't scroll horizontallyBrigadier
Any solution for horizontal Move?Primal
Can't scroll horizontally and vertically!Gotha
Problem: when ever I just place 2 fingers on the screen it will already make a lot of zoom in, like it think I zoomed until my fingers place... any ideas on how to fix this?Tavish
S
9

Thanks for your solution, I implemented it a bit different because my scrollview is inside a fragment and not an activity, to delegate all the logic to the view I would recommend to add dispatchTouchEvent in the same custom scroll view:

package com.your.package;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.animation.ScaleAnimation;
import android.widget.ScrollView;

import com.your.package.R;

public class CustomZoomScrollView extends ScrollView {


    // step 1: add some instance
    private float mScale = 1f;
    private ScaleGestureDetector mScaleDetector;
    GestureDetector gestureDetector;


    public CustomZoomScrollView(Context context) {
        super(context);
    }

    public CustomZoomScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //step 2: create instance from GestureDetector(this step should be place into onCreate())
        gestureDetector = new GestureDetector(getContext(), new GestureListener());

        mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.SimpleOnScaleGestureListener()
        {
            @Override
            public boolean onScale(ScaleGestureDetector detector)
            {
                float scale = 1 - detector.getScaleFactor();

                float prevScale = mScale;
                mScale += scale;

                if (mScale < 0.1f) // Minimum scale condition:
                    mScale = 0.1f;

                if (mScale > 10f) // Maximum scale condition:
                    mScale = 10f;
                ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1f / prevScale, 1f / mScale, detector.getFocusX(), detector.getFocusY());
                scaleAnimation.setDuration(0);
                scaleAnimation.setFillAfter(true);
                getRootView().findViewById(R.id.svSeats).startAnimation(scaleAnimation);
                return true;
            }
        });
    }

    // step 3: override dispatchTouchEvent()
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        super.dispatchTouchEvent(event);
        mScaleDetector.onTouchEvent(event);
        gestureDetector.onTouchEvent(event);
        return gestureDetector.onTouchEvent(event);
    }

//step 4: add private class GestureListener

    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
        // event when double tap occurs
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            // double tap fired.
            return true;
        }
    }
}
Squier answered 20/2, 2018 at 20:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.