I am trying to create a ViewGroup that supports panning and scaling of its contents. All I could find on the Internet were ideas and implementations that could be done in ImageView, but not in the container. I want to display a map, and in addition, I want to display several markers, which are ImageButtons, so the user can use them for more information. This is achieved on iOS using UIScrollView, but I could not find an alternative on Android.
I decided to use FrameView, so I could set ImageView with the image as a background, and on top of it add RelativeLayout, on which I could add ImageButtons and put them using fields.
I borrowed part of the TouchImageView implementation here , but I ran into complications. I started with panning, and I partially succeeded, it pans around the container, but panning works terribly, it is very exciting. Here is my code:
public class ScrollingViewGroup extends FrameLayout {
private int x = 0;
private int y = 0;
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
PointF last = new PointF();
PointF start = new PointF();
public ScrollingViewGroup(Context context) {
super(context);
sharedConstructing(context);
}
public ScrollingViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
sharedConstructing(context);
}
private void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
Log.d("ScrollingViewGroup", Float.toString(deltaX));
Log.d("ScrollingViewGroup", Float.toString(deltaY));
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
x += deltaX;
y += deltaY;
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setTranslationX(x);
setTranslationY(y);
invalidate();
return true;
}
});
}
Any ideas are greatly appreciated.
edit: jitter seems to be the reason because when moving deltaX and deltaY alternate between positive and negative numbers, the LogCat check ... is still not sure why. This is caused by a current variable that gives different values each time, but instead of being consistent, they look as if the finger will move back and forth, and not just forward. For example, instead of curr.x equal to 0,1,2,3,4 etc., it is 0,1,0,5,2,1,5 etc. Not sure why.