I have a HorizontalScrollView
in which there are multiple views inside it. I have implemented pinch zoom gesture
in which multiple views, which are between my two fingers, are scaled.
But I am facing one glitch. When I am doing pinch zoom, the mid point of pinch zoom is moving but for user experience I want this point to be remain fixed and other things should adjust itself while scaling so that mid point remains static.
Can someone tell me how to do it.
onDraw()
method of custom view is
Rect r =new Rect(0, 0, 700, 40);
public void onDraw(Canvas canvas) {
float kk=mScaleFactor; //this variable will be set by pinch zoom event and represent how much to scale
sf*=kk; // this view must scale according to previous scaling
canvas.save();
canvas.scale(sf , 1);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
canvas.drawRect(r, paint);
width=sf*700;
canvas.restore();
requestLayout(); //this will change view width to fit the expanded rectangle
}
onMeasure method is called on requestLayout
@Override protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
setMeasuredDimension((int)width, 340);
}
The above custom view is called 12 times by a subclass of HorizontalScrollView
. So there are 12 child views of HorizontalScrollview
.
In this class I am doing the following things
Detecting the touch coordinates of two fingers.
Calculating the index of child view on which first finger is touched.
Calculating the index of child view on which second finger is touched.
Passing scale factor of pinch zoom to all the child views between start and last. These two indices are calculated in previous two step.
And finally invalidate() is called on the child view. So child can scale itself according to scale factor passed by parent view.
But there is one problem here. The mid point of two finger should remain static and other things should adjust during scaling. But my mid point is moving with scaling.
Can someone help me in doing this. Please tell me if any part of code is require.
Code of gesture listener of HorizontalScrollview
is
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
ViewGroup pp=takeparent(); //give object of this class
for(int i=start;i<=last;i++)
{
LinearLayout ll=(LinearLayout)pp.getChildAt(i);
DrawView view=(DrawView)ll.findViewById(R.id.drawview);
view.mScaleFactor=mScaleFactor;
view.invalidate();
view.donesf=true;
}
Sample app of mine
Edits as suggested in comments:
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
ViewGroup pp=takeparent(); pp contains all the custom child views
//start and last are indices of range of child for which we have to apply gesture
for(int i=start;i<=last;i++)
{
LinearLayout ll=(LinearLayout)pp.getChildAt(i);
DrawView view=(DrawView)ll.findViewById(R.id.drawview);
view.mScaleFactor=mScaleFactor;
view.pivotx=detector.getFocusX()+view.getLeft();
view.pivoty=detector.getFocusY()+view.getTop();
view.invalidate();
}
return true;
}
This is custom view onDraw method
public void onDraw(Canvas canvas) {
sf=mScaleFactor //this scale factor is set by parent view
width=sf*700; //this width will be use to rescale the view's width in requestLayout()
canvas.save();
canvas.scale(sf,1,pivotx,pivoty); //pivotX and pivotY are also set by parent's onScale method of gestureListener
canvas.drawRect(r, paint);
requestLayout();
canvas.restore();
}