5

I have a problem: my custom listview doesn't scroll before zooming. Zooming working as expected. How I can to fix this problem?

ZoomableListView:

public class ZoomableListView extends ListView {

private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
private boolean isPagerEnabled;
private static final int INVALID_POINTER_ID = -1;

// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;

private float mPosX;
private float mPosY;

private float mLastTouchX;
private float mLastTouchY;

// Pivot point for Scaling
static float gx = 0, gy = 0;

public ZoomableListView(Context context, AttributeSet attrs) {
super(context, attrs);
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}

public ZoomableListView(Context context) {
super(context);
mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
}

@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
canvas.restore();
}


@Override
protected void dispatchDraw(Canvas canvas) {
// Save the canvas to set the scaling factor returned from detector
canvas.save(Canvas.MATRIX_SAVE_FLAG);
if (mScaleFactor == 1.0f) {
    isPagerEnabled = true;
} else {
    isPagerEnabled = false;
}

if (mScaleFactor == 1.0f) {
    mPosX = 0.0f;
    mPosY = 0.0f;
}
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
invalidate();
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
mScaleDetector.onTouchEvent(ev);
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
    final float x = ev.getX();
    final float y = ev.getY();

    mLastTouchX = x;
    mLastTouchY = y;

    // Save the ID of this pointer
    mActivePointerId = ev.getPointerId(0);
    break;
}

case MotionEvent.ACTION_MOVE: {
    // Find the index of the active pointer and fetch its position
    final int pointerIndex = ev.findPointerIndex(mActivePointerId);
    final float x = ev.getX(pointerIndex);
    final float y = ev.getY(pointerIndex);

    final float dx = x - mLastTouchX;
    final float dy = y - mLastTouchY;

    mPosX += dx;
    mPosY += dy;

    mLastTouchX = x;
    mLastTouchY = y;

    invalidate();
    break;
}

case MotionEvent.ACTION_UP: {
    mActivePointerId = INVALID_POINTER_ID;
    break;
}

case MotionEvent.ACTION_CANCEL: {
    mActivePointerId = INVALID_POINTER_ID;
    break;
}

case MotionEvent.ACTION_POINTER_UP: {
    // Extract the index of the pointer that left the touch sensor
    final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
    final int pointerId = ev.getPointerId(pointerIndex);
    if (pointerId == mActivePointerId) {
    // This was our active pointer going up. Choose a new
    // active pointer and adjust accordingly.
    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
    mLastTouchX = ev.getX(newPointerIndex);
    mLastTouchY = ev.getY(newPointerIndex);
    mActivePointerId = ev.getPointerId(newPointerIndex);
    }
    break;
}
}

return true;
}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
    mScaleFactor *= detector.getScaleFactor();

    // Don't let the object get too small or too large.
    mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f));

    invalidate();
    return true;
}
}

}

Here is the XML of custom listview:

<com.android.app.core.view.ZoomableListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="40dp"
    android:divider="@android:color/darker_gray"
    android:dividerHeight="1dp" >
</com.android.app.core.view.ZoomableListView>

Thank's for any answers.

ricky
  • 135
  • 1
  • 2
  • 7
  • you are returning true in `onTouchEvent`. This means you have handled the touch event, so the parent won't try to handle it any more. – bogdan Jan 09 '14 at 10:20
  • sorry, I meant that listview doesn't scroll before zooming – ricky Jan 09 '14 at 10:35
  • @ricky this zooms the listview from top left corner. Can we controll this? this should zoom the view from the mid point of two fingers. in short this should zoom the view at the pinch position – Qadir Hussain Jul 30 '15 at 06:08
  • http://stackoverflow.com/questions/32242187/how-to-zoom-list-item-from-center-of-pinch – Qadir Hussain Aug 27 '15 at 17:41

2 Answers2

5

Add super.onTouchEvent(ev);. I tried this out to confirm it worked:

@Override
public boolean onTouchEvent(MotionEvent ev) {
    super.onTouchEvent(ev);
    ...
Mike Ortiz
  • 4,031
  • 4
  • 27
  • 54
  • 1
    You need some polish around the edge detection but it is a very nice class! You should check out my project, [TouchImageView](https://github.com/MikeOrtiz/TouchImageView). It may help with your edge detection code. – Mike Ortiz Jan 09 '14 at 10:39
  • 2
    Another note, in your onScale, you should grab the focus point of the scale, with `detector.getFocusX();` and `detector.getFocusY()`. Then, use that focus point to scale your canvas when you are pinch zooming. This will make the view appear to scale more naturally. – Mike Ortiz Jan 09 '14 at 10:47
  • 1
    Thanks, I added detector.getFocusX(); and detector.getFocusY(). After this my view actually appear to scale more naturally) – ricky Jan 09 '14 at 10:59
  • @ricky Would you mind posting your final solution for future Googlers? Nice work! – spitzanator Apr 28 '14 at 19:33
  • yes, it's make sense)I will post my solution on the GitHub – ricky Jul 25 '14 at 09:17
  • @ricky where is the Github link? please share – Qadir Hussain Jul 23 '15 at 06:38
  • @MikeOrtiz please Post your comment in code, I am not getting this. How should I grab the focus point of the scale,? please explain and share code – Qadir Hussain Jul 23 '15 at 06:39
  • @MikeOrtiz http://stackoverflow.com/questions/32242187/how-to-zoom-list-item-from-center-of-pinch – Qadir Hussain Aug 27 '15 at 17:42
1

please add these lines

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
    return true;
}

have a try with this

<com.android.app.core.view.ZoomableListView
    android:id="@android:id/list"
     android:layout_width="fill_parent"
            android:layout_height="fill_parent" 
    android:layout_marginBottom="40dp"
    android:divider="@android:color/darker_gray"
    android:dividerHeight="1dp" >
</com.android.app.core.view.ZoomableListView>
Jitesh Upadhyay
  • 5,244
  • 2
  • 25
  • 43