'Zoom in & out , and scroll or fling only framelayout

I'm going to implement gesturedetector. I'm noob about. I've this layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/sfondo_old"
    tools:context=".activities.Board1">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusableInTouchMode="true">

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar_menu_disegno"
            android:visibility="gone" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:orientation="vertical"
            android:weightSum="2">


          <FrameLayout
                android:id="@+id/frameLayout"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1.99"> -->


                <!-- IMAGE LOADED -->

                <ImageView
                    android:id="@+id/area_campo"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/campo1"
                    />

                <!-- CUSTOM DRAWING VIEW -->

                <it.colan.matchup.ui.component.DrawingView
                    android:id="@+id/area_disegno"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />

                    </FrameLayout>


           <!-- </FrameLayout> -->

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/area_disegno"
                android:layout_weight="0.01"
                android:orientation="horizontal"
                android:weightSum="1">

                <include
                    android:id="@+id/strumenti"
                    layout="@layout/menu_strumenti"

                    android:layout_alignParentLeft="true"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:orientation="horizontal"
                    android:gravity="center"
                    android:background="@color/black"
                    />



            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

And i've tried to apply gesture detector here but when i try scale with gesture it work if i touch on external framelayout but when scale inside framelayout not work. Why?

This is my Board1 Activity code (removed button click listener and other) :

public class Board1 extends AppCompatActivity {

    
    private DrawingView areaDisegno; // for drawing
    private ImageView areaCampo; // image behind drawing
 
    private FrameLayout frameLayout; // all entire layout which can zoom and scroll for moving around 
 

    private int mCurrentBackgroundColor;
    private int mCurrentColor;
    private int mCurrentStroke;
    private static final int MAX_STROKE_WIDTH = 50;
 

    private ScaleGestureDetector mScaleGestureDetector;
    private GestureDetector mGestureDetector;

    private float mScaleFactor = 1.0f;

    public boolean onTouchEvent(MotionEvent motionEvent) {
            mScaleGestureDetector.onTouchEvent(motionEvent);
            mGestureDetector.onTouchEvent(motionEvent);
            return true;
    }

    private class GestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

            return super.onScroll(e1, e2, distanceX, distanceY);
        }



    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector scaleGestureDetector){

            if(!zoomBloccato) {
                mScaleFactor *= scaleGestureDetector.getScaleFactor();
                Log.d("DEBUG", "Board 1 - Scalefactor " + mScaleFactor);
                mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
                frameLayout.setScaleX(mScaleFactor);
                frameLayout.setScaleY(mScaleFactor);
            }
            return true;
        }


    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().setNavigationBarColor(getResources().getColor(R.color.black));
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_board1);

        mScaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());
        mGestureDetector = new GestureDetector(this, new GestureListener());

        ActivityCompat.requestPermissions(Board1.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                EXTERNAL_STORAGE_PERMISSION_CODE);
 

        areaDisegno = findViewById(R.id.area_disegno);
        areaCampo = findViewById(R.id.area_campo);
        frameLayout = findViewById(R.id.frameLayout);
        
        inizializzaAreaDisegno();

        mCurrentColor = Color.BLACK;

        areaDisegno.setPaintColor(mCurrentColor);

        
        mCurrentStroke = 30;

        areaDisegno.setPaintStrokeWidth(mCurrentStroke);

        areaDisegno.setDisegnoAbilitato(true);
       

    }

    

    private void inizializzaAreaDisegno()
    {

        //   mCurrentBackgroundColor = ContextCompat.getColor(this, android.R.color.white);
        mCurrentColor = ContextCompat.getColor(this, android.R.color.black);
        mCurrentStroke = 10;

        areaDisegno.setBackgroundColor(mCurrentBackgroundColor);
        areaDisegno.setBackgroundColor(mCurrentColor);
        areaDisegno.setPaintStrokeWidth(mCurrentStroke);

    }
 
}

I've tried but not work on only framelayout. I must only zoom in and zoom out and scrolling around when zoomed in but not work :(. Thanks Cris



Solution 1:[1]

You can use below code for zoom in, out with scroll

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;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sumit Kumar