2

I've implemented zoom and pan/drag functionality in my custom relative layout successfully with the help of following links.

1). An excellent tutorial - making-sense-of-multitouch

2). (SO link) Extending RelativeLayout, and overriding dispatchDraw() to create a zoomable ViewGroup

3). (SO link) Scroll/Panning or drag in custom layout

Here's my full working code.

https://gist.github.com/pandeyGitHub/6805840 .

and my layout.xml looks like this:-

<com.myzoomproject.views.ZoomableRelativeLayout
    android:id="@+id/root_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.myzoomproject.views.CustomViewPager
        android:id="@+id/pager_test2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</com.myzoomproject.views.ZoomableRelativeLayout>

My Custom relative layout contains a viewpager and each single page in my viewpager contains 2-4 imageviews (one fullscreen imageview & a couple of clickable smaller imageviews). Zooming & panning the page works just fine.

Problem 1: But somehow I'm not able to set boundary limits for panning functionality. The page would pan off the screen on overscrolling.

Problem 2: Also, it seems that image-views are panned/translated only in drawing but not in actuality. because they are not clickable anymore the moment they move away from their original position on screen, & the clickable-coordinates remains confined to their original positions only.

I looked up several similar questions on SO link 1, link 2, link 3 but they all are based on ImageView zoom and not the custom-layout zoom.

So unlike them, I do not have a reference to my imageviews in my ZoomableRelativeLayout. Referencing the Imageviews, reading the bitmaps & displaying them is taken care of by other classes (MyPagerActivity & MyPagerFragment classes). Also, the solution in above mentioned links relies on matrix transformation, which i probably cannot use in my case.

Looking forward to any help on this.

Thanks.

Community
  • 1
  • 1
epiphany27
  • 517
  • 1
  • 10
  • 23

3 Answers3

0

You need to put min/max limits on the mPosX & mPosY positions - do this after adding dx & dy.

To work out what limits to apply you could get the child View's size using getWidth() and getHeight(), and factor in the current scale.

nmw
  • 6,664
  • 3
  • 31
  • 32
0

I've somehow found a workaround to this by some hooks, which is far from being a perfect solution, since I had to hard-code some values. I've added the following code-snippet in my existing code to set the boundary limits to panning. Now the panning works fine.

Logging the mClipBound.top, bottom, left, right values I came up with the following hard-coded values which might work only for 720x1280 & 800x1280 devices.

case MotionEvent.ACTION_MOVE: {
    ...
    ...

    if (isPortraitMode) {
        if (mClipBound.top < 104 && dy > 0) //104 is a hard-coded value here.
           dy = 0;

        if (mClipBound.bottom > (screenHeight - 77) && dy < 0) // 77 - hardcoded
           dy = 0;
    } else {
        if (mClipBound.top < 0 && dy > 0)
            dy = 0;
        if (mClipBound.bottom > screenHeight && dy < 0)
        dy = 0;

    }

    if (mClipBound.left < 30 && dx > 0) // 30 - hardcoded
        dx = 0;

    if (mClipBound.right > screenWidth && dx < 0)
        dx = 0;

    mPosX += dx;
    mPosY += dy;
        ...
        ...
        ...
 }

 ...
 ...


 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    screenWidth = widthSize;
    screenHeight = heightSize;
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension((int) (widthSize), (int) (heightSize ));
 }

But still i haven't been able to resolve problem 2: mentioned in my question above. Some proper adjustments in onMeasure(..) & onLayout(..) methods using mScaleFactor might resolve the issue. But i haven't been able to make it work yet.

epiphany27
  • 517
  • 1
  • 10
  • 23
0

For the problem 2, you have to resize the canvas rect of all your relativelayout´s children. You should do this in onScaleEnd method of your scalegesturedetector.

public void resizeChildren() {

    int childCount = this.getChildCount();

    for (int i = 0; i < childCount; i++) {

        MyView child = (MyView)this.getChildAt(i);
        child.setScaleFactor(mScaleFactor);
        child.setCanvasRect(mRect);


    }

}

setScaleFactor() and setCanvasRect() are methods for MyView which is a custom View I use for finger painting.